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
@@ -1,5 +1,5 @@
import EditableTimer from 'common/input/EditableTimer';
import { stringFromMillis } from 'ontime-server/utils/time';
import { stringFromMillis } from 'ontime-utils/time';
import { useContext } from 'react';
import { LoggingContext } from '../../../app/context/LoggingContext';
@@ -1,4 +1,4 @@
import { clamp } from 'app/utils';
import { clamp } from 'app/utils/math';
import styles from './MyProgressBar.module.css';
export default function MyProgressBar(props) {
+1 -7
View File
@@ -1,5 +1,5 @@
import PropTypes from "prop-types";
import { Link, Redirect } from 'react-router-dom';
import { Link } from 'react-router-dom';
import { Image } from '@chakra-ui/react';
import { AnimatePresence, motion } from 'framer-motion';
import { useState, useEffect, useCallback } from 'react';
@@ -57,7 +57,6 @@ export default function NavLogo(props) {
to='/presenter'
className={style.navItem}
tabIndex={1}
onKeyDownCapture={() => <Redirect push to='/presenter' />}
>
Presenter
</Link>
@@ -65,7 +64,6 @@ export default function NavLogo(props) {
to='/sm'
className={style.navItem}
tabIndex={2}
onKeyDownCapture={() => <Redirect push to='/sm' />}
>
Backstage
</Link>
@@ -73,7 +71,6 @@ export default function NavLogo(props) {
to='/public'
className={style.navItem}
tabIndex={3}
onKeyDownCapture={() => <Redirect push to='/public' />}
>
Public
</Link>
@@ -81,7 +78,6 @@ export default function NavLogo(props) {
to='/lower'
className={style.navItem}
tabIndex={4}
onKeyDownCapture={() => <Redirect push to='/lower' />}
>
Lower Thirds
</Link>
@@ -89,7 +85,6 @@ export default function NavLogo(props) {
to='/pip'
className={style.navItem}
tabIndex={4}
onKeyDownCapture={() => <Redirect push to='/pip' />}
>
PIP
</Link>
@@ -97,7 +92,6 @@ export default function NavLogo(props) {
to='/studio'
className={style.navItem}
tabIndex={5}
onKeyDownCapture={() => <Redirect push to='/studio' />}
>
Studio Clock
</Link>
@@ -0,0 +1,67 @@
import PropTypes from 'prop-types';
import style from './ProtectRoute.module.scss';
import { PinInput, PinInputField } from '@chakra-ui/react';
import { IconButton } from '@chakra-ui/button';
import { FiCheck } from 'react-icons/fi';
import { AppContext } from '../../../app/context/AppContext';
import { useContext, useEffect, useState } from 'react';
export default function ProtectRoute(props) {
const isLocal = window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1';
const [pin, setPin] = useState('');
const [failed, setFailed] = useState(false);
const { auth, validate } = useContext(AppContext);
// Set window title
useEffect(() => {
document.title = 'ontime';
}, []);
const handleValidation = () => {
const r = validate(pin);
if (!r) {
setFailed(true);
}
}
return (
<>
{!isLocal && !auth ? (
<div className={style.container}>
ontime
<div className={failed ? style.pin__failed : style.pin}>
<PinInput
type='alphanumeric'
size='lg'
mask
onChange={(value) => {
setFailed(false);
setPin(value);
}}
>
<PinInputField />
<PinInputField />
<PinInputField />
<PinInputField />
</PinInput>
<IconButton
aria-label='Enter'
size='lg'
isRound
icon={<FiCheck />}
style={{ fontSize: '1.5em' }}
onClick={() => handleValidation()}
/>
</div>
</div>
) : (
props.children
)}
</>
);
}
ProtectRoute.propTypes = {
children: PropTypes.node.isRequired
};
@@ -0,0 +1,47 @@
@use '../../../styles/main' as *;
@use '../../../styles/mixins' as *;
.container {
background: #222;
display: grid;
place-content: center;
height: 100vh;
padding-bottom: 30vh;
color: $ontime-pink;
font-family: 'Open Sans', sans-serif;
font-weight: 200;
text-align: center;
font-size: 3vw;
}
.pin,
.pin__failed {
display: flex;
gap: 10px;
padding: 20px;
input {
border-radius: 50%;
}
button {
margin-left: 20px;
}
}
.pin__failed {
input {
animation: colourFade 1.5s ease;
}
}
@keyframes colourFade {
from {
background: $ontime-pink;
}
to {
background: rgba($ontime-pink, 0);
}
}
@@ -1,4 +1,4 @@
import { stringFromMillis } from 'ontime-server/utils/time';
import { stringFromMillis } from 'ontime-utils/time';
import style from './Paginator.module.css';
export default function TodayItem(props) {
const { selected, timeStart, timeEnd, title, backstageEvent } = props;
+1 -1
View File
@@ -4,7 +4,7 @@ import {
isTimeString,
timeStringToMillis,
} from '../utils/dateConfig';
import { stringFromMillis } from 'ontime-server/utils/time';
import { stringFromMillis } from 'ontime-utils/time';
import style from './EditableTimer.module.css';
import { LoggingContext } from '../../app/context/LoggingContext';
+1 -1
View File
@@ -1,4 +1,4 @@
import { stringFromMillis } from 'ontime-server/utils/time';
import { stringFromMillis } from 'ontime-utils/time';
/**
* @description From a list of events, returns only events of type event with calculated delays
+13
View File
@@ -0,0 +1,13 @@
/**
* Handles link to external URLs: specifically for a electron / browser case
* If electron: ask main process to call a new browser window
* If browser: open in new tab
* @param url
*/
export default function handleLink(url) {
if (window.process?.type === 'renderer') {
window.ipcRenderer.send('send-to-link', url);
} else {
window.open(url);
}
}