mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-23 16:09:11 +00:00
refactor: simple migrations and tweaks to cuesheet
This commit is contained in:
committed by
Carlos Valente
parent
c8c2a05724
commit
aefa4cbf44
@@ -20,6 +20,11 @@
|
|||||||
opacity: 0.4;
|
opacity: 0.4;
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:focus-visible {
|
||||||
|
outline: 2px solid $blue-500;
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.small {
|
.small {
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
.checkbox {
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: flex;
|
||||||
|
width: 1rem;
|
||||||
|
height: 1rem;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: $component-border-radius-sm;
|
||||||
|
|
||||||
|
&[data-unchecked] {
|
||||||
|
background-color: $gray-1100;
|
||||||
|
|
||||||
|
&:hover:not(:disabled) {
|
||||||
|
background: $gray-1000;
|
||||||
|
}
|
||||||
|
&:active:not(:disabled) {
|
||||||
|
background: $gray-1200;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&[data-checked] {
|
||||||
|
background-color: $blue-500;
|
||||||
|
|
||||||
|
&:hover:not(:disabled) {
|
||||||
|
background: $blue-400;
|
||||||
|
}
|
||||||
|
&:active:not(:disabled) {
|
||||||
|
background: $blue-600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
opacity: 0.4;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus-visible {
|
||||||
|
outline: 2px solid $blue-500;
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.indicator {
|
||||||
|
display: flex;
|
||||||
|
color: $ui-white;
|
||||||
|
|
||||||
|
&[data-unchecked] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import { IoCheckmark } from 'react-icons/io5';
|
||||||
|
import { Checkbox as BaseCheckbox } from '@base-ui-components/react/checkbox';
|
||||||
|
|
||||||
|
import style from './Checkbox.module.scss';
|
||||||
|
|
||||||
|
export default function Checkbox(checkboxProps: BaseCheckbox.Root.Props) {
|
||||||
|
return (
|
||||||
|
<BaseCheckbox.Root className={style.checkbox} {...checkboxProps}>
|
||||||
|
<BaseCheckbox.Indicator className={style.indicator}>
|
||||||
|
<IoCheckmark className={style.icon} />
|
||||||
|
</BaseCheckbox.Indicator>
|
||||||
|
</BaseCheckbox.Root>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
.input {
|
.input {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
|
||||||
background-color: $gray-1200;
|
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
color: $gray-200;
|
color: $gray-200;
|
||||||
@@ -31,6 +30,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.subtle {
|
||||||
|
background-color: $gray-1200;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ghosted {
|
||||||
|
background-color: transparent;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.medium {
|
.medium {
|
||||||
height: 2rem;
|
height: 2rem;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { cx } from '../../../utils/styleUtils';
|
|||||||
import style from './Input.module.scss';
|
import style from './Input.module.scss';
|
||||||
|
|
||||||
export interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
|
export interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
|
||||||
variant?: 'subtle';
|
variant?: 'subtle' | 'ghosted';
|
||||||
height?: 'medium' | 'large';
|
height?: 'medium' | 'large';
|
||||||
fluid?: boolean;
|
fluid?: boolean;
|
||||||
}
|
}
|
||||||
@@ -20,6 +20,7 @@ const Input = forwardRef<HTMLInputElement, InputProps>(function Input(
|
|||||||
type='text'
|
type='text'
|
||||||
autoCorrect='off'
|
autoCorrect='off'
|
||||||
autoComplete='off'
|
autoComplete='off'
|
||||||
|
spellCheck='false'
|
||||||
className={cx([style.input, style[variant], style[height], fluid && style.fluid, className])}
|
className={cx([style.input, style[variant], style[height], fluid && style.fluid, className])}
|
||||||
{...inputProps}
|
{...inputProps}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import { useCallback, useMemo, useState } from 'react';
|
import { useCallback, useMemo, useState } from 'react';
|
||||||
import { IoApps, IoSettingsOutline } from 'react-icons/io5';
|
import { IoApps, IoSettingsOutline } from 'react-icons/io5';
|
||||||
import { IconButton, Modal, ModalContent, ModalOverlay, useDisclosure } from '@chakra-ui/react';
|
import { Modal, ModalContent, ModalOverlay } from '@chakra-ui/react';
|
||||||
|
import { useDisclosure } from '@mantine/hooks';
|
||||||
|
|
||||||
|
import IconButton from '../../common/components/buttons/IconButton';
|
||||||
import NavigationMenu from '../../common/components/navigation-menu/NavigationMenu';
|
import NavigationMenu from '../../common/components/navigation-menu/NavigationMenu';
|
||||||
import useViewEditor from '../../common/components/navigation-menu/useViewEditor';
|
import useViewEditor from '../../common/components/navigation-menu/useViewEditor';
|
||||||
import EmptyPage from '../../common/components/state/EmptyPage';
|
import EmptyPage from '../../common/components/state/EmptyPage';
|
||||||
@@ -21,12 +23,11 @@ import { cuesheetOptions } from './cuesheet.options';
|
|||||||
import styles from './CuesheetPage.module.scss';
|
import styles from './CuesheetPage.module.scss';
|
||||||
|
|
||||||
export default function CuesheetPage() {
|
export default function CuesheetPage() {
|
||||||
// TODO: can we use the normalised rundown for the table?
|
|
||||||
const { data: flatRundown, status: rundownStatus } = useFlatRundown();
|
const { data: flatRundown, status: rundownStatus } = useFlatRundown();
|
||||||
const { data: customFields, status: customFieldStatus } = useCustomFields();
|
const { data: customFields, status: customFieldStatus } = useCustomFields();
|
||||||
const { showEditFormDrawer, isViewLocked } = useViewEditor({ isLockable: true });
|
const { showEditFormDrawer, isViewLocked } = useViewEditor({ isLockable: true });
|
||||||
const { isOpen: isMenuOpen, onOpen, onClose } = useDisclosure();
|
const [isMenuOpen, menuHandler] = useDisclosure();
|
||||||
const { isOpen: isEventEditorOpen, onOpen: onEventEditorOpen, onClose: onEventEditorClose } = useDisclosure();
|
const [isEventEditorOpen, eventEditorHandler] = useDisclosure();
|
||||||
const [eventId, setEventId] = useState<string | null>(null);
|
const [eventId, setEventId] = useState<string | null>(null);
|
||||||
|
|
||||||
const columns = useMemo(() => makeCuesheetColumns(customFields), [customFields]);
|
const columns = useMemo(() => makeCuesheetColumns(customFields), [customFields]);
|
||||||
@@ -40,13 +41,13 @@ export default function CuesheetPage() {
|
|||||||
(eventId: string | null) => {
|
(eventId: string | null) => {
|
||||||
if (eventId) {
|
if (eventId) {
|
||||||
setEventId(eventId);
|
setEventId(eventId);
|
||||||
onEventEditorOpen();
|
eventEditorHandler.open();
|
||||||
} else {
|
} else {
|
||||||
setEventId(null);
|
setEventId(null);
|
||||||
onEventEditorClose();
|
eventEditorHandler.close();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[onEventEditorClose, onEventEditorOpen],
|
[eventEditorHandler],
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!customFields || !flatRundown || rundownStatus === 'pending' || customFieldStatus === 'pending') {
|
if (!customFields || !flatRundown || rundownStatus === 'pending' || customFieldStatus === 'pending') {
|
||||||
@@ -55,32 +56,34 @@ export default function CuesheetPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Modal isOpen={isEventEditorOpen} onClose={onEventEditorClose} variant='ontime'>
|
<Modal isOpen={isEventEditorOpen} onClose={eventEditorHandler.close} variant='ontime'>
|
||||||
<ModalOverlay />
|
<ModalOverlay />
|
||||||
<ModalContent maxWidth='max(640px, 40vw)' padding='1rem'>
|
<ModalContent maxWidth='max(640px, 40vw)' padding='1rem'>
|
||||||
<CuesheetEventEditor eventId={eventId!} />
|
<CuesheetEventEditor eventId={eventId!} />
|
||||||
</ModalContent>
|
</ModalContent>
|
||||||
</Modal>
|
</Modal>
|
||||||
<div className={styles.tableWrapper} data-testid='cuesheet'>
|
<div className={styles.tableWrapper} data-testid='cuesheet'>
|
||||||
<NavigationMenu isOpen={isMenuOpen} onClose={onClose} />
|
<NavigationMenu isOpen={isMenuOpen} onClose={menuHandler.close} />
|
||||||
<ViewParamsEditor viewOptions={cuesheetOptions} />
|
<ViewParamsEditor viewOptions={cuesheetOptions} />
|
||||||
<CuesheetOverview>
|
<CuesheetOverview>
|
||||||
<IconButton
|
<IconButton
|
||||||
aria-label='Toggle navigation'
|
aria-label='Toggle navigation'
|
||||||
variant='ontime-subtle-white'
|
variant='subtle-white'
|
||||||
size='lg'
|
size='xlarge'
|
||||||
icon={<IoApps />}
|
onClick={menuHandler.open}
|
||||||
onClick={onOpen}
|
disabled={isViewLocked}
|
||||||
isDisabled={isViewLocked}
|
>
|
||||||
/>
|
<IoApps />
|
||||||
|
</IconButton>
|
||||||
<IconButton
|
<IconButton
|
||||||
aria-label='Toggle settings'
|
aria-label='Toggle settings'
|
||||||
variant='ontime-subtle-white'
|
variant='subtle-white'
|
||||||
size='lg'
|
size='xlarge'
|
||||||
icon={<IoSettingsOutline />}
|
|
||||||
onClick={showEditFormDrawer}
|
onClick={showEditFormDrawer}
|
||||||
isDisabled={isViewLocked}
|
disabled={isViewLocked}
|
||||||
/>
|
>
|
||||||
|
<IoSettingsOutline />
|
||||||
|
</IconButton>
|
||||||
</CuesheetOverview>
|
</CuesheetOverview>
|
||||||
<CuesheetProgress />
|
<CuesheetProgress />
|
||||||
<CuesheetDnd columns={columns}>
|
<CuesheetDnd columns={columns}>
|
||||||
|
|||||||
@@ -17,9 +17,7 @@ interface CuesheetDndProps {
|
|||||||
columns: ColumnDef<OntimeEntry>[];
|
columns: ColumnDef<OntimeEntry>[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function CuesheetDnd(props: PropsWithChildren<CuesheetDndProps>) {
|
export default function CuesheetDnd({ columns, children }: PropsWithChildren<CuesheetDndProps>) {
|
||||||
const { columns, children } = props;
|
|
||||||
|
|
||||||
const { columnOrder, saveColumnOrder } = useColumnManager(columns);
|
const { columnOrder, saveColumnOrder } = useColumnManager(columns);
|
||||||
|
|
||||||
const sensors = useSensors(
|
const sensors = useSensors(
|
||||||
|
|||||||
@@ -21,9 +21,7 @@ interface CuesheetTableProps {
|
|||||||
showModal: (eventId: MaybeString) => void;
|
showModal: (eventId: MaybeString) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function CuesheetTable(props: CuesheetTableProps) {
|
export default function CuesheetTable({ data, columns, showModal }: CuesheetTableProps) {
|
||||||
const { data, columns, showModal } = props;
|
|
||||||
|
|
||||||
const { updateEntry, updateTimer } = useEntryActions();
|
const { updateEntry, updateTimer } = useEntryActions();
|
||||||
const { followSelected, showDelayedTimes, hideTableSeconds } = useCuesheetOptions();
|
const { followSelected, showDelayedTimes, hideTableSeconds } = useCuesheetOptions();
|
||||||
const { columnVisibility, columnOrder, columnSizing, resetColumnOrder, setColumnVisibility, setColumnSizing } =
|
const { columnVisibility, columnOrder, columnSizing, resetColumnOrder, setColumnVisibility, setColumnSizing } =
|
||||||
|
|||||||
@@ -10,8 +10,7 @@ interface BlockRowProps {
|
|||||||
columnCount: number;
|
columnCount: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
function BlockRow(props: BlockRowProps) {
|
function BlockRow({ hidePast, title, columnCount }: BlockRowProps) {
|
||||||
const { hidePast, title, columnCount } = props;
|
|
||||||
const { currentBlockId } = useCurrentBlockId();
|
const { currentBlockId } = useCurrentBlockId();
|
||||||
const firstCellRef = useRef<null | HTMLTableCellElement>(null);
|
const firstCellRef = useRef<null | HTMLTableCellElement>(null);
|
||||||
|
|
||||||
|
|||||||
+1
-3
@@ -18,9 +18,7 @@ interface CuesheetBodyProps {
|
|||||||
table: Table<OntimeEntry>;
|
table: Table<OntimeEntry>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function CuesheetBody(props: CuesheetBodyProps) {
|
export default function CuesheetBody({ rowModel, selectedRef, table }: CuesheetBodyProps) {
|
||||||
const { rowModel, selectedRef, table } = props;
|
|
||||||
|
|
||||||
const { selectedEventId } = useSelectedEventId();
|
const { selectedEventId } = useSelectedEventId();
|
||||||
const { hideDelays, hidePast } = useCuesheetOptions();
|
const { hideDelays, hidePast } = useCuesheetOptions();
|
||||||
|
|
||||||
|
|||||||
+1
-2
@@ -13,8 +13,7 @@ interface CuesheetHeaderProps {
|
|||||||
headerGroups: HeaderGroup<OntimeEntry>[];
|
headerGroups: HeaderGroup<OntimeEntry>[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function CuesheetHeader(props: CuesheetHeaderProps) {
|
export default function CuesheetHeader({ headerGroups }: CuesheetHeaderProps) {
|
||||||
const { headerGroups } = props;
|
|
||||||
const { hideIndexColumn, showActionMenu } = useCuesheetOptions();
|
const { hideIndexColumn, showActionMenu } = useCuesheetOptions();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -8,8 +8,7 @@ interface DelayRowProps {
|
|||||||
duration: number;
|
duration: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
function DelayRow(props: DelayRowProps) {
|
function DelayRow({ duration }: DelayRowProps) {
|
||||||
const { duration } = props;
|
|
||||||
const delayTime = millisToDelayString(duration, 'expanded');
|
const delayTime = millisToDelayString(duration, 'expanded');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
+7
-3
@@ -17,9 +17,13 @@ interface ParentFocusableInput extends HTMLInputElement {
|
|||||||
|
|
||||||
export default memo(DurationInput);
|
export default memo(DurationInput);
|
||||||
|
|
||||||
function DurationInput(props: PropsWithChildren<DurationInputProps>) {
|
function DurationInput({
|
||||||
const { initialValue, lockedValue, delayed, onSubmit, children } = props;
|
initialValue,
|
||||||
|
lockedValue,
|
||||||
|
delayed,
|
||||||
|
onSubmit,
|
||||||
|
children,
|
||||||
|
}: PropsWithChildren<DurationInputProps>) {
|
||||||
const [isEditing, setIsEditing] = useState(false);
|
const [isEditing, setIsEditing] = useState(false);
|
||||||
const [value, setValue] = useState(initialValue);
|
const [value, setValue] = useState(initialValue);
|
||||||
const inputRef = useRef<ParentFocusableInput>(null);
|
const inputRef = useRef<ParentFocusableInput>(null);
|
||||||
|
|||||||
+5
-10
@@ -1,5 +1,6 @@
|
|||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import { Input } from '@chakra-ui/react';
|
|
||||||
|
import Input from '../../../../common/components/input/input/Input';
|
||||||
|
|
||||||
import style from './EditableImage.module.scss';
|
import style from './EditableImage.module.scss';
|
||||||
|
|
||||||
@@ -10,9 +11,7 @@ interface EditableImageProps {
|
|||||||
|
|
||||||
export default memo(EditableImage);
|
export default memo(EditableImage);
|
||||||
|
|
||||||
function EditableImage(props: EditableImageProps) {
|
function EditableImage({ initialValue, updateValue }: EditableImageProps) {
|
||||||
const { initialValue, updateValue } = props;
|
|
||||||
|
|
||||||
const handleUpdate = (newValue: string) => {
|
const handleUpdate = (newValue: string) => {
|
||||||
if (newValue === initialValue) {
|
if (newValue === initialValue) {
|
||||||
return;
|
return;
|
||||||
@@ -26,10 +25,8 @@ function EditableImage(props: EditableImageProps) {
|
|||||||
if (!initialValue) {
|
if (!initialValue) {
|
||||||
return (
|
return (
|
||||||
<Input
|
<Input
|
||||||
size='sm'
|
variant='ghosted'
|
||||||
variant='ontime-transparent'
|
fluid
|
||||||
padding={0}
|
|
||||||
fontSize='md'
|
|
||||||
placeholder='Paste image URL'
|
placeholder='Paste image URL'
|
||||||
onBlur={(event) => handleUpdate(event.currentTarget.value)}
|
onBlur={(event) => handleUpdate(event.currentTarget.value)}
|
||||||
onKeyDown={(event) => {
|
onKeyDown={(event) => {
|
||||||
@@ -38,8 +35,6 @@ function EditableImage(props: EditableImageProps) {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
defaultValue={initialValue}
|
defaultValue={initialValue}
|
||||||
spellCheck={false}
|
|
||||||
autoComplete='off'
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,8 +39,7 @@ export default memo(EventRow, (prevProps, nextProps) => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
function EventRow(props: EventRowProps) {
|
function EventRow({ rowId, event, eventIndex, rowIndex, isPast, selectedRef, rowBgColour, table }: EventRowProps) {
|
||||||
const { rowId, event, eventIndex, rowIndex, isPast, selectedRef, rowBgColour, table } = props;
|
|
||||||
const { hideIndexColumn, showActionMenu } = useCuesheetOptions();
|
const { hideIndexColumn, showActionMenu } = useCuesheetOptions();
|
||||||
const ownRef = useRef<HTMLTableRowElement>(null);
|
const ownRef = useRef<HTMLTableRowElement>(null);
|
||||||
const [isVisible, setIsVisible] = useState(false);
|
const [isVisible, setIsVisible] = useState(false);
|
||||||
|
|||||||
+1
-2
@@ -10,8 +10,7 @@ interface MultiLineCellProps {
|
|||||||
|
|
||||||
export default memo(MultiLineCell);
|
export default memo(MultiLineCell);
|
||||||
|
|
||||||
function MultiLineCell(props: MultiLineCellProps) {
|
function MultiLineCell({ initialValue, handleUpdate }: MultiLineCellProps) {
|
||||||
const { initialValue, handleUpdate } = props;
|
|
||||||
const ref = useRef<HTMLInputElement | null>(null);
|
const ref = useRef<HTMLInputElement | null>(null);
|
||||||
const submitCallback = useCallback((newValue: string) => handleUpdate(newValue), [handleUpdate]);
|
const submitCallback = useCallback((newValue: string) => handleUpdate(newValue), [handleUpdate]);
|
||||||
|
|
||||||
|
|||||||
+39
-42
@@ -1,6 +1,6 @@
|
|||||||
import { forwardRef, memo, useCallback, useImperativeHandle, useRef } from 'react';
|
import { forwardRef, memo, useCallback, useImperativeHandle, useRef } from 'react';
|
||||||
import { Input } from '@chakra-ui/react';
|
|
||||||
|
|
||||||
|
import Input from '../../../../common/components/input/input/Input';
|
||||||
import useReactiveTextInput from '../../../../common/components/input/text-input/useReactiveTextInput';
|
import useReactiveTextInput from '../../../../common/components/input/text-input/useReactiveTextInput';
|
||||||
|
|
||||||
interface SingleLineCellProps {
|
interface SingleLineCellProps {
|
||||||
@@ -10,50 +10,47 @@ interface SingleLineCellProps {
|
|||||||
handleCancelUpdate?: () => void;
|
handleCancelUpdate?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SingleLineCell = forwardRef((props: SingleLineCellProps, inputRef) => {
|
const SingleLineCell = forwardRef(
|
||||||
const { initialValue, allowSubmitSameValue, handleUpdate, handleCancelUpdate } = props;
|
({ initialValue, allowSubmitSameValue, handleUpdate, handleCancelUpdate }: SingleLineCellProps, inputRef) => {
|
||||||
const ref = useRef<HTMLInputElement | null>(null);
|
const ref = useRef<HTMLInputElement | null>(null);
|
||||||
const submitCallback = useCallback((newValue: string) => handleUpdate(newValue), [handleUpdate]);
|
const submitCallback = useCallback((newValue: string) => handleUpdate(newValue), [handleUpdate]);
|
||||||
|
|
||||||
const { value, onChange, onBlur, onKeyDown } = useReactiveTextInput(initialValue, submitCallback, ref, {
|
const { value, onChange, onBlur, onKeyDown } = useReactiveTextInput(initialValue, submitCallback, ref, {
|
||||||
allowSubmitSameValue,
|
allowSubmitSameValue,
|
||||||
allowKeyboardNavigation: true,
|
allowKeyboardNavigation: true,
|
||||||
submitOnEnter: true, // single line should submit on enter
|
submitOnEnter: true, // single line should submit on enter
|
||||||
submitOnCtrlEnter: true,
|
submitOnCtrlEnter: true,
|
||||||
onCancelUpdate: handleCancelUpdate,
|
onCancelUpdate: handleCancelUpdate,
|
||||||
});
|
});
|
||||||
|
|
||||||
// expose a subset of the methods to the parent
|
// expose a subset of the methods to the parent
|
||||||
useImperativeHandle(inputRef, () => {
|
useImperativeHandle(inputRef, () => {
|
||||||
return {
|
return {
|
||||||
focus() {
|
focus() {
|
||||||
ref.current?.focus();
|
ref.current?.focus();
|
||||||
},
|
},
|
||||||
select() {
|
select() {
|
||||||
ref.current?.select();
|
ref.current?.select();
|
||||||
},
|
},
|
||||||
focusParentElement() {
|
focusParentElement() {
|
||||||
ref.current?.parentElement?.focus();
|
ref.current?.parentElement?.focus();
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}, [ref]);
|
}, [ref]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Input
|
<Input
|
||||||
ref={ref}
|
ref={ref}
|
||||||
size='sm'
|
variant='ghosted'
|
||||||
variant='ontime-transparent'
|
fluid
|
||||||
padding={0}
|
value={value}
|
||||||
fontSize='md'
|
onChange={onChange}
|
||||||
value={value}
|
onBlur={onBlur}
|
||||||
onChange={onChange}
|
onKeyDown={onKeyDown}
|
||||||
onBlur={onBlur}
|
/>
|
||||||
onKeyDown={onKeyDown}
|
);
|
||||||
spellCheck={false}
|
},
|
||||||
autoComplete='off'
|
);
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
SingleLineCell.displayName = 'SingleLineCell';
|
SingleLineCell.displayName = 'SingleLineCell';
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -18,9 +18,9 @@ const TextLikeInput = forwardRef((props: PropsWithChildren<TextLikeInputProps>,
|
|||||||
return {
|
return {
|
||||||
focusParentElement() {
|
focusParentElement() {
|
||||||
ref.current?.parentElement?.focus();
|
ref.current?.parentElement?.focus();
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
})
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes} {...elementProps} tabIndex={0} ref={ref}>
|
<div className={classes} {...elementProps} tabIndex={0} ref={ref}>
|
||||||
|
|||||||
@@ -19,9 +19,13 @@ interface ParentFocusableInput extends HTMLInputElement {
|
|||||||
|
|
||||||
export default memo(TimeInputDuration);
|
export default memo(TimeInputDuration);
|
||||||
|
|
||||||
function TimeInputDuration(props: PropsWithChildren<TimeInputDurationProps>) {
|
function TimeInputDuration({
|
||||||
const { initialValue, lockedValue, delayed, onSubmit, children } = props;
|
initialValue,
|
||||||
|
lockedValue,
|
||||||
|
delayed,
|
||||||
|
onSubmit,
|
||||||
|
children,
|
||||||
|
}: PropsWithChildren<TimeInputDurationProps>) {
|
||||||
const [isEditing, setIsEditing] = useState(false);
|
const [isEditing, setIsEditing] = useState(false);
|
||||||
const [value, setValue] = useState(initialValue);
|
const [value, setValue] = useState(initialValue);
|
||||||
const inputRef = useRef<ParentFocusableInput>(null);
|
const inputRef = useRef<ParentFocusableInput>(null);
|
||||||
|
|||||||
+1
-2
@@ -10,8 +10,7 @@ interface CuesheetTableMenuProps {
|
|||||||
|
|
||||||
export default memo(CuesheetTableMenu);
|
export default memo(CuesheetTableMenu);
|
||||||
|
|
||||||
function CuesheetTableMenu(props: CuesheetTableMenuProps) {
|
function CuesheetTableMenu({ showModal }: CuesheetTableMenuProps) {
|
||||||
const { showModal } = props;
|
|
||||||
const { isOpen, eventId, entryIndex, position, closeMenu } = useCuesheetTableMenu();
|
const { isOpen, eventId, entryIndex, position, closeMenu } = useCuesheetTableMenu();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
+1
-2
@@ -11,8 +11,7 @@ interface CuesheetTableMenuActionsProps {
|
|||||||
showModal: (entryId: string) => void;
|
showModal: (entryId: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function CuesheetTableMenuActions(props: CuesheetTableMenuActionsProps) {
|
export default function CuesheetTableMenuActions({ eventId, entryIndex, showModal }: CuesheetTableMenuActionsProps) {
|
||||||
const { eventId, entryIndex, showModal } = props;
|
|
||||||
const { addEntry, getEntryById, move, deleteEntry } = useEntryActions();
|
const { addEntry, getEntryById, move, deleteEntry } = useEntryActions();
|
||||||
|
|
||||||
const handleCloneEvent = () => {
|
const handleCloneEvent = () => {
|
||||||
|
|||||||
+14
-20
@@ -1,18 +1,13 @@
|
|||||||
import { memo, ReactNode } from 'react';
|
import { memo, ReactNode } from 'react';
|
||||||
import { Button, Checkbox } from '@chakra-ui/react';
|
|
||||||
import { Column } from '@tanstack/react-table';
|
import { Column } from '@tanstack/react-table';
|
||||||
import { OntimeEntry } from 'ontime-types';
|
import { OntimeEntry } from 'ontime-types';
|
||||||
|
|
||||||
|
import Button from '../../../../common/components/buttons/Button';
|
||||||
|
import Checkbox from '../../../../common/components/checkbox/Checkbox';
|
||||||
import * as Editor from '../../../../common/components/editor-utils/EditorUtils';
|
import * as Editor from '../../../../common/components/editor-utils/EditorUtils';
|
||||||
|
|
||||||
import style from './CuesheetTableSettings.module.scss';
|
import style from './CuesheetTableSettings.module.scss';
|
||||||
|
|
||||||
// reusable button styles
|
|
||||||
const buttonProps = {
|
|
||||||
size: 'xs',
|
|
||||||
variant: 'ontime-subtle',
|
|
||||||
};
|
|
||||||
|
|
||||||
interface CuesheetTableSettingsProps {
|
interface CuesheetTableSettingsProps {
|
||||||
columns: Column<OntimeEntry, unknown>[];
|
columns: Column<OntimeEntry, unknown>[];
|
||||||
handleResetResizing: () => void;
|
handleResetResizing: () => void;
|
||||||
@@ -20,9 +15,12 @@ interface CuesheetTableSettingsProps {
|
|||||||
handleClearToggles: () => void;
|
handleClearToggles: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
function CuesheetTableSettings(props: CuesheetTableSettingsProps) {
|
function CuesheetTableSettings({
|
||||||
const { columns, handleResetResizing, handleResetReordering, handleClearToggles } = props;
|
columns,
|
||||||
|
handleResetResizing,
|
||||||
|
handleResetReordering,
|
||||||
|
handleClearToggles,
|
||||||
|
}: CuesheetTableSettingsProps) {
|
||||||
return (
|
return (
|
||||||
<div className={style.tableSettings}>
|
<div className={style.tableSettings}>
|
||||||
<div>
|
<div>
|
||||||
@@ -32,14 +30,10 @@ function CuesheetTableSettings(props: CuesheetTableSettingsProps) {
|
|||||||
const columnHeader = column.columnDef.header;
|
const columnHeader = column.columnDef.header;
|
||||||
const visible = column.getIsVisible();
|
const visible = column.getIsVisible();
|
||||||
return (
|
return (
|
||||||
<label key={`${column.id}-${visible}`} className={style.option}>
|
<Editor.Label key={`${column.id}-${visible}`} className={style.option}>
|
||||||
<Checkbox
|
<Checkbox defaultChecked={visible} onCheckedChange={column.toggleVisibility} />
|
||||||
variant='ontime-ondark'
|
|
||||||
defaultChecked={visible}
|
|
||||||
onChange={column.getToggleVisibilityHandler()}
|
|
||||||
/>
|
|
||||||
{columnHeader as ReactNode}
|
{columnHeader as ReactNode}
|
||||||
</label>
|
</Editor.Label>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
@@ -47,13 +41,13 @@ function CuesheetTableSettings(props: CuesheetTableSettingsProps) {
|
|||||||
<div className={style.column}>
|
<div className={style.column}>
|
||||||
<Editor.Label className={style.sectionTitle}>Reset Options</Editor.Label>
|
<Editor.Label className={style.sectionTitle}>Reset Options</Editor.Label>
|
||||||
<div className={style.row}>
|
<div className={style.row}>
|
||||||
<Button onClick={handleClearToggles} {...buttonProps}>
|
<Button size='small' variant='subtle' onClick={handleClearToggles}>
|
||||||
Show All
|
Show All
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={handleResetResizing} {...buttonProps}>
|
<Button size='small' variant='subtle' onClick={handleResetResizing}>
|
||||||
Reset Resizing
|
Reset Resizing
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={handleResetReordering} {...buttonProps}>
|
<Button size='small' variant='subtle' onClick={handleResetReordering}>
|
||||||
Reset Reordering
|
Reset Reordering
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { lazy, useCallback, useEffect } from 'react';
|
import { lazy, useCallback, useEffect } from 'react';
|
||||||
import { IoApps, IoClose, IoSettingsOutline } from 'react-icons/io5';
|
import { IoApps, IoClose, IoSettingsOutline } from 'react-icons/io5';
|
||||||
import { IconButton, useDisclosure } from '@chakra-ui/react';
|
import { useDisclosure, useHotkeys } from '@mantine/hooks';
|
||||||
import { useHotkeys } from '@mantine/hooks';
|
|
||||||
|
|
||||||
|
import IconButton from '../../common/components/buttons/IconButton';
|
||||||
import NavigationMenu from '../../common/components/navigation-menu/NavigationMenu';
|
import NavigationMenu from '../../common/components/navigation-menu/NavigationMenu';
|
||||||
import { useElectronListener } from '../../common/hooks/useElectronEvent';
|
import { useElectronListener } from '../../common/hooks/useElectronEvent';
|
||||||
import { useWindowTitle } from '../../common/hooks/useWindowTitle';
|
import { useWindowTitle } from '../../common/hooks/useWindowTitle';
|
||||||
@@ -20,7 +20,7 @@ const MessageControl = lazy(() => import('../../features/control/message/Message
|
|||||||
|
|
||||||
export default function Editor() {
|
export default function Editor() {
|
||||||
const { isOpen: isSettingsOpen, setLocation, close } = useAppSettingsNavigation();
|
const { isOpen: isSettingsOpen, setLocation, close } = useAppSettingsNavigation();
|
||||||
const { isOpen: isMenuOpen, onOpen, onClose } = useDisclosure();
|
const [isOpen, handler] = useDisclosure();
|
||||||
|
|
||||||
useWindowTitle('Editor');
|
useWindowTitle('Editor');
|
||||||
|
|
||||||
@@ -49,22 +49,19 @@ export default function Editor() {
|
|||||||
return (
|
return (
|
||||||
<div className={styles.mainContainer} data-testid='event-editor'>
|
<div className={styles.mainContainer} data-testid='event-editor'>
|
||||||
<WelcomePlacement />
|
<WelcomePlacement />
|
||||||
<NavigationMenu isOpen={isMenuOpen} onClose={onClose} />
|
<NavigationMenu isOpen={isOpen} onClose={handler.close} />
|
||||||
<EditorOverview>
|
<EditorOverview>
|
||||||
<IconButton
|
<IconButton aria-label='Toggle navigation' variant='subtle-white' size='xlarge' onClick={handler.open}>
|
||||||
aria-label='Toggle navigation'
|
<IoApps />
|
||||||
variant='ontime-subtle-white'
|
</IconButton>
|
||||||
size='lg'
|
|
||||||
icon={<IoApps />}
|
|
||||||
onClick={onOpen}
|
|
||||||
/>
|
|
||||||
<IconButton
|
<IconButton
|
||||||
aria-label='Toggle settings'
|
aria-label='Toggle settings'
|
||||||
variant={isSettingsOpen ? 'ontime-subtle' : 'ontime-subtle-white'}
|
variant={isSettingsOpen ? 'subtle' : 'subtle-white'}
|
||||||
size='lg'
|
size='xlarge'
|
||||||
icon={isSettingsOpen ? <IoClose /> : <IoSettingsOutline />}
|
|
||||||
onClick={toggleSettings}
|
onClick={toggleSettings}
|
||||||
/>
|
>
|
||||||
|
{isSettingsOpen ? <IoClose /> : <IoSettingsOutline />}
|
||||||
|
</IconButton>
|
||||||
</EditorOverview>
|
</EditorOverview>
|
||||||
{isSettingsOpen ? (
|
{isSettingsOpen ? (
|
||||||
<AppSettings />
|
<AppSettings />
|
||||||
|
|||||||
Reference in New Issue
Block a user