mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-21 06:59:09 +00:00
cleanup + lint
This commit is contained in:
+1
-4
@@ -11,16 +11,13 @@
|
|||||||
"@testing-library/react": "^11.1.0",
|
"@testing-library/react": "^11.1.0",
|
||||||
"@testing-library/user-event": "^12.1.10",
|
"@testing-library/user-event": "^12.1.10",
|
||||||
"date-fns": "^2.19.0",
|
"date-fns": "^2.19.0",
|
||||||
"formik": "^2.2.6",
|
|
||||||
"framer-motion": "^4",
|
"framer-motion": "^4",
|
||||||
"react": "^17.0.1",
|
"react": "^17.0.1",
|
||||||
"react-datepicker": "^3.6.0",
|
|
||||||
"react-dom": "^17.0.1",
|
"react-dom": "^17.0.1",
|
||||||
"react-router": "^5.2.0",
|
"react-router": "^5.2.0",
|
||||||
"react-router-dom": "^5.2.0",
|
"react-router-dom": "^5.2.0",
|
||||||
"react-scripts": "4.0.3",
|
"react-scripts": "4.0.3",
|
||||||
"web-vitals": "^1.0.1",
|
"web-vitals": "^1.0.1"
|
||||||
"yup": "^0.32.9"
|
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "react-scripts start",
|
"start": "react-scripts start",
|
||||||
|
|||||||
@@ -10,16 +10,12 @@ function App() {
|
|||||||
return (
|
return (
|
||||||
<PresenterMessageProvider>
|
<PresenterMessageProvider>
|
||||||
<EventProvider>
|
<EventProvider>
|
||||||
|
|
||||||
<div className='App'>
|
<div className='App'>
|
||||||
<Route path='/' exact component={DefaultPresenter} />
|
<Route path='/' exact component={DefaultPresenter} />
|
||||||
|
|
||||||
<EventListProvider>
|
<EventListProvider>
|
||||||
<Route path='/editor' exact component={Editor} />
|
<Route path='/editor' exact component={Editor} />
|
||||||
</EventListProvider>
|
</EventListProvider>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</EventProvider>
|
</EventProvider>
|
||||||
</PresenterMessageProvider>
|
</PresenterMessageProvider>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import styles from './SmallTimer.module.css';
|
import styles from './SmallTimer.module.css';
|
||||||
|
|
||||||
export default function SmallTimer({label, time}) {
|
export default function SmallTimer({ label, time }) {
|
||||||
return (
|
return (
|
||||||
<div className={styles.SmallTimer}>
|
<div className={styles.SmallTimer}>
|
||||||
<div className={styles.label}>{label}</div>
|
<div className={styles.label}>{label}</div>
|
||||||
|
|||||||
@@ -19,4 +19,4 @@ export default function ChakraInput(props) {
|
|||||||
}}
|
}}
|
||||||
</Field>
|
</Field>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,38 +0,0 @@
|
|||||||
import { FormErrorMessage } from '@chakra-ui/form-control';
|
|
||||||
import { FormLabel } from '@chakra-ui/form-control';
|
|
||||||
import { FormControl } from '@chakra-ui/form-control';
|
|
||||||
import { NumberInputStepper } from '@chakra-ui/number-input';
|
|
||||||
import { NumberInputField } from '@chakra-ui/number-input';
|
|
||||||
import { NumberDecrementStepper } from '@chakra-ui/number-input';
|
|
||||||
import { NumberIncrementStepper } from '@chakra-ui/number-input';
|
|
||||||
import { NumberInput } from '@chakra-ui/number-input';
|
|
||||||
import { Field } from 'formik';
|
|
||||||
|
|
||||||
export default function ChakraNumberInput(props) {
|
|
||||||
const { label, name, ...rest } = props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Field name={name}>
|
|
||||||
{({ field, form }) => {
|
|
||||||
return (
|
|
||||||
<FormControl isInvalid={form.errors[name] && form.touched[name]}>
|
|
||||||
<FormLabel htmlFor={name}>{label}</FormLabel>
|
|
||||||
<NumberInput
|
|
||||||
defaultValue={field.value}
|
|
||||||
{...rest}
|
|
||||||
onChange={(val) => form.setFieldValue(field.name, val)}
|
|
||||||
>
|
|
||||||
<NumberInputField id={name} {...field} />
|
|
||||||
<NumberInputStepper>
|
|
||||||
<NumberIncrementStepper />
|
|
||||||
<NumberDecrementStepper />
|
|
||||||
</NumberInputStepper>
|
|
||||||
</NumberInput>
|
|
||||||
|
|
||||||
<FormErrorMessage>{form.errors[name]}</FormErrorMessage>
|
|
||||||
</FormControl>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
</Field>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
import { FormLabel } from '@chakra-ui/form-control';
|
|
||||||
import { Text } from '@chakra-ui/layout';
|
|
||||||
import {
|
|
||||||
NumberDecrementStepper,
|
|
||||||
NumberIncrementStepper,
|
|
||||||
NumberInput,
|
|
||||||
NumberInputField,
|
|
||||||
NumberInputStepper,
|
|
||||||
} from '@chakra-ui/number-input';
|
|
||||||
import styles from './TimeInput.module.css';
|
|
||||||
|
|
||||||
export default function SingleTimeInput(props) {
|
|
||||||
return (
|
|
||||||
<div className={styles.container}>
|
|
||||||
<FormLabel>{props.label}</FormLabel>
|
|
||||||
<Text className={styles.label}>min</Text>
|
|
||||||
<div className={styles.timeInput}>
|
|
||||||
<NumberInput min={0} max={60} maxW={20} allowMouseWheel>
|
|
||||||
<NumberInputField />
|
|
||||||
<NumberInputStepper>
|
|
||||||
<NumberIncrementStepper />
|
|
||||||
<NumberDecrementStepper />
|
|
||||||
</NumberInputStepper>
|
|
||||||
</NumberInput>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
import { FormErrorMessage } from '@chakra-ui/form-control';
|
|
||||||
import { FormLabel } from '@chakra-ui/form-control';
|
|
||||||
import { FormControl } from '@chakra-ui/form-control';
|
|
||||||
import DatePicker from 'react-datepicker';
|
|
||||||
import { Field } from 'formik';
|
|
||||||
import 'react-datepicker/dist/react-datepicker.css';
|
|
||||||
import './timeInput.css';
|
|
||||||
|
|
||||||
export default function TimeInput(props) {
|
|
||||||
const { label, name, ...rest } = props;
|
|
||||||
return (
|
|
||||||
<Field name={name}>
|
|
||||||
{({ field, form }) => {
|
|
||||||
const { setFieldValue } = form;
|
|
||||||
const { value } = field;
|
|
||||||
return (
|
|
||||||
<FormControl isInvalid={form.errors[name] && form.touched[name]}>
|
|
||||||
<FormLabel htmlFor={name}>{label}</FormLabel>
|
|
||||||
<DatePicker
|
|
||||||
id={name}
|
|
||||||
{...field}
|
|
||||||
{...rest}
|
|
||||||
showTimeSelect
|
|
||||||
showTimeSelectOnly
|
|
||||||
timeIntervals={15}
|
|
||||||
dateFormat='hh:mm'
|
|
||||||
selected={value}
|
|
||||||
onChange={(val) => setFieldValue(name, val)}
|
|
||||||
/>
|
|
||||||
<FormErrorMessage>{form.errors[name]}</FormErrorMessage>
|
|
||||||
</FormControl>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
</Field>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
.container {
|
|
||||||
padding-right: 1em;
|
|
||||||
padding-top: 2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.timeInput {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.label {
|
|
||||||
font-size: 0.9em;
|
|
||||||
color: #666;
|
|
||||||
}
|
|
||||||
|
|
||||||
.spacer {
|
|
||||||
width: 0.25em
|
|
||||||
}
|
|
||||||
@@ -1,122 +0,0 @@
|
|||||||
.react-datepicker {
|
|
||||||
font-family: unset;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.react-datepicker-wrapper,
|
|
||||||
.react-datepicker__input-container {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.react-datepicker-popper {
|
|
||||||
background-color: white;
|
|
||||||
}
|
|
||||||
.react-datepicker__input-container {
|
|
||||||
font-size: 1rem;
|
|
||||||
padding-left: 1rem;
|
|
||||||
padding-right: 1rem;
|
|
||||||
height: 2.5rem;
|
|
||||||
border-radius: 0.25rem;
|
|
||||||
border: 1px solid;
|
|
||||||
border-color: hsl(0,0%,80%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.react-datepicker__input-container:hover {
|
|
||||||
border-color: hsl(0,0%,70%);
|
|
||||||
}
|
|
||||||
.react-datepicker__input-container:focus-within {
|
|
||||||
z-index: 1;
|
|
||||||
border-color: #3182ce;
|
|
||||||
box-shadow: 0 0 0 1px #3182ce;
|
|
||||||
}
|
|
||||||
|
|
||||||
.react-datepicker__input-container > input {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
outline: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.react-datepicker__navigation--next--with-time:not(.react-datepicker__navigation--next--with-today-button) {
|
|
||||||
right: 90px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.react-datepicker__navigation--previous,
|
|
||||||
.react-datepicker__navigation--next {
|
|
||||||
height: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.react-datepicker__navigation--previous {
|
|
||||||
border-right-color: #cbd5e0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.react-datepicker__navigation--previous:hover {
|
|
||||||
border-right-color: #a0aec0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.react-datepicker__navigation--next {
|
|
||||||
border-left-color: #cbd5e0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.react-datepicker__navigation--next:hover {
|
|
||||||
border-left-color: #a0aec0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.react-datepicker__header {
|
|
||||||
background: #f7fafc;
|
|
||||||
}
|
|
||||||
|
|
||||||
.react-datepicker__header,
|
|
||||||
.react-datepicker__time-container {
|
|
||||||
border-color: #E2E8F0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.react-datepicker__current-month,
|
|
||||||
.react-datepicker-time__header,
|
|
||||||
.react-datepicker-year-header {
|
|
||||||
font-size: inherit;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
.react-datepicker__time-container .react-datepicker__time .react-datepicker__time-box ul.react-datepicker__time-list li.react-datepicker__time-list-item {
|
|
||||||
margin: 0 1px 0 0;
|
|
||||||
height: auto;
|
|
||||||
padding: 7px 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.react-datepicker__time-container .react-datepicker__time .react-datepicker__time-box ul.react-datepicker__time-list li.react-datepicker__time-list-item:hover {
|
|
||||||
background: #edf2f7;
|
|
||||||
}
|
|
||||||
|
|
||||||
.react-datepicker__day:hover {
|
|
||||||
background: #edf2f7;
|
|
||||||
}
|
|
||||||
|
|
||||||
.react-datepicker__day--selected,
|
|
||||||
.react-datepicker__day--in-selecting-range,
|
|
||||||
.react-datepicker__day--in-range,
|
|
||||||
.react-datepicker__month-text--selected,
|
|
||||||
.react-datepicker__month-text--in-selecting-range,
|
|
||||||
.react-datepicker__month-text--in-range,
|
|
||||||
.react-datepicker__time-container .react-datepicker__time .react-datepicker__time-box ul.react-datepicker__time-list li.react-datepicker__time-list-item--selected {
|
|
||||||
background: #3182ce;
|
|
||||||
font-weight: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
.react-datepicker__time-container .react-datepicker__time .react-datepicker__time-box ul.react-datepicker__time-list li.react-datepicker__time-list-item--selected:hover {
|
|
||||||
background: #2a69ac;
|
|
||||||
}
|
|
||||||
|
|
||||||
.react-datepicker__close-icon::after {
|
|
||||||
background-color: unset;
|
|
||||||
border-radius: unset;
|
|
||||||
font-size: 1.5rem;
|
|
||||||
font-weight: bold;
|
|
||||||
color: hsl(0,0%,80%);
|
|
||||||
height: 20px;
|
|
||||||
width: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.react-datepicker__close-icon::after:hover {
|
|
||||||
color: hsl(0,0%,70%)
|
|
||||||
}
|
|
||||||
@@ -2,25 +2,17 @@ import { Button } from '@chakra-ui/button';
|
|||||||
import style from './PlaybackControl.module.css';
|
import style from './PlaybackControl.module.css';
|
||||||
import Countdown from '../../common/components/countdown/Countdown';
|
import Countdown from '../../common/components/countdown/Countdown';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { clamp } from '../../app/utils';
|
|
||||||
import { ArrowBackIcon, ArrowForwardIcon } from '@chakra-ui/icons';
|
import { ArrowBackIcon, ArrowForwardIcon } from '@chakra-ui/icons';
|
||||||
|
|
||||||
export default function PlaybackControl() {
|
export default function PlaybackControl() {
|
||||||
const [time, setTime] = useState(15);
|
const [time] = useState(15);
|
||||||
const [roll, setRoll] = useState(false);
|
const [roll, setRoll] = useState(false);
|
||||||
|
|
||||||
const incrementTimer = (amount = 1) => {
|
|
||||||
const t = clamp(time + amount * 60, 0, 3600);
|
|
||||||
setTime(t);
|
|
||||||
};
|
|
||||||
|
|
||||||
const defProps = {
|
const defProps = {
|
||||||
colorScheme: 'blackAlpha',
|
colorScheme: 'blackAlpha',
|
||||||
variant: 'outline',
|
variant: 'outline',
|
||||||
};
|
};
|
||||||
|
|
||||||
const smallSize = 50;
|
|
||||||
const midSize = 100;
|
|
||||||
const bigSize = 120;
|
const bigSize = 120;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -29,44 +21,7 @@ export default function PlaybackControl() {
|
|||||||
<div className={style.timer}>
|
<div className={style.timer}>
|
||||||
<Countdown time={time} small />
|
<Countdown time={time} small />
|
||||||
</div>
|
</div>
|
||||||
{/* <Button
|
|
||||||
width={smallSize}
|
|
||||||
{...defProps}
|
|
||||||
className={style.minu1}
|
|
||||||
disabled={roll}
|
|
||||||
onClick={() => incrementTimer(-1)}
|
|
||||||
>
|
|
||||||
-1
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
width={smallSize}
|
|
||||||
{...defProps}
|
|
||||||
className={style.plus1}
|
|
||||||
disabled={roll}
|
|
||||||
onClick={() => incrementTimer()}
|
|
||||||
>
|
|
||||||
+1
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
width={smallSize}
|
|
||||||
{...defProps}
|
|
||||||
className={style.minu5}
|
|
||||||
disabled={roll}
|
|
||||||
onClick={() => incrementTimer(5)}
|
|
||||||
>
|
|
||||||
-5
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
width={smallSize}
|
|
||||||
{...defProps}
|
|
||||||
className={style.plus5}
|
|
||||||
disabled={roll}
|
|
||||||
onClick={() => incrementTimer(5)}
|
|
||||||
>
|
|
||||||
+5
|
|
||||||
</Button> */}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={style.playbackContainer}>
|
<div className={style.playbackContainer}>
|
||||||
<Button
|
<Button
|
||||||
width={bigSize}
|
width={bigSize}
|
||||||
@@ -84,14 +39,6 @@ export default function PlaybackControl() {
|
|||||||
>
|
>
|
||||||
Pause
|
Pause
|
||||||
</Button>
|
</Button>
|
||||||
{/* <Button
|
|
||||||
width={bigSize}
|
|
||||||
colorScheme='yellow'
|
|
||||||
className={style.reset}
|
|
||||||
disabled={roll}
|
|
||||||
>
|
|
||||||
Reset
|
|
||||||
</Button> */}
|
|
||||||
</div>
|
</div>
|
||||||
<div className={style.trackContainer}>
|
<div className={style.trackContainer}>
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
@@ -35,9 +35,9 @@
|
|||||||
grid-area: minu5;
|
grid-area: minu5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.playbackContainer, .trackContainer {
|
.playbackContainer,
|
||||||
|
.trackContainer {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-evenly;
|
justify-content: space-evenly;
|
||||||
padding-top: 0.5em;
|
padding-top: 0.5em;
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Button } from '@chakra-ui/button';
|
import { IconButton } from '@chakra-ui/button';
|
||||||
import { ArrowForwardIcon } from '@chakra-ui/icons';
|
import { SettingsIcon } from '@chakra-ui/icons';
|
||||||
import { Grid, GridItem, Heading } from '@chakra-ui/layout';
|
import { Grid, GridItem, Heading } from '@chakra-ui/layout';
|
||||||
import { Box } from '@chakra-ui/layout';
|
import { Box } from '@chakra-ui/layout';
|
||||||
import { useContext } from 'react';
|
import { useContext } from 'react';
|
||||||
@@ -7,7 +7,6 @@ import { useEffect, useState } from 'react';
|
|||||||
import { EventContext } from '../../app/context/eventContext';
|
import { EventContext } from '../../app/context/eventContext';
|
||||||
import NumberedText from '../../common/components/text/NumberedText';
|
import NumberedText from '../../common/components/text/NumberedText';
|
||||||
import PlaybackControl from '../control/PlaybackControl';
|
import PlaybackControl from '../control/PlaybackControl';
|
||||||
import EventForm from '../form/EventForm';
|
|
||||||
import MessageForm from '../form/MessageForm';
|
import MessageForm from '../form/MessageForm';
|
||||||
import PreviewContainer from '../viewers/PreviewContainer';
|
import PreviewContainer from '../viewers/PreviewContainer';
|
||||||
import styles from './Editor.module.css';
|
import styles from './Editor.module.css';
|
||||||
@@ -34,11 +33,10 @@ export default function Editor() {
|
|||||||
>
|
>
|
||||||
<GridItem rowSpan={3}>
|
<GridItem rowSpan={3}>
|
||||||
<Box className={styles.editor} borderRadius='0.5em'>
|
<Box className={styles.editor} borderRadius='0.5em'>
|
||||||
<Heading style={{ paddingBottom: '0.25em' }}>Event List</Heading>
|
<Heading size='lg' style={{ paddingBottom: '0.25em' }}>
|
||||||
<NumberedText
|
Event List
|
||||||
number={1}
|
</Heading>
|
||||||
text={'Manage and select event to run'}
|
<NumberedText number={1} text={'Manage and select event to run'} />
|
||||||
/>
|
|
||||||
<div className={styles.content}>
|
<div className={styles.content}>
|
||||||
<EventList formMode={formMode} setFormMode={setFormMode} />
|
<EventList formMode={formMode} setFormMode={setFormMode} />
|
||||||
</div>
|
</div>
|
||||||
@@ -47,7 +45,9 @@ export default function Editor() {
|
|||||||
|
|
||||||
<GridItem colStart={2} rowStart={2} rowSpan={2} colSpan={2}>
|
<GridItem colStart={2} rowStart={2} rowSpan={2} colSpan={2}>
|
||||||
<Box className={styles.editor} borderRadius='0.5em' overflowX='auto'>
|
<Box className={styles.editor} borderRadius='0.5em' overflowX='auto'>
|
||||||
<Heading style={{ paddingBottom: '0.25em' }}>Preview Displays</Heading>
|
<Heading size='lg' style={{ paddingBottom: '0.25em' }}>
|
||||||
|
Preview Displays
|
||||||
|
</Heading>
|
||||||
<NumberedText number={4} text={'Realtime screen preview'} />
|
<NumberedText number={4} text={'Realtime screen preview'} />
|
||||||
<div className={styles.content}>
|
<div className={styles.content}>
|
||||||
<PreviewContainer />
|
<PreviewContainer />
|
||||||
@@ -57,8 +57,13 @@ export default function Editor() {
|
|||||||
|
|
||||||
<GridItem colStart={2} rowStart={1} rowSpan={1} colSpan={1}>
|
<GridItem colStart={2} rowStart={1} rowSpan={1} colSpan={1}>
|
||||||
<Box className={styles.editor} borderRadius='0.5em'>
|
<Box className={styles.editor} borderRadius='0.5em'>
|
||||||
<Heading style={{ paddingBottom: '0.25em' }}>Display Messages</Heading>
|
<Heading size='lg' style={{ paddingBottom: '0.25em' }}>
|
||||||
<NumberedText number={2} text={'Show realtime messages on separate screen types'} />
|
Display Messages
|
||||||
|
</Heading>
|
||||||
|
<NumberedText
|
||||||
|
number={2}
|
||||||
|
text={'Show realtime messages on separate screen types'}
|
||||||
|
/>
|
||||||
<div className={styles.content}></div>
|
<div className={styles.content}></div>
|
||||||
<MessageForm />
|
<MessageForm />
|
||||||
</Box>
|
</Box>
|
||||||
@@ -66,7 +71,9 @@ export default function Editor() {
|
|||||||
|
|
||||||
<GridItem colStart={3} rowStart={1}>
|
<GridItem colStart={3} rowStart={1}>
|
||||||
<Box className={styles.editor} borderRadius='0.5em'>
|
<Box className={styles.editor} borderRadius='0.5em'>
|
||||||
<Heading style={{ paddingBottom: '0.25em' }}>Time Control</Heading>
|
<Heading size='lg' style={{ paddingBottom: '0.25em' }}>
|
||||||
|
Time Control
|
||||||
|
</Heading>
|
||||||
<NumberedText number={3} text={'Control Timer'} />
|
<NumberedText number={3} text={'Control Timer'} />
|
||||||
<div className={styles.content}></div>
|
<div className={styles.content}></div>
|
||||||
<PlaybackControl />
|
<PlaybackControl />
|
||||||
@@ -74,7 +81,67 @@ export default function Editor() {
|
|||||||
</GridItem>
|
</GridItem>
|
||||||
|
|
||||||
<GridItem colStart={4} rowSpan={3}>
|
<GridItem colStart={4} rowSpan={3}>
|
||||||
<Box className={styles.editor} borderRadius='0.5em'>S</Box>
|
<Box className={styles.editor} borderRadius='0.5em'>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
alignItems: 'center',
|
||||||
|
gap: '2em',
|
||||||
|
paddingTop: '3em',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<IconButton icon={<SettingsIcon />} isRound variant='outline' />
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: 35,
|
||||||
|
height: 35,
|
||||||
|
backgroundColor: '#3b8cd8',
|
||||||
|
borderRadius: '50%',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: 35,
|
||||||
|
height: 35,
|
||||||
|
backgroundColor: '#3182ce',
|
||||||
|
borderRadius: '50%',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: 35,
|
||||||
|
height: 35,
|
||||||
|
backgroundColor: '#2778c4',
|
||||||
|
borderRadius: '50%',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: 35,
|
||||||
|
height: 35,
|
||||||
|
backgroundColor: '#1d6eba',
|
||||||
|
borderRadius: '50%',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: 35,
|
||||||
|
height: 35,
|
||||||
|
backgroundColor: '#1364b0',
|
||||||
|
borderRadius: '50%',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: 35,
|
||||||
|
height: 35,
|
||||||
|
backgroundColor: '#095aa6',
|
||||||
|
borderRadius: '50%',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Box>
|
||||||
</GridItem>
|
</GridItem>
|
||||||
</Grid>
|
</Grid>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
margin-top: 1.5vh;
|
margin-top: 1.5vh;
|
||||||
background-color: #fcfcfa;
|
background-color: #fcfcfa;
|
||||||
|
/* 011627 */
|
||||||
padding: 1em 1.5em;
|
padding: 1em 1.5em;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { IconButton } from '@chakra-ui/button';
|
import { IconButton } from '@chakra-ui/button';
|
||||||
import { AddIcon, MinusIcon } from '@chakra-ui/icons';
|
import { AddIcon, MinusIcon } from '@chakra-ui/icons';
|
||||||
import { Box } from '@chakra-ui/layout';
|
import { Box } from '@chakra-ui/layout';
|
||||||
import { useNumberInput } from '@chakra-ui/number-input';
|
|
||||||
import {
|
import {
|
||||||
Slider,
|
Slider,
|
||||||
SliderFilledTrack,
|
SliderFilledTrack,
|
||||||
|
|||||||
@@ -1,17 +1,29 @@
|
|||||||
import { AddIcon, AttachmentIcon, DownloadIcon } from '@chakra-ui/icons';
|
import {
|
||||||
import { Button, IconButton } from '@chakra-ui/react';
|
AddIcon,
|
||||||
|
AttachmentIcon,
|
||||||
|
ChevronDownIcon,
|
||||||
|
DownloadIcon,
|
||||||
|
} from '@chakra-ui/icons';
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
ButtonGroup,
|
||||||
|
IconButton,
|
||||||
|
Menu,
|
||||||
|
MenuButton,
|
||||||
|
MenuItem,
|
||||||
|
MenuList,
|
||||||
|
} from '@chakra-ui/react';
|
||||||
import { useContext } from 'react';
|
import { useContext } from 'react';
|
||||||
import { EventContext } from '../../../app/context/eventContext';
|
import { EventContext } from '../../../app/context/eventContext';
|
||||||
import { EventListContext } from '../../../app/context/eventListContext';
|
import { EventListContext } from '../../../app/context/eventListContext';
|
||||||
import EventListItem from './EventListItem';
|
import EventListItem from './EventListItem';
|
||||||
import { sortByOrderVal } from './listUtils';
|
|
||||||
import style from './List.module.css';
|
import style from './List.module.css';
|
||||||
import DelayBlock from './DelayBlock';
|
import DelayBlock from './DelayBlock';
|
||||||
import BlockBlock from './BlockBlock';
|
import BlockBlock from './BlockBlock';
|
||||||
|
|
||||||
export default function EventList(props) {
|
export default function EventList() {
|
||||||
const [events, setEvents] = useContext(EventListContext);
|
const [events, setEvents] = useContext(EventListContext);
|
||||||
const [event, setEvent] = useContext(EventContext);
|
const [event] = useContext(EventContext);
|
||||||
|
|
||||||
const selected = event?.id || -1;
|
const selected = event?.id || -1;
|
||||||
|
|
||||||
@@ -100,19 +112,51 @@ export default function EventList(props) {
|
|||||||
const updateData = (itemIndex, data) => {
|
const updateData = (itemIndex, data) => {
|
||||||
const newEvents = replaceAt(events, itemIndex, data);
|
const newEvents = replaceAt(events, itemIndex, data);
|
||||||
setEvents(newEvents);
|
setEvents(newEvents);
|
||||||
}
|
};
|
||||||
|
|
||||||
console.log('events in event list', events);
|
console.log('events in event list', events);
|
||||||
let cumulativeDelay = 0;
|
let cumulativeDelay = 0;
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={style.headerButtons}>
|
<div className={style.headerButtons}>
|
||||||
<Button size='sm' rightIcon={<AttachmentIcon />} disabled>
|
<Menu>
|
||||||
Upload
|
<ButtonGroup isAttached>
|
||||||
</Button>
|
<Button size='sm' variant='outline'>
|
||||||
<Button size='sm' rightIcon={<DownloadIcon />} disabled>
|
Upload
|
||||||
Download
|
</Button>
|
||||||
</Button>
|
<MenuButton
|
||||||
|
as={Button}
|
||||||
|
leftIcon={<AttachmentIcon />}
|
||||||
|
size='sm'
|
||||||
|
variant='outline'
|
||||||
|
>
|
||||||
|
<ChevronDownIcon />
|
||||||
|
</MenuButton>
|
||||||
|
</ButtonGroup>
|
||||||
|
<MenuList>
|
||||||
|
<MenuItem>Upload Excel</MenuItem>
|
||||||
|
<MenuItem>Upload CSV</MenuItem>
|
||||||
|
</MenuList>
|
||||||
|
</Menu>
|
||||||
|
<Menu>
|
||||||
|
<ButtonGroup isAttached>
|
||||||
|
<Button size='sm' variant='outline'>
|
||||||
|
Save
|
||||||
|
</Button>
|
||||||
|
<MenuButton
|
||||||
|
as={Button}
|
||||||
|
leftIcon={<DownloadIcon />}
|
||||||
|
size='sm'
|
||||||
|
variant='outline'
|
||||||
|
>
|
||||||
|
<ChevronDownIcon />
|
||||||
|
</MenuButton>
|
||||||
|
</ButtonGroup>
|
||||||
|
<MenuList>
|
||||||
|
<MenuItem>Download Excel</MenuItem>
|
||||||
|
<MenuItem>Download CSV</MenuItem>
|
||||||
|
</MenuList>
|
||||||
|
</Menu>
|
||||||
<IconButton
|
<IconButton
|
||||||
size='sm'
|
size='sm'
|
||||||
icon={<AddIcon />}
|
icon={<AddIcon />}
|
||||||
|
|||||||
@@ -1,159 +0,0 @@
|
|||||||
import { Button } from '@chakra-ui/button';
|
|
||||||
import { Form, Formik } from 'formik';
|
|
||||||
import { useContext, useEffect, useState } from 'react';
|
|
||||||
import DatePicker from 'react-datepicker';
|
|
||||||
import * as Yup from 'yup';
|
|
||||||
import { EventContext } from '../../app/context/eventContext';
|
|
||||||
import { EventListContext } from '../../app/context/eventListContext';
|
|
||||||
import ChakraInput from '../../common/input/ChakraInput';
|
|
||||||
import ChakraNumberInput from '../../common/input/ChakraNumberInput';
|
|
||||||
import TimeInput from '../../common/input/TimeInput';
|
|
||||||
import styles from './EventForm.module.css';
|
|
||||||
import 'react-datepicker/dist/react-datepicker-cssmodules.css';
|
|
||||||
import ReactDatePicker from 'react-datepicker';
|
|
||||||
import 'react-datepicker/dist/react-datepicker.css';
|
|
||||||
import { Wrap } from '@chakra-ui/layout';
|
|
||||||
import { Flex } from '@chakra-ui/layout';
|
|
||||||
|
|
||||||
const sampleInitialValues = {
|
|
||||||
title: '',
|
|
||||||
subtitle: '',
|
|
||||||
presenter: '',
|
|
||||||
timeStart: new Date(),
|
|
||||||
timeEnd: new Date(),
|
|
||||||
timerDuration: 5,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function EventForm(props) {
|
|
||||||
const [event, setEvent] = useContext(EventContext);
|
|
||||||
const [, setEvents] = useContext(EventListContext);
|
|
||||||
const [initialValues, setInitialValues] = useState(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (props.formMode === 'edit') setInitialValues(event);
|
|
||||||
else if (props.formMode === 'add') setInitialValues(sampleInitialValues);
|
|
||||||
else if (props.formMode === null) setInitialValues(null);
|
|
||||||
}, [event, props.formMode]);
|
|
||||||
|
|
||||||
// TODO: Cleanup
|
|
||||||
if (props.formMode === null || initialValues === null)
|
|
||||||
return <div>Replace with nice empty illustration</div>;
|
|
||||||
else if (props.formMode === 'edit' && event === null) {
|
|
||||||
return <div>Replace with nice empty illustration also</div>;
|
|
||||||
}
|
|
||||||
|
|
||||||
const validationSchema = Yup.object({
|
|
||||||
title: Yup.string().required('An event requires a title'),
|
|
||||||
subtitle: Yup.string(),
|
|
||||||
presenter: Yup.string(),
|
|
||||||
timeStart: Yup.date(),
|
|
||||||
timeEnd: Yup.date(),
|
|
||||||
timerDuration: Yup.number()
|
|
||||||
.min(1)
|
|
||||||
.max(60)
|
|
||||||
.required('An event requires a duration'),
|
|
||||||
});
|
|
||||||
|
|
||||||
const submitForm = (values) => {
|
|
||||||
console.log('called submit');
|
|
||||||
|
|
||||||
// prevent default stops page from refreshing, necessary?
|
|
||||||
|
|
||||||
// update form state
|
|
||||||
props.setFormMode(null);
|
|
||||||
|
|
||||||
// are we updating or creating new?
|
|
||||||
|
|
||||||
// add new event to data context
|
|
||||||
if (props.formMode === 'add')
|
|
||||||
setEvents((prevEvents) => [...prevEvents, { ...values }]);
|
|
||||||
|
|
||||||
// edit event data from context
|
|
||||||
if (props.formMode === 'edit')
|
|
||||||
setEvents((prevEvents) => [
|
|
||||||
...prevEvents.filter((pe) => pe.id !== values.id),
|
|
||||||
{ ...values },
|
|
||||||
]);
|
|
||||||
};
|
|
||||||
|
|
||||||
const cancelForm = () => {
|
|
||||||
props.setFormMode(null);
|
|
||||||
setEvent(null);
|
|
||||||
setInitialValues(null);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Formik
|
|
||||||
// enableReinitialize={true}
|
|
||||||
initialValues={initialValues}
|
|
||||||
validationSchema={validationSchema}
|
|
||||||
onSubmit={(values, actions) => {
|
|
||||||
setTimeout(() => {
|
|
||||||
submitForm(values);
|
|
||||||
}, 100);
|
|
||||||
}}
|
|
||||||
// FIX: This kept being called on render
|
|
||||||
// onReset={() => {
|
|
||||||
// cancelForm();
|
|
||||||
// }}
|
|
||||||
>
|
|
||||||
{(props) => (
|
|
||||||
<Form onSubmit={props.handleSubmit}>
|
|
||||||
<ChakraInput
|
|
||||||
name='title'
|
|
||||||
label='Event Title'
|
|
||||||
placeholder='eg. Is the Internet a fad?'
|
|
||||||
/>
|
|
||||||
<Flex direction='row'>
|
|
||||||
<ChakraInput
|
|
||||||
name='subtitle'
|
|
||||||
label='Event Subtitle'
|
|
||||||
placeholder='eg. After tea thoughts'
|
|
||||||
/>
|
|
||||||
<ChakraInput
|
|
||||||
name='presenter'
|
|
||||||
label='Presenter Name'
|
|
||||||
placeholder='eg. Duran Duran'
|
|
||||||
/>
|
|
||||||
</Flex>
|
|
||||||
|
|
||||||
{/* <TimeInput name='timeStart' label='Scheduled Start' /> */}
|
|
||||||
<ChakraNumberInput
|
|
||||||
name='timerDuration'
|
|
||||||
label='Timer Duration (minutes)'
|
|
||||||
allowMouseWheel
|
|
||||||
min={1}
|
|
||||||
max={60}
|
|
||||||
maxW={24}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Flex direction='row'>
|
|
||||||
<TimeInput name='timeStart' label='Scheduled Start' />
|
|
||||||
<TimeInput name='timeEnd' label='Scheduled End' />
|
|
||||||
</Flex>
|
|
||||||
|
|
||||||
<div className={styles.buttons}>
|
|
||||||
<Button
|
|
||||||
variant='outline'
|
|
||||||
disabled={props.isSubmitting}
|
|
||||||
// type='reset'
|
|
||||||
onClick={() => cancelForm()}
|
|
||||||
>
|
|
||||||
Back
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
colorScheme='teal'
|
|
||||||
isLoading={props.isSubmitting}
|
|
||||||
disabled={!props.isValid || !props.dirty || props.isSubmitting}
|
|
||||||
type='submit'
|
|
||||||
>
|
|
||||||
Save
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</Form>
|
|
||||||
)}
|
|
||||||
</Formik>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
.label {
|
|
||||||
padding-top: 1.5em;
|
|
||||||
font-size: 0.9em;
|
|
||||||
color: #666;
|
|
||||||
}
|
|
||||||
|
|
||||||
.timings {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
.timeInput {
|
|
||||||
display: flex;
|
|
||||||
gap: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.buttons {
|
|
||||||
padding-top: 3em;
|
|
||||||
bottom: 10px;
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
gap: 1em;
|
|
||||||
}
|
|
||||||
@@ -6,7 +6,7 @@ import { useContext } from 'react';
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { PresenterMessagesContext } from '../../app/context/presenterMessageContext';
|
import { PresenterMessagesContext } from '../../app/context/presenterMessageContext';
|
||||||
|
|
||||||
export default function MessageForm(props) {
|
export default function MessageForm() {
|
||||||
const [presenterShow, setPresenterShow] = useState(false);
|
const [presenterShow, setPresenterShow] = useState(false);
|
||||||
const [publicShow, setPublicShow] = useState(false);
|
const [publicShow, setPublicShow] = useState(false);
|
||||||
const [presMessage, setPresMessage] = useContext(PresenterMessagesContext);
|
const [presMessage, setPresMessage] = useContext(PresenterMessagesContext);
|
||||||
@@ -24,11 +24,11 @@ export default function MessageForm(props) {
|
|||||||
setPublicShow(!publicShow);
|
setPublicShow(!publicShow);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlePublicChange = () => {};
|
const handlePublicChange = (val) => {};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<form style={{ display: 'flex', gap: '1em' }}>
|
<form style={{ display: 'flex', gap: '1em', fontSize: '15px' }}>
|
||||||
<FormControl id='presenterMessage'>
|
<FormControl id='presenterMessage'>
|
||||||
<FormLabel>Presenter screen message</FormLabel>
|
<FormLabel>Presenter screen message</FormLabel>
|
||||||
<Input
|
<Input
|
||||||
@@ -48,7 +48,10 @@ export default function MessageForm(props) {
|
|||||||
<form style={{ display: 'flex', gap: '1em', paddingTop: '1em' }}>
|
<form style={{ display: 'flex', gap: '1em', paddingTop: '1em' }}>
|
||||||
<FormControl id='generalMessage'>
|
<FormControl id='generalMessage'>
|
||||||
<FormLabel>Public screen message</FormLabel>
|
<FormLabel>Public screen message</FormLabel>
|
||||||
<Input placeholder='all screens will render this' />
|
<Input
|
||||||
|
placeholder='all screens will render this'
|
||||||
|
onChange={(event) => handlePublicChange(event.target.value)}
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<IconButton
|
<IconButton
|
||||||
style={{ alignSelf: 'flex-end' }}
|
style={{ alignSelf: 'flex-end' }}
|
||||||
|
|||||||
@@ -31,11 +31,7 @@ export default function DefaultPresenter() {
|
|||||||
setInitialValues(event);
|
setInitialValues(event);
|
||||||
}, [event]);
|
}, [event]);
|
||||||
|
|
||||||
console.log('local event event', event);
|
// NOTE: test only
|
||||||
console.log('local event values', values);
|
|
||||||
console.log('local event initialv', initialValues);
|
|
||||||
|
|
||||||
// NITE: test only
|
|
||||||
const clockStarted = addMinutes(now, 6);
|
const clockStarted = addMinutes(now, 6);
|
||||||
|
|
||||||
const timer = differenceInSeconds(
|
const timer = differenceInSeconds(
|
||||||
@@ -48,8 +44,6 @@ export default function DefaultPresenter() {
|
|||||||
const timeEnd = format(values.timeEnd, 'HH:mm');
|
const timeEnd = format(values.timeEnd, 'HH:mm');
|
||||||
const elapsed = timer / (values.timerDuration * 60);
|
const elapsed = timer / (values.timerDuration * 60);
|
||||||
|
|
||||||
console.log('timers', timer, timeStart, currentTime, timeEnd, elapsed);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='presenter'>
|
<div className='presenter'>
|
||||||
<div className='presentationTitle'>{values.title}</div>
|
<div className='presentationTitle'>{values.title}</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user