mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-13 11:23:50 +00:00
refactor: migrate modal components
This commit is contained in:
committed by
Carlos Valente
parent
36223ff49f
commit
a8ea1080f3
@@ -8,5 +8,8 @@
|
||||
}
|
||||
|
||||
.column {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
@@ -1,17 +1,9 @@
|
||||
import { lazy, useEffect, useRef, useState } from 'react';
|
||||
import {
|
||||
Button,
|
||||
Modal,
|
||||
ModalBody,
|
||||
ModalCloseButton,
|
||||
ModalContent,
|
||||
ModalFooter,
|
||||
ModalHeader,
|
||||
ModalOverlay,
|
||||
} from '@chakra-ui/react';
|
||||
|
||||
import { getCSSContents, postCSSContents, restoreCSSContents } from '../../../../common/api/assets';
|
||||
import Button from '../../../../common/components/buttons/Button';
|
||||
import Info from '../../../../common/components/info/Info';
|
||||
import Modal from '../../../../common/components/modal/Modal';
|
||||
import * as Panel from '../../panel-utils/PanelUtils';
|
||||
|
||||
import style from './StyleEditorModal.module.scss';
|
||||
@@ -27,9 +19,7 @@ interface CSSRef {
|
||||
getCss: () => string;
|
||||
}
|
||||
|
||||
export default function CodeEditorModal(props: CodeEditorModalProps) {
|
||||
const { isOpen, onClose } = props;
|
||||
|
||||
export default function CodeEditorModal({ isOpen, onClose }: CodeEditorModalProps) {
|
||||
const [css, setCSS] = useState('');
|
||||
const [isDirty, setIsDirty] = useState(false);
|
||||
const [saveLoading, setSaveLoading] = useState(false);
|
||||
@@ -84,46 +74,43 @@ export default function CodeEditorModal(props: CodeEditorModalProps) {
|
||||
}, [isOpen]);
|
||||
|
||||
return (
|
||||
<Modal isOpen={isOpen} onClose={onClose} variant='ontime' isCentered>
|
||||
<ModalOverlay />
|
||||
<ModalContent maxWidth='max(800px, 40vw)'>
|
||||
<ModalHeader>Edit CSS override</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
<ModalBody>
|
||||
<CodeEditor ref={cssRef} initialValue={css} language='css' isDirty={isDirty} setIsDirty={setIsDirty} />
|
||||
</ModalBody>
|
||||
|
||||
<ModalFooter className={style.column}>
|
||||
<Modal
|
||||
title='Edit CSS override'
|
||||
isOpen={isOpen}
|
||||
onClose={onClose}
|
||||
showCloseButton
|
||||
showBackdrop
|
||||
bodyElements={
|
||||
<CodeEditor ref={cssRef} initialValue={css} language='css' isDirty={isDirty} setIsDirty={setIsDirty} />
|
||||
}
|
||||
footerElements={
|
||||
<div className={style.column}>
|
||||
<Info>Invalid CSS will be refused by the browser</Info>
|
||||
{error && <Panel.Error className={style.right}>{`Error: ${error}`}</Panel.Error>}
|
||||
<Panel.InlineElements align='apart' className={style.editorActions}>
|
||||
<Button
|
||||
variant='ontime-ghosted'
|
||||
onClick={handleRestore}
|
||||
isDisabled={saveLoading || resetLoading}
|
||||
isLoading={resetLoading}
|
||||
>
|
||||
<Button variant='ghosted' size='large' onClick={handleRestore} disabled={saveLoading || resetLoading}>
|
||||
Reset to example
|
||||
</Button>
|
||||
<Panel.InlineElements>
|
||||
<Button variant='ontime-ghosted' onClick={clear}>
|
||||
<Button variant='ghosted' size='large' onClick={clear}>
|
||||
Clear
|
||||
</Button>
|
||||
<Button variant='ontime-subtle' onClick={onClose}>
|
||||
<Button size='large' onClick={onClose}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
variant='ontime-filled'
|
||||
variant='primary'
|
||||
size='large'
|
||||
onClick={handleSave}
|
||||
isDisabled={saveLoading || resetLoading || !isDirty}
|
||||
isLoading={saveLoading}
|
||||
disabled={saveLoading || resetLoading || !isDirty}
|
||||
loading={saveLoading}
|
||||
>
|
||||
Save changes
|
||||
</Button>
|
||||
</Panel.InlineElements>
|
||||
</Panel.InlineElements>
|
||||
</ModalFooter>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
.scrollContainer {
|
||||
max-height: 70vh;
|
||||
overflow: auto;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
@@ -1,45 +1,35 @@
|
||||
import { Controller, useForm } from 'react-hook-form';
|
||||
import {
|
||||
Button,
|
||||
Input,
|
||||
Modal,
|
||||
ModalBody,
|
||||
ModalCloseButton,
|
||||
ModalContent,
|
||||
ModalFooter,
|
||||
ModalHeader,
|
||||
ModalOverlay,
|
||||
Select,
|
||||
Switch,
|
||||
} from '@chakra-ui/react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { QuickStartData } from 'ontime-types';
|
||||
import { parseUserTime } from 'ontime-utils';
|
||||
|
||||
import { quickProject } from '../../../common/api/db';
|
||||
import { invalidateAllCaches, maybeAxiosError } from '../../../common/api/utils';
|
||||
import Button from '../../../common/components/buttons/Button';
|
||||
import Input from '../../../common/components/input/input/Input';
|
||||
import TimeInput from '../../../common/components/input/time-input/TimeInput';
|
||||
import Modal from '../../../common/components/modal/Modal';
|
||||
import Select from '../../../common/components/select/Select';
|
||||
import Switch from '../../../common/components/switch/Switch';
|
||||
import { editorSettingsDefaults, useEditorSettings } from '../../../common/stores/editorSettings';
|
||||
import * as Panel from '../panel-utils/PanelUtils';
|
||||
|
||||
import { quickStartDefaults } from './quickStart.utils';
|
||||
|
||||
import style from './QuickStart.module.scss';
|
||||
|
||||
interface QuickStartProps {
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
export default function QuickStart(props: QuickStartProps) {
|
||||
const { isOpen, onClose } = props;
|
||||
export default function QuickStart({ isOpen, onClose }: QuickStartProps) {
|
||||
const { defaultWarnTime, defaultDangerTime, setDangerTime, setWarnTime } = useEditorSettings();
|
||||
|
||||
const {
|
||||
control,
|
||||
handleSubmit,
|
||||
register,
|
||||
formState: { errors, isSubmitting, isValid },
|
||||
watch,
|
||||
setError,
|
||||
setValue,
|
||||
} = useForm<QuickStartData>({
|
||||
defaultValues: quickStartDefaults,
|
||||
values: quickStartDefaults,
|
||||
@@ -65,123 +55,114 @@ export default function QuickStart(props: QuickStartProps) {
|
||||
const dangerTimeInMs = parseUserTime(defaultDangerTime);
|
||||
|
||||
return (
|
||||
<Modal isOpen={isOpen} onClose={onClose} closeOnOverlayClick={false} variant='ontime'>
|
||||
<ModalOverlay />
|
||||
<ModalCloseButton />
|
||||
<ModalContent maxWidth='max(640px, 40vw)'>
|
||||
<Modal
|
||||
isOpen={isOpen}
|
||||
onClose={onClose}
|
||||
showBackdrop
|
||||
showCloseButton
|
||||
title='Create new project...'
|
||||
bodyElements={
|
||||
<form onSubmit={handleSubmit(onSubmit)} id='quick-start'>
|
||||
<ModalHeader>Create new project...</ModalHeader>
|
||||
<ModalBody className={style.scrollContainer}>
|
||||
<ModalCloseButton />
|
||||
<Panel.ListGroup>
|
||||
<Panel.ListItem>
|
||||
<Panel.Field title='Project title' description='Shown as the title in some views' />
|
||||
<Input
|
||||
variant='ontime-filled'
|
||||
size='sm'
|
||||
maxLength={150}
|
||||
placeholder='Project title'
|
||||
autoComplete='off'
|
||||
width='20rem'
|
||||
{...register('project.title')}
|
||||
/>
|
||||
</Panel.ListItem>
|
||||
<Panel.ListItem>
|
||||
<Panel.Field
|
||||
title='Time format'
|
||||
description='Default time format to show in views 12 /24 hours'
|
||||
error={errors.settings?.timeFormat?.message}
|
||||
/>
|
||||
<Select variant='ontime' size='sm' width='auto' isDisabled={false} {...register('settings.timeFormat')}>
|
||||
<option value='12'>12 hours 11:00:10 PM</option>
|
||||
<option value='24'>24 hours 23:00:10</option>
|
||||
</Select>
|
||||
</Panel.ListItem>
|
||||
<Panel.ListItem>
|
||||
<Panel.Field
|
||||
title='Views language'
|
||||
description='Language to be displayed in views'
|
||||
error={errors.settings?.language?.message}
|
||||
/>
|
||||
<Select variant='ontime' size='sm' width='auto' isDisabled={false} {...register('settings.language')}>
|
||||
<option value='en'>English</option>
|
||||
<option value='fr'>French</option>
|
||||
<option value='de'>German</option>
|
||||
<option value='hu'>Hungarian</option>
|
||||
<option value='it'>Italian</option>
|
||||
<option value='no'>Norwegian</option>
|
||||
<option value='pt'>Portuguese</option>
|
||||
<option value='es'>Spanish</option>
|
||||
<option value='sv'>Swedish</option>
|
||||
<option value='pl'>Polish</option>
|
||||
<option value='zh'>Chinese (Simplified)</option>
|
||||
</Select>
|
||||
</Panel.ListItem>
|
||||
</Panel.ListGroup>
|
||||
<Panel.ListGroup>
|
||||
<Panel.ListItem>
|
||||
<Panel.Field title='Project title' description='Shown as the title in some views' />
|
||||
<Input maxLength={150} placeholder='Project title' fluid {...register('project.title')} />
|
||||
</Panel.ListItem>
|
||||
<Panel.ListItem>
|
||||
<Panel.Field
|
||||
title='Time format'
|
||||
description='Default time format to show in views 12 /24 hours'
|
||||
error={errors.settings?.timeFormat?.message}
|
||||
/>
|
||||
<Select
|
||||
{...register('settings.timeFormat')}
|
||||
defaultValue='24'
|
||||
options={[
|
||||
{ value: '12', label: '12 hours 11:00:10 PM' },
|
||||
{ value: '24', label: '24 hours 23:00:10' },
|
||||
]}
|
||||
/>
|
||||
</Panel.ListItem>
|
||||
<Panel.ListItem>
|
||||
<Panel.Field
|
||||
title='Views language'
|
||||
description='Language to be displayed in views'
|
||||
error={errors.settings?.language?.message}
|
||||
/>
|
||||
<Select
|
||||
{...register('settings.language')}
|
||||
defaultValue='en'
|
||||
options={[
|
||||
{ value: 'en', label: 'English' },
|
||||
{ value: 'fr', label: 'French' },
|
||||
{ value: 'de', label: 'German' },
|
||||
{ value: 'hu', label: 'Hungarian' },
|
||||
{ value: 'it', label: 'Italian' },
|
||||
{ value: 'no', label: 'Norwegian' },
|
||||
{ value: 'pt', label: 'Portuguese' },
|
||||
{ value: 'es', label: 'Spanish' },
|
||||
{ value: 'sv', label: 'Swedish' },
|
||||
{ value: 'pl', label: 'Polish' },
|
||||
{ value: 'zh', label: 'Chinese (Simplified)' },
|
||||
]}
|
||||
/>
|
||||
</Panel.ListItem>
|
||||
</Panel.ListGroup>
|
||||
|
||||
<Panel.ListGroup>
|
||||
<Panel.ListItem>
|
||||
<Panel.Field title='Warning time' description='Default threshold for warning time in an event' />
|
||||
<TimeInput<'warnTime'>
|
||||
name='warnTime'
|
||||
submitHandler={(_field, value) => setWarnTime(value)}
|
||||
time={warnTimeInMs}
|
||||
placeholder={editorSettingsDefaults.warnTime}
|
||||
/>
|
||||
</Panel.ListItem>
|
||||
<Panel.ListItem>
|
||||
<Panel.Field title='Danger time' description='Default threshold for danger time in an event' />
|
||||
<TimeInput<'dangerTime'>
|
||||
name='dangerTime'
|
||||
submitHandler={(_field, value) => setDangerTime(value)}
|
||||
time={dangerTimeInMs}
|
||||
placeholder={editorSettingsDefaults.dangerTime}
|
||||
/>
|
||||
</Panel.ListItem>
|
||||
</Panel.ListGroup>
|
||||
<Panel.ListGroup>
|
||||
<Panel.ListItem>
|
||||
<Panel.Field title='Warning time' description='Default threshold for warning time in an event' />
|
||||
<TimeInput<'warnTime'>
|
||||
name='warnTime'
|
||||
submitHandler={(_field, value) => setWarnTime(value)}
|
||||
time={warnTimeInMs}
|
||||
placeholder={editorSettingsDefaults.warnTime}
|
||||
/>
|
||||
</Panel.ListItem>
|
||||
<Panel.ListItem>
|
||||
<Panel.Field title='Danger time' description='Default threshold for danger time in an event' />
|
||||
<TimeInput<'dangerTime'>
|
||||
name='dangerTime'
|
||||
submitHandler={(_field, value) => setDangerTime(value)}
|
||||
time={dangerTimeInMs}
|
||||
placeholder={editorSettingsDefaults.dangerTime}
|
||||
/>
|
||||
</Panel.ListItem>
|
||||
</Panel.ListGroup>
|
||||
|
||||
<Panel.ListGroup>
|
||||
<Panel.ListItem>
|
||||
<Panel.Field
|
||||
title='Freeze timer on end'
|
||||
description='When a timer hits 00:00:00, it freezes instead of going negative. It invalidates the End Message.'
|
||||
/>
|
||||
<Controller
|
||||
control={control}
|
||||
name='viewSettings.freezeEnd'
|
||||
render={({ field: { onChange, value, ref } }) => (
|
||||
<Switch variant='ontime' size='lg' isChecked={value} onChange={onChange} ref={ref} />
|
||||
)}
|
||||
/>
|
||||
</Panel.ListItem>
|
||||
<Panel.ListItem>
|
||||
<Panel.Field
|
||||
title='End message'
|
||||
description='Message for negative timers; applies only if the timer isn`t frozen on End. If no message is provided, it continues into negative time'
|
||||
/>
|
||||
<Input
|
||||
size='sm'
|
||||
autoComplete='off'
|
||||
variant='ontime-filled'
|
||||
maxLength={150}
|
||||
width='20rem'
|
||||
placeholder='Shown when timer reaches end'
|
||||
{...register('viewSettings.endMessage')}
|
||||
/>
|
||||
</Panel.ListItem>
|
||||
</Panel.ListGroup>
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
{errors?.root && <Panel.Error>{errors.root.message}</Panel.Error>}
|
||||
<Button variant='ontime-ghosted' size='md' onClick={onClose} isDisabled={false}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button variant='ontime-filled' size='md' type='submit' isDisabled={!isValid} isLoading={isSubmitting}>
|
||||
Create project
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
<Panel.ListGroup>
|
||||
<Panel.ListItem>
|
||||
<Panel.Field
|
||||
title='Freeze timer on end'
|
||||
description='When a timer hits 00:00:00, it freezes instead of going negative. It invalidates the End Message.'
|
||||
/>
|
||||
<Switch
|
||||
name='viewSettings.freezeEnd'
|
||||
checked={watch('viewSettings.freezeEnd')}
|
||||
onCheckedChange={(checked) => setValue('viewSettings.freezeEnd', checked)}
|
||||
/>
|
||||
</Panel.ListItem>
|
||||
<Panel.ListItem>
|
||||
<Panel.Field
|
||||
title='End message'
|
||||
description='Message for negative timers; applies only if the timer isn`t frozen on End. If no message is provided, it continues into negative time'
|
||||
/>
|
||||
<Input maxLength={150} fluid placeholder='eg: Time is up!' {...register('viewSettings.endMessage')} />
|
||||
</Panel.ListItem>
|
||||
</Panel.ListGroup>
|
||||
</form>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
}
|
||||
footerElements={
|
||||
<>
|
||||
{errors?.root && <Panel.Error>{errors.root.message}</Panel.Error>}
|
||||
<Button variant='ghosted' onClick={onClose} disabled={false}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button variant='primary' type='submit' form='quick-start' disabled={!isValid} loading={isSubmitting}>
|
||||
Create project
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user