mirror of
https://github.com/cpvalente/ontime.git
synced 2026-09-10 08:39:34 +00:00
refactor: consolidate event editor styles
This commit is contained in:
committed by
Carlos Valente
parent
dd5ffb2f47
commit
a518dc4882
@@ -5,6 +5,7 @@ import { millisToString, parseUserTime } from 'ontime-utils';
|
|||||||
import { useEmitLog } from '../../../stores/logger';
|
import { useEmitLog } from '../../../stores/logger';
|
||||||
|
|
||||||
interface TimeInputProps<T extends string> {
|
interface TimeInputProps<T extends string> {
|
||||||
|
id?: T;
|
||||||
name: T;
|
name: T;
|
||||||
submitHandler: (field: T, value: string) => void;
|
submitHandler: (field: T, value: string) => void;
|
||||||
time?: number;
|
time?: number;
|
||||||
@@ -15,7 +16,7 @@ interface TimeInputProps<T extends string> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function TimeInput<T extends string>(props: TimeInputProps<T>) {
|
export default function TimeInput<T extends string>(props: TimeInputProps<T>) {
|
||||||
const { name, submitHandler, time = 0, placeholder, disabled, align = 'center', className } = props;
|
const { id, name, submitHandler, time = 0, placeholder, disabled, align = 'center', className } = props;
|
||||||
const { emitError } = useEmitLog();
|
const { emitError } = useEmitLog();
|
||||||
const inputRef = useRef<HTMLInputElement | null>(null);
|
const inputRef = useRef<HTMLInputElement | null>(null);
|
||||||
const [value, setValue] = useState<string>('');
|
const [value, setValue] = useState<string>('');
|
||||||
@@ -117,6 +118,7 @@ export default function TimeInput<T extends string>(props: TimeInputProps<T>) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Input
|
<Input
|
||||||
|
id={id}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
size='sm'
|
size='sm'
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
|
|||||||
@@ -20,3 +20,20 @@
|
|||||||
outline: 2px solid $gray-1000;
|
outline: 2px solid $gray-1000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 1rem;
|
||||||
|
color: $label-gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
display: block;
|
||||||
|
font-size: calc(1rem - 3px);
|
||||||
|
color: $label-gray;
|
||||||
|
margin-bottom: 0.25rem;
|
||||||
|
max-width: max-content; // prevent label from taking entire row
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import type { LabelHTMLAttributes, ReactNode } from 'react';
|
||||||
import { IoArrowUp } from '@react-icons/all-files/io5/IoArrowUp';
|
import { IoArrowUp } from '@react-icons/all-files/io5/IoArrowUp';
|
||||||
import { type IconBaseProps } from '@react-icons/all-files/lib';
|
import { type IconBaseProps } from '@react-icons/all-files/lib';
|
||||||
|
|
||||||
@@ -8,3 +9,16 @@ import style from './EditorUtils.module.scss';
|
|||||||
export function Corner({ className, ...elementProps }: IconBaseProps) {
|
export function Corner({ className, ...elementProps }: IconBaseProps) {
|
||||||
return <IoArrowUp className={cx([style.corner, className])} {...elementProps} />;
|
return <IoArrowUp className={cx([style.corner, className])} {...elementProps} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function Title({ children }: { children: ReactNode }) {
|
||||||
|
return <h3 className={style.title}>{children}</h3>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Label({ children, className, ...elementProps }: LabelHTMLAttributes<HTMLLabelElement>) {
|
||||||
|
const classes = cx([style.label, className]);
|
||||||
|
return (
|
||||||
|
<label className={classes} {...elementProps}>
|
||||||
|
{children}
|
||||||
|
</label>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -40,13 +40,6 @@
|
|||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.inputLabel {
|
|
||||||
display: block;
|
|
||||||
font-size: calc(1rem - 3px);
|
|
||||||
color: $label-gray;
|
|
||||||
margin-bottom: 0.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.decorated {
|
.decorated {
|
||||||
color: var(--decorator-color, $ui-white);
|
color: var(--decorator-color, $ui-white);
|
||||||
background-color: var(--decorator-bg, $gray-1100);
|
background-color: var(--decorator-bg, $gray-1100);
|
||||||
@@ -58,7 +51,6 @@
|
|||||||
.delayLabel {
|
.delayLabel {
|
||||||
font-size: calc(1rem - 3px);
|
font-size: calc(1rem - 3px);
|
||||||
color: $ontime-delay-text;
|
color: $ontime-delay-text;
|
||||||
margin-top: 0.25rem;
|
|
||||||
|
|
||||||
&::after {
|
&::after {
|
||||||
content: '\200b';
|
content: '\200b';
|
||||||
@@ -66,8 +58,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.switchLabel {
|
.switchLabel {
|
||||||
font-size: calc(1rem - 3px);
|
|
||||||
color: $label-gray;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { useEventAction } from '../../../common/hooks/useEventAction';
|
|||||||
import useCustomFields from '../../../common/hooks-query/useCustomFields';
|
import useCustomFields from '../../../common/hooks-query/useCustomFields';
|
||||||
import useRundown from '../../../common/hooks-query/useRundown';
|
import useRundown from '../../../common/hooks-query/useRundown';
|
||||||
import { getAccessibleColour } from '../../../common/utils/styleUtils';
|
import { getAccessibleColour } from '../../../common/utils/styleUtils';
|
||||||
|
import * as Editor from '../../editors/editor-utils/EditorUtils';
|
||||||
import { useEventSelection } from '../useEventSelection';
|
import { useEventSelection } from '../useEventSelection';
|
||||||
|
|
||||||
import EventEditorTimes from './composite/EventEditorTimes';
|
import EventEditorTimes from './composite/EventEditorTimes';
|
||||||
@@ -100,7 +101,7 @@ export default function EventEditor() {
|
|||||||
/>
|
/>
|
||||||
<div className={style.column}>
|
<div className={style.column}>
|
||||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
|
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
|
||||||
<span>Custom Fields</span>
|
<Editor.Title>Custom Fields</Editor.Title>
|
||||||
<Button variant='ontime-subtle' size='sm' onClick={handleOpenCustomManager}>
|
<Button variant='ontime-subtle' size='sm' onClick={handleOpenCustomManager}>
|
||||||
Manage
|
Manage
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { millisToString, parseUserTime } from 'ontime-utils';
|
|||||||
import TimeInput from '../../../../common/components/input/time-input/TimeInput';
|
import TimeInput from '../../../../common/components/input/time-input/TimeInput';
|
||||||
import { useEventAction } from '../../../../common/hooks/useEventAction';
|
import { useEventAction } from '../../../../common/hooks/useEventAction';
|
||||||
import { millisToDelayString } from '../../../../common/utils/dateConfig';
|
import { millisToDelayString } from '../../../../common/utils/dateConfig';
|
||||||
|
import * as Editor from '../../../editors/editor-utils/EditorUtils';
|
||||||
import TimeInputFlow from '../../time-input-flow/TimeInputFlow';
|
import TimeInputFlow from '../../time-input-flow/TimeInputFlow';
|
||||||
|
|
||||||
import style from '../EventEditor.module.scss';
|
import style from '../EventEditor.module.scss';
|
||||||
@@ -72,7 +73,7 @@ const EventEditorTimes = (props: EventEditorTimesProps) => {
|
|||||||
return (
|
return (
|
||||||
<div className={style.column}>
|
<div className={style.column}>
|
||||||
<div>
|
<div>
|
||||||
<div className={style.inputLabel}>Event schedule</div>
|
<Editor.Label>Event schedule</Editor.Label>
|
||||||
<div className={style.inline}>
|
<div className={style.inline}>
|
||||||
<TimeInputFlow
|
<TimeInputFlow
|
||||||
eventId={eventId}
|
eventId={eventId}
|
||||||
@@ -90,15 +91,20 @@ const EventEditorTimes = (props: EventEditorTimesProps) => {
|
|||||||
|
|
||||||
<div className={style.splitTwo}>
|
<div className={style.splitTwo}>
|
||||||
<div>
|
<div>
|
||||||
<label className={style.inputLabel} htmlFor='timeWarning'>
|
<Editor.Label htmlFor='timeWarning'>Warning Time</Editor.Label>
|
||||||
Warning Time
|
<TimeInput
|
||||||
</label>
|
id='timeWarning'
|
||||||
<TimeInput name='timeWarning' submitHandler={handleSubmit} time={timeWarning} placeholder='Duration' />
|
name='timeWarning'
|
||||||
|
submitHandler={handleSubmit}
|
||||||
|
time={timeWarning}
|
||||||
|
placeholder='Duration'
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label className={style.inputLabel}>Timer Type</label>
|
<Editor.Label htmlFor='timerType'>Timer Type</Editor.Label>
|
||||||
<Select
|
<Select
|
||||||
size='sm'
|
size='sm'
|
||||||
|
id='timerType'
|
||||||
name='timerType'
|
name='timerType'
|
||||||
value={timerType}
|
value={timerType}
|
||||||
onChange={(event) => handleSubmit('timerType', event.target.value)}
|
onChange={(event) => handleSubmit('timerType', event.target.value)}
|
||||||
@@ -112,14 +118,19 @@ const EventEditorTimes = (props: EventEditorTimesProps) => {
|
|||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label className={style.inputLabel} htmlFor='timeDanger'>
|
<Editor.Label htmlFor='timeDanger'>Danger Time</Editor.Label>
|
||||||
Danger Time
|
<TimeInput
|
||||||
</label>
|
id='timeDanger'
|
||||||
<TimeInput name='timeDanger' submitHandler={handleSubmit} time={timeDanger} placeholder='Duration' />
|
name='timeDanger'
|
||||||
|
submitHandler={handleSubmit}
|
||||||
|
time={timeDanger}
|
||||||
|
placeholder='Duration'
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label className={style.inputLabel}>End Action</label>
|
<Editor.Label htmlFor='endAction'>End Action</Editor.Label>
|
||||||
<Select
|
<Select
|
||||||
|
id='endAction'
|
||||||
size='sm'
|
size='sm'
|
||||||
name='endAction'
|
name='endAction'
|
||||||
value={endAction}
|
value={endAction}
|
||||||
@@ -135,11 +146,17 @@ const EventEditorTimes = (props: EventEditorTimesProps) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<span className={style.inputLabel}>Event Visibility</span>
|
<Editor.Label htmlFor='isPublic'>Event Visibility</Editor.Label>
|
||||||
<label className={style.switchLabel}>
|
<Editor.Label className={style.switchLabel}>
|
||||||
<Switch size='md' isChecked={isPublic} onChange={() => handleSubmit('isPublic', isPublic)} variant='ontime' />
|
<Switch
|
||||||
|
id='isPublic'
|
||||||
|
size='md'
|
||||||
|
isChecked={isPublic}
|
||||||
|
onChange={() => handleSubmit('isPublic', isPublic)}
|
||||||
|
variant='ontime'
|
||||||
|
/>
|
||||||
{isPublic ? 'Public' : 'Private'}
|
{isPublic ? 'Public' : 'Private'}
|
||||||
</label>
|
</Editor.Label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { Input } from '@chakra-ui/react';
|
|||||||
import { sanitiseCue } from 'ontime-utils';
|
import { sanitiseCue } from 'ontime-utils';
|
||||||
|
|
||||||
import SwatchSelect from '../../../../common/components/input/colour-input/SwatchSelect';
|
import SwatchSelect from '../../../../common/components/input/colour-input/SwatchSelect';
|
||||||
|
import * as Editor from '../../../editors/editor-utils/EditorUtils';
|
||||||
import { type EditorUpdateFields } from '../EventEditor';
|
import { type EditorUpdateFields } from '../EventEditor';
|
||||||
|
|
||||||
import EventTextArea from './EventTextArea';
|
import EventTextArea from './EventTextArea';
|
||||||
@@ -30,9 +31,7 @@ const EventEditorTitles = (props: EventEditorTitlesProps) => {
|
|||||||
<div className={style.column}>
|
<div className={style.column}>
|
||||||
<div className={style.splitTwo}>
|
<div className={style.splitTwo}>
|
||||||
<div>
|
<div>
|
||||||
<label className={style.inputLabel} htmlFor='eventId'>
|
<Editor.Label htmlFor='eventId'>Event ID (read only)</Editor.Label>
|
||||||
Event ID (read only)
|
|
||||||
</label>
|
|
||||||
<Input
|
<Input
|
||||||
id='eventId'
|
id='eventId'
|
||||||
size='sm'
|
size='sm'
|
||||||
@@ -45,7 +44,7 @@ const EventEditorTitles = (props: EventEditorTitlesProps) => {
|
|||||||
<EventTextInput field='cue' label='Cue' initialValue={cue} submitHandler={cueSubmitHandler} maxLength={10} />
|
<EventTextInput field='cue' label='Cue' initialValue={cue} submitHandler={cueSubmitHandler} maxLength={10} />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label className={style.inputLabel}>Colour</label>
|
<Editor.Label>Colour</Editor.Label>
|
||||||
<SwatchSelect name='colour' value={colour} handleChange={handleSubmit} />
|
<SwatchSelect name='colour' value={colour} handleChange={handleSubmit} />
|
||||||
</div>
|
</div>
|
||||||
<EventTextInput field='title' label='Title' initialValue={title} submitHandler={handleSubmit} />
|
<EventTextInput field='title' label='Title' initialValue={title} submitHandler={handleSubmit} />
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
import { CSSProperties, useCallback, useRef } from 'react';
|
import { type CSSProperties, useCallback, useRef } from 'react';
|
||||||
|
|
||||||
import { AutoTextArea } from '../../../../common/components/input/auto-text-area/AutoTextArea';
|
import { AutoTextArea } from '../../../../common/components/input/auto-text-area/AutoTextArea';
|
||||||
import useReactiveTextInput from '../../../../common/components/input/text-input/useReactiveTextInput';
|
import useReactiveTextInput from '../../../../common/components/input/text-input/useReactiveTextInput';
|
||||||
import { cx } from '../../../../common/utils/styleUtils';
|
import * as Editor from '../../../editors/editor-utils/EditorUtils';
|
||||||
import { EditorUpdateFields } from '../EventEditor';
|
import { EditorUpdateFields } from '../EventEditor';
|
||||||
|
|
||||||
import style from '../EventEditor.module.scss';
|
|
||||||
|
|
||||||
interface CountedTextAreaProps {
|
interface CountedTextAreaProps {
|
||||||
className?: string;
|
className?: string;
|
||||||
field: EditorUpdateFields;
|
field: EditorUpdateFields;
|
||||||
@@ -24,13 +22,12 @@ export default function EventTextArea(props: CountedTextAreaProps) {
|
|||||||
const { value, onChange, onBlur, onKeyDown } = useReactiveTextInput(initialValue, submitCallback, ref, {
|
const { value, onChange, onBlur, onKeyDown } = useReactiveTextInput(initialValue, submitCallback, ref, {
|
||||||
submitOnCtrlEnter: true,
|
submitOnCtrlEnter: true,
|
||||||
});
|
});
|
||||||
const classes = cx([style.inputLabel, className]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<label className={classes} htmlFor={field} style={givenStyles}>
|
<Editor.Label className={className} htmlFor={field} style={givenStyles}>
|
||||||
{label}
|
{label}
|
||||||
</label>
|
</Editor.Label>
|
||||||
<AutoTextArea
|
<AutoTextArea
|
||||||
id={field}
|
id={field}
|
||||||
inputref={ref}
|
inputref={ref}
|
||||||
|
|||||||
@@ -2,10 +2,9 @@ import { useCallback, useRef } from 'react';
|
|||||||
import { Input, InputProps } from '@chakra-ui/react';
|
import { Input, InputProps } from '@chakra-ui/react';
|
||||||
|
|
||||||
import useReactiveTextInput from '../../../../common/components/input/text-input/useReactiveTextInput';
|
import useReactiveTextInput from '../../../../common/components/input/text-input/useReactiveTextInput';
|
||||||
|
import * as Editor from '../../../editors/editor-utils/EditorUtils';
|
||||||
import { EditorUpdateFields } from '../EventEditor';
|
import { EditorUpdateFields } from '../EventEditor';
|
||||||
|
|
||||||
import style from '../EventEditor.module.scss';
|
|
||||||
|
|
||||||
interface EventTextInputProps extends InputProps {
|
interface EventTextInputProps extends InputProps {
|
||||||
field: EditorUpdateFields;
|
field: EditorUpdateFields;
|
||||||
label: string;
|
label: string;
|
||||||
@@ -24,9 +23,7 @@ export default function EventTextInput(props: EventTextInputProps) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<label className={style.inputLabel} htmlFor={field}>
|
<Editor.Label htmlFor={field}>{label}</Editor.Label>
|
||||||
{label}
|
|
||||||
</label>
|
|
||||||
<Input
|
<Input
|
||||||
id={field}
|
id={field}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
|
|||||||
Reference in New Issue
Block a user