Feat/navigate (#81)

* feat/navigate upgrade react router
* feat/navigate migrate to react router 6
* feat/navigate style modal
* feat/navigate create endpoints for app settings
* feat/navigate protect editor with pin
* feat/navigate apply dynamic routing draft
* feat/navigate upgrade relevant packages
* feat/navigate restructure directory and add tests
* feat/navigate test aliases validation
* feat/navigate validate aliases before sending
* feat/navigate create data endpoint
* feat/navigate config: prettier
* feat/navigate invalidate empty strings
* feat/navigate create endpoints
* feat/navigate parse on import
* feat/navigate navigate to alias
* feat/navigate user help and sample data
* feat/navigate refact aliases modal
* feat/navigate refact settings style
* feat/navigate update sample db
* feat/navigate link is relative to hostname
* feat/navigate navigate to first match
* feat/navigate update readme and version bump
* feat/navigate config: create shared module
* feat/navigate config: cheat module install
* feat/navigate fix tests
* feat/navigate run tests in pull request
* Update ontime_cy.yml
This commit is contained in:
Carlos Valente
2022-01-04 22:12:59 +01:00
committed by GitHub
parent dd43d5e20a
commit 2fa397548a
74 changed files with 2592 additions and 1428 deletions
+133 -140
View File
@@ -1,31 +1,26 @@
import { ModalBody } from '@chakra-ui/modal';
import {
FormLabel,
FormControl,
Input,
Button,
Textarea,
} from '@chakra-ui/react';
import { FormLabel, Input, Textarea } from '@chakra-ui/react';
import { fetchEvent, postEvent } from 'app/api/eventApi';
import { useEffect, useState } from 'react';
import { useFetch } from 'app/hooks/useFetch';
import { EVENT_TABLE } from 'app/api/apiConstants';
import style from './Modals.module.scss';
import { eventPlaceholderSettings } from '../../app/api/ontimeApi';
import SubmitContainer from './SubmitContainer';
import { inputProps } from './modalHelper';
export default function SettingsModal() {
const { data, status } = useFetch(EVENT_TABLE, fetchEvent);
const [formData, setFormData] = useState({
title: '',
url: '',
publicInfo: '',
backstageInfo: '',
endMessage: '',
});
const { data, status, refetch } = useFetch(EVENT_TABLE, fetchEvent);
const [formData, setFormData] = useState(eventPlaceholderSettings);
const [changed, setChanged] = useState(false);
const [submitting, setSubmitting] = useState(false);
/**
* Set formdata from server state
*/
useEffect(() => {
if (data == null) return;
if (changed) return;
setFormData({
title: data.title,
@@ -34,8 +29,11 @@ export default function SettingsModal() {
backstageInfo: data.backstageInfo,
endMessage: data.endMessage,
});
}, [data]);
}, [changed, data]);
/**
* Validate and submit data
*/
const submitHandler = async (event) => {
event.preventDefault();
setSubmitting(true);
@@ -46,133 +44,128 @@ export default function SettingsModal() {
setSubmitting(false);
};
/**
* Reverts local state equals to server state
*/
const revert = async () => {
setChanged(false);
await refetch();
};
/**
* Handles change of input field in local state
* @param {string} field - object parameter to update
* @param {string} value - new object parameter value
*/
const handleChange = (field, value) => {
const temp = { ...formData };
temp[field] = value;
setFormData(temp);
setChanged(true);
};
return (
<>
<ModalBody className={style.modalBody}>
<p className={style.notes}>
Options related to the running event
<br />
Affects rendered views
</p>
<form onSubmit={submitHandler}>
<ModalBody className={style.modalBody}>
{status === 'success' && (
<>
<p className={style.notes}>
Options related to the running event
<br />
Affect rendered views
</p>
<FormControl id='title'>
<FormLabel htmlFor='title'>Event Title</FormLabel>
<Input
size='sm'
maxLength={35}
name='title'
placeholder='Event Title'
autoComplete='off'
value={formData.title}
onChange={(event) => {
setChanged(true);
setFormData({ ...formData, title: event.target.value });
}}
isDisabled={submitting}
/>
</FormControl>
<FormControl id='url'>
<FormLabel htmlFor='url'>
Event URL
<span className={style.notes}>
(shown as a QR code in some views)
</span>
</FormLabel>
<Input
size='sm'
name='url'
placeholder='www.onsite.no'
autoComplete='off'
value={formData.url}
onChange={(event) => {
setChanged(true);
setFormData({ ...formData, url: event.target.value });
}}
isDisabled={submitting}
/>
</FormControl>
<FormControl id='pubInfo'>
<FormLabel htmlFor='pubInfo'>Public Info</FormLabel>
<Textarea
size='sm'
name='pubInfo'
placeholder='Information to be shown on public screens'
autoComplete='off'
value={formData.publicInfo}
onChange={(event) => {
setChanged(true);
setFormData({
...formData,
publicInfo: event.target.value,
});
}}
isDisabled={submitting}
/>
</FormControl>
<FormControl id='backstageInfo'>
<FormLabel htmlFor='backstageInfo'>Backstage Info</FormLabel>
<Textarea
size='sm'
name='backstageInfo'
placeholder='Information to be shown on backstage screens'
autoComplete='off'
resize={false}
value={formData.backstageInfo}
onChange={(event) => {
setChanged(true);
setFormData({
...formData,
backstageInfo: event.target.value,
});
}}
isDisabled={submitting}
/>
</FormControl>
<FormControl id='endMessage'>
<FormLabel htmlFor='endMessage'>
End Message
<span className={style.notes}>
Shown on presenter view when time is finished
</span>
</FormLabel>
<Input
size='sm'
maxLength={30}
name='endMessage'
placeholder='Empty message shows elapsed time'
autoComplete='off'
value={formData.endMessage}
onChange={(event) => {
setChanged(true);
setFormData({
...formData,
endMessage: event.target.value,
});
}}
isDisabled={submitting}
/>
</FormControl>
</>
)}
<div className={style.submitContainer}>
<Button
colorScheme='blue'
type='submit'
isLoading={submitting}
disabled={!changed}
>
Save
</Button>
<div className={style.modalFields}>
<div className={style.hSeparator}>Event Data</div>
<div className={style.spacedEntry}>
<FormLabel htmlFor='title'>Event Title</FormLabel>
<Input
{...inputProps}
maxLength={35}
name='title'
placeholder='Event Title'
value={formData.title}
onChange={(event) => handleChange('title', event.target.value)}
/>
</div>
</ModalBody>
<div className={style.hSeparator}>Additional Screen Info</div>
<div className={style.spacedEntry}>
<FormLabel htmlFor='url'>
Event URL
<span className={style.labelNote}>
<br />
Shown as a QR code in some views
</span>
</FormLabel>
<Input
{...inputProps}
name='url'
placeholder='www.onsite.no'
value={formData.url}
onChange={(event) => handleChange('url', event.target.value)}
/>
</div>
<div className={style.spacedEntry}>
<FormLabel htmlFor='pubInfo'>
Public Info
<span className={style.labelNote}>
<br />
Information to be shown on public screens
</span>
</FormLabel>
<Textarea
{...inputProps}
name='pubInfo'
placeholder='Information to be shown on public screens'
value={formData.publicInfo}
onChange={(event) =>
handleChange('publicInfo', event.target.value)
}
/>
</div>
<div className={style.spacedEntry}>
<FormLabel htmlFor='backstageInfo'>
Backstage Info
<span className={style.labelNote}>
<br />
Information to be shown on backstage screens
</span>
</FormLabel>
<Textarea
{...inputProps}
name='backstageInfo'
placeholder='Information to be shown on backstage screens'
resize={false}
value={formData.backstageInfo}
onChange={(event) =>
handleChange('backstageInfo', event.target.value)
}
/>
</div>
<div className={style.spacedEntry}>
<FormLabel htmlFor='endMessage'>
End Message
<span className={style.labelNote}>
<br />
Shown on presenter view when time is finished
</span>
</FormLabel>
<Input
{...inputProps}
maxLength={30}
name='endMessage'
placeholder='Empty message shows elapsed time'
value={formData.endMessage}
onChange={(event) =>
handleChange('endMessage', event.target.value)
}
/>
</div>
</div>
<SubmitContainer
revert={revert}
submitting={submitting}
changed={changed}
status={status}
/>
</form>
</>
</ModalBody>
);
}