mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-07 08:23:55 +00:00
v2: refactor (#264)
* chore: upgrade dependencies * chore: remove unused * fix: issue with missing index data * fix: discrepancy on counting events * fix: swapped classes * fix: prevent attempting load in empty list * chore: cleanup completed * chore: remove unused * refactor: convert to typescript * refactor: migrate to new endpoints * refactor: convert to typescript * fix: prevent issue with undefined process * fix: small code smells * fix: issue with missing version variable on build * refactor: configure retries on data fetching * style: design review * fix: prevent cursor out of range * lint: react query linting * style: checkbox styles
This commit is contained in:
@@ -43,7 +43,7 @@ jobs:
|
||||
|
||||
# App
|
||||
- name: Electron - Install dependencies
|
||||
run: yarn install && yarn setdb
|
||||
run: yarn setup
|
||||
working-directory: ./server
|
||||
|
||||
- name: Server - run tests
|
||||
|
||||
+4
-2
@@ -12,12 +12,14 @@
|
||||
"eslint:recommended",
|
||||
"plugin:react/recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"eslint-config-prettier"
|
||||
"eslint-config-prettier",
|
||||
"plugin:@tanstack/eslint-plugin-query/recommended"
|
||||
],
|
||||
"plugins": [
|
||||
"react",
|
||||
"testing-library",
|
||||
"simple-import-sort"
|
||||
"simple-import-sort",
|
||||
"@tanstack/query"
|
||||
],
|
||||
"rules": {
|
||||
"no-useless-concat": "warn",
|
||||
|
||||
+1
-1
@@ -32,6 +32,6 @@
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id='root'></div>
|
||||
<script type='module' src='/src/index.jsx'></script>
|
||||
<script type='module' src='/src/index.tsx'></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+8
-6
@@ -10,14 +10,15 @@
|
||||
"@emotion/react": "^11.10.5",
|
||||
"@emotion/styled": "^11.10.5",
|
||||
"@react-icons/all-files": "^4.1.0",
|
||||
"@tanstack/react-query": "^4.10.3",
|
||||
"@tanstack/react-query-devtools": "^4.11.0",
|
||||
"@tanstack/react-query": "^4.18.0",
|
||||
"@tanstack/react-query-devtools": "^4.18.0",
|
||||
"autosize": "^5.0.1",
|
||||
"axios": "^0.27.2",
|
||||
"axios": "^1.2.0",
|
||||
"color": "^4.2.3",
|
||||
"express": "^4.18.2",
|
||||
"framer-motion": "^7.5.3",
|
||||
"jotai": "^1.8.5",
|
||||
"luxon": "^3.0.1",
|
||||
"jotai": "^1.10.0",
|
||||
"luxon": "^3.1.0",
|
||||
"react": "^18.2.0",
|
||||
"react-beautiful-dnd": "^13.1.1",
|
||||
"react-dom": "^18.2.0",
|
||||
@@ -25,7 +26,7 @@
|
||||
"react-qr-code": "^2.0.5",
|
||||
"react-router-dom": "^6.3.0",
|
||||
"react-table": "^7.7.0",
|
||||
"socket.io-client": "^4.5.2",
|
||||
"socket.io-client": "^4.5.4",
|
||||
"typeface-open-sans": "^1.1.13",
|
||||
"web-vitals": "^2.1.4"
|
||||
},
|
||||
@@ -50,6 +51,7 @@
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tanstack/eslint-plugin-query": "^4.15.1",
|
||||
"@testing-library/jest-dom": "^5.16.4",
|
||||
"@testing-library/react": "^13.1.1",
|
||||
"@testing-library/react-hooks": "^8.0.0",
|
||||
|
||||
@@ -13,12 +13,13 @@ import theme from './theme/theme';
|
||||
import AppRouter from './AppRouter';
|
||||
|
||||
// Load Open Sans typeface
|
||||
// @ts-expect-error no types from font import
|
||||
import('typeface-open-sans');
|
||||
|
||||
function App() {
|
||||
const { isElectron, sendToElectron } = useElectronEvent();
|
||||
|
||||
const handleKeyPress = useCallback((event) => {
|
||||
const handleKeyPress = useCallback((event:KeyboardEvent) => {
|
||||
// handle held key
|
||||
if (event.repeat) return;
|
||||
// check if the alt key is pressed
|
||||
@@ -1,33 +0,0 @@
|
||||
import { useCallback, useState } from 'react';
|
||||
import { IconButton, IconButtonProps, Tooltip } from '@chakra-ui/react';
|
||||
|
||||
interface TooltipLoadingActionBtnProps extends IconButtonProps {
|
||||
clickHandler: () => void;
|
||||
tooltip: string;
|
||||
openDelay?: number;
|
||||
}
|
||||
|
||||
export default function TooltipLoadingActionBtn(props: TooltipLoadingActionBtnProps) {
|
||||
const { clickHandler, icon, size = 'xs', tooltip, openDelay = 0, ...rest } = props;
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const handleClick = useCallback(() => {
|
||||
setLoading(true);
|
||||
clickHandler();
|
||||
}, [clickHandler, setLoading]);
|
||||
|
||||
return (
|
||||
<Tooltip label={tooltip} shouldWrapChildren={loading} openDelay={openDelay}>
|
||||
<IconButton
|
||||
{...rest}
|
||||
aria-label={tooltip}
|
||||
size={size}
|
||||
icon={icon}
|
||||
onClick={handleClick}
|
||||
disabled={loading}
|
||||
isLoading={loading}
|
||||
/>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ class ErrorBoundary extends React.Component {
|
||||
try {
|
||||
this.context.emitError(error.toString());
|
||||
} catch (e) {
|
||||
console.log('Unable to emit error', error, e )
|
||||
console.log('Unable to emit error', error, e);
|
||||
}
|
||||
this.reportContent = `${error} ${info.componentStack}`;
|
||||
}
|
||||
@@ -36,11 +36,12 @@ class ErrorBoundary extends React.Component {
|
||||
render() {
|
||||
if (this.state.errorMessage) {
|
||||
return (
|
||||
<div className={style.errorContainer} data-testid="error-container">
|
||||
<div className={style.errorContainer} data-testid='error-container'>
|
||||
<div>
|
||||
<p className={style.error}>:/</p>
|
||||
<p>Something went wrong</p>
|
||||
<p
|
||||
<div
|
||||
role='button'
|
||||
className={style.report}
|
||||
onClick={() => {
|
||||
if (navigator.clipboard) {
|
||||
@@ -50,11 +51,12 @@ class ErrorBoundary extends React.Component {
|
||||
}}
|
||||
>
|
||||
Copy error
|
||||
</p>
|
||||
<p
|
||||
</div>
|
||||
<div
|
||||
role='button'
|
||||
className={style.report}
|
||||
onClick={() => {
|
||||
if (window.process.type === 'renderer') {
|
||||
if (window?.process?.type === 'renderer') {
|
||||
window.ipcRenderer.send('reload');
|
||||
} else {
|
||||
window.location.reload();
|
||||
@@ -62,7 +64,7 @@ class ErrorBoundary extends React.Component {
|
||||
}}
|
||||
>
|
||||
Reload interface
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -15,7 +15,6 @@ import { useKeyDown } from '../../hooks/useKeyDown';
|
||||
|
||||
import style from './NavigationMenu.module.scss';
|
||||
|
||||
// Todo: restyle _main.scss links
|
||||
export default function NavigationMenu() {
|
||||
const location = useLocation();
|
||||
|
||||
@@ -65,6 +64,7 @@ export default function NavigationMenu() {
|
||||
<div
|
||||
className={style.link}
|
||||
tabIndex={0}
|
||||
role='button'
|
||||
onClick={handleFullscreen}
|
||||
onKeyDown={(event) => {
|
||||
isKeyEnter(event) && handleFullscreen();
|
||||
@@ -76,6 +76,7 @@ export default function NavigationMenu() {
|
||||
<div
|
||||
className={style.link}
|
||||
tabIndex={0}
|
||||
role='button'
|
||||
onClick={handleMirror}
|
||||
onKeyDown={(event) => {
|
||||
isKeyEnter(event) && handleMirror();
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
import { ReactComponent as Emptyimage } from 'assets/images/empty.svg';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import style from './Empty.module.scss';
|
||||
|
||||
export default function Empty(props) {
|
||||
const { text, dark, ...rest } = props;
|
||||
return (
|
||||
<div className={`${style.emptyContainer} ${dark ? style.dark : ''}`} {...rest}>
|
||||
<Emptyimage className={style.empty} />
|
||||
<span className={style.text}>{text}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Empty.propTypes = {
|
||||
text: PropTypes.string,
|
||||
dark: PropTypes.bool,
|
||||
}
|
||||
@@ -1,26 +1,17 @@
|
||||
@use '../../../theme/main' as *;
|
||||
@use '../../../theme/ontimeColours' as *;
|
||||
|
||||
.emptyContainer {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
color: $bg-black-200;
|
||||
color: $gray-1350;
|
||||
|
||||
.empty {
|
||||
width: 100%;
|
||||
opacity: 0.3;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.text {
|
||||
font-weight: 600;
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
&.dark {
|
||||
background: $bg-black;
|
||||
color: $bg-gray-500;
|
||||
|
||||
.empty {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
import { ReactComponent as Emptyimage } from 'assets/images/empty.svg';
|
||||
|
||||
import style from './Empty.module.scss';
|
||||
|
||||
interface EmptyProps {
|
||||
text: string;
|
||||
}
|
||||
|
||||
export default function Empty(props: EmptyProps) {
|
||||
const { text, ...rest } = props;
|
||||
return (
|
||||
<div className={style.emptyContainer} {...rest}>
|
||||
<Emptyimage className={style.empty} />
|
||||
<span className={style.text}>{text}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
import { createContext, useCallback } from 'react';
|
||||
|
||||
import { useLocalStorage } from '../hooks/useLocalStorage';
|
||||
|
||||
export const CollapseContext = createContext({
|
||||
collapsed: {},
|
||||
setCollapsed: () => undefined,
|
||||
clearCollapsed: () => undefined,
|
||||
isCollapsed: () => undefined,
|
||||
});
|
||||
|
||||
export const CollapseProvider = ({ children }) => {
|
||||
const [collapsed, saveCollapsed] = useLocalStorage('collapsed', {});
|
||||
|
||||
/**
|
||||
* @description Sets collapsed state for a single id
|
||||
* @param {string} - id
|
||||
* @param {boolean} - collapsed / not collapsed
|
||||
*/
|
||||
const setCollapsed = useCallback(
|
||||
(id, isCollapsed) => {
|
||||
if (isCollapsed) {
|
||||
saveCollapsed((prev) => ({ ...prev, [id]: true }));
|
||||
} else {
|
||||
saveCollapsed((prev) => {
|
||||
const newObject = { ...prev };
|
||||
delete newObject[id];
|
||||
return { ...newObject };
|
||||
});
|
||||
}
|
||||
},
|
||||
[saveCollapsed]
|
||||
);
|
||||
|
||||
/**
|
||||
* @description Clears collapsed state in local-storage
|
||||
*/
|
||||
const collapseMultiple = useCallback(
|
||||
(events) => {
|
||||
const newOptions = {};
|
||||
for (const event of events) {
|
||||
newOptions[event.id] = true;
|
||||
}
|
||||
saveCollapsed(newOptions);
|
||||
},
|
||||
[saveCollapsed]
|
||||
);
|
||||
|
||||
/**
|
||||
* @description Clears collapsed state in local-storage
|
||||
*/
|
||||
const expandAll = useCallback(() => {
|
||||
saveCollapsed({});
|
||||
}, [saveCollapsed]);
|
||||
|
||||
/**
|
||||
* @description Clears collapsed state in local-storage
|
||||
* @return {boolean} - collapsed / not collapsed
|
||||
*/
|
||||
const isCollapsed = useCallback(
|
||||
(id) => {
|
||||
return id in collapsed;
|
||||
},
|
||||
[collapsed]
|
||||
);
|
||||
|
||||
return (
|
||||
<CollapseContext.Provider value={{ setCollapsed, collapseMultiple, expandAll, isCollapsed }}>
|
||||
{children}
|
||||
</CollapseContext.Provider>
|
||||
);
|
||||
};
|
||||
@@ -9,7 +9,13 @@ export default function useAliases() {
|
||||
status,
|
||||
isError,
|
||||
refetch,
|
||||
} = useQuery(ALIASES, getAliases, { placeholderData: [] });
|
||||
} = useQuery({
|
||||
queryKey: ALIASES,
|
||||
queryFn: getAliases,
|
||||
placeholderData: [],
|
||||
retry: 5,
|
||||
retryDelay: attempt => attempt * 2500,
|
||||
});
|
||||
|
||||
return { data, status, isError, refetch };
|
||||
}
|
||||
@@ -10,7 +10,13 @@ export default function useEvent() {
|
||||
status,
|
||||
isError,
|
||||
refetch,
|
||||
} = useQuery(EVENT_TABLE, fetchEvent, { placeholderData: eventDataPlaceholder });
|
||||
} = useQuery({
|
||||
queryKey: EVENT_TABLE,
|
||||
queryFn: fetchEvent,
|
||||
placeholderData: eventDataPlaceholder,
|
||||
retry: 5,
|
||||
retryDelay: attempt => attempt * 2500,
|
||||
});
|
||||
|
||||
return { data, status, isError, refetch };
|
||||
}
|
||||
@@ -10,7 +10,13 @@ export default function useInfo() {
|
||||
status,
|
||||
isError,
|
||||
refetch,
|
||||
} = useQuery(APP_INFO, getInfo, { placeholderData: ontimePlaceholderInfo });
|
||||
} = useQuery({
|
||||
queryKey: APP_INFO,
|
||||
queryFn: getInfo,
|
||||
placeholderData: ontimePlaceholderInfo,
|
||||
retry: 5,
|
||||
retryDelay: attempt => attempt * 2500,
|
||||
});
|
||||
|
||||
return { data, status, isError, refetch };
|
||||
}
|
||||
|
||||
@@ -10,7 +10,13 @@ export default function useOscSettings() {
|
||||
status,
|
||||
isError,
|
||||
refetch,
|
||||
} = useQuery(OSC_SETTINGS, getOSC, { placeholderData: oscPlaceholderSettings });
|
||||
} = useQuery({
|
||||
queryKey: OSC_SETTINGS,
|
||||
queryFn: getOSC,
|
||||
placeholderData: oscPlaceholderSettings,
|
||||
retry: 5,
|
||||
retryDelay: attempt => attempt * 2500,
|
||||
});
|
||||
|
||||
return { data, status, isError, refetch };
|
||||
}
|
||||
|
||||
@@ -9,7 +9,13 @@ export default function useRundown() {
|
||||
status,
|
||||
isError,
|
||||
refetch,
|
||||
} = useQuery(RUNDOWN_TABLE, fetchRundown, { placeholderData: [] });
|
||||
} = useQuery({
|
||||
queryKey: RUNDOWN_TABLE,
|
||||
queryFn: fetchRundown,
|
||||
placeholderData: [],
|
||||
retry: 5,
|
||||
retryDelay: attempt => attempt * 2500,
|
||||
});
|
||||
|
||||
return { data, status, isError, refetch };
|
||||
}
|
||||
|
||||
@@ -10,7 +10,13 @@ export default function useSettings() {
|
||||
status,
|
||||
isError,
|
||||
refetch,
|
||||
} = useQuery(APP_SETTINGS, getSettings, { placeholderData: ontimePlaceholderSettings });
|
||||
} = useQuery({
|
||||
queryKey: APP_SETTINGS,
|
||||
queryFn: getSettings,
|
||||
placeholderData: ontimePlaceholderSettings,
|
||||
retry: 5,
|
||||
retryDelay: attempt => attempt * 2500,
|
||||
});
|
||||
|
||||
return { data, status, isError, refetch };
|
||||
}
|
||||
|
||||
@@ -10,7 +10,13 @@ export default function useUserFields() {
|
||||
status,
|
||||
isError,
|
||||
refetch,
|
||||
} = useQuery(USERFIELDS, getUserFields, { placeholderData: userFieldsPlaceholder });
|
||||
} = useQuery({
|
||||
queryKey: USERFIELDS,
|
||||
queryFn: getUserFields,
|
||||
placeholderData: userFieldsPlaceholder,
|
||||
retry: 5,
|
||||
retryDelay: attempt => attempt * 2500,
|
||||
});
|
||||
|
||||
return { data, status, isError, refetch };
|
||||
}
|
||||
|
||||
@@ -10,7 +10,13 @@ export default function useViewSettings() {
|
||||
status,
|
||||
isError,
|
||||
refetch,
|
||||
} = useQuery(VIEW_SETTINGS, getView, { placeholderData: viewsSettingsPlaceholder });
|
||||
} = useQuery({
|
||||
queryKey: VIEW_SETTINGS,
|
||||
queryFn: getView,
|
||||
placeholderData: viewsSettingsPlaceholder,
|
||||
retry: 5,
|
||||
retryDelay: attempt => attempt * 2500,
|
||||
});
|
||||
|
||||
return { data, status, isError, refetch };
|
||||
}
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
|
||||
import { RUNDOWN_TABLE } from '../api/apiConstants';
|
||||
|
||||
/**
|
||||
* @description utility hook to handle mutations in events
|
||||
* @param mutation
|
||||
*/
|
||||
export default function useMutateEvents(mutation){
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation(mutation, {
|
||||
onMutate: async (newEvent) => {
|
||||
// cancel ongoing queries
|
||||
queryClient.cancelQueries(RUNDOWN_TABLE, { exact: true });
|
||||
|
||||
// Snapshot the previous value
|
||||
const previousEvent = queryClient.getQueryData([RUNDOWN_TABLE, newEvent.id]);
|
||||
|
||||
// optimistically update object
|
||||
queryClient.setQueryData([RUNDOWN_TABLE, newEvent.id], newEvent);
|
||||
|
||||
// Return a context with the previous and new event
|
||||
return { previousEvent, newEvent };
|
||||
},
|
||||
|
||||
// Mutation fails, rollback undoes optimist update
|
||||
onError: (error, newEvent, context) => {
|
||||
queryClient.setQueryData([RUNDOWN_TABLE, context.newEvent.id], context.previousEvent);
|
||||
},
|
||||
|
||||
// Mutation finished, failed or successful
|
||||
// Fetch anyway, just to be sure
|
||||
onSettled: (newEvent) => {
|
||||
queryClient.invalidateQueries([RUNDOWN_TABLE, newEvent.id]);
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -6,9 +6,9 @@ export const useRuntimeStylesheet = (pathToFile) => {
|
||||
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
let response = await fetch(pathToFile);
|
||||
const response = await fetch(pathToFile);
|
||||
if (response.ok) {
|
||||
return await response.text();
|
||||
return response.text();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ function createSocketHook<T>(key: string, defaultValue: T | null = null) {
|
||||
// we need the null because useQuery can't receive undefined
|
||||
const fetcher = () => (queryClient.getQueryData([key]) ?? defaultValue) as T | null;
|
||||
|
||||
return () => useQuery([key], fetcher, { placeholderData: defaultValue });
|
||||
return () => useQuery({ queryKey: [key], queryFn: fetcher, placeholderData: defaultValue });
|
||||
}
|
||||
|
||||
const emptyRundown = {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { generateId } from '../generate_id.js';
|
||||
import { generateId } from '../generate_id';
|
||||
|
||||
test('generate a valid 5 digit id', () => {
|
||||
const id = generateId();
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* @param {string} alias
|
||||
* @returns {{message: string, status: boolean}}
|
||||
*/
|
||||
export const validateAlias = (alias) => {
|
||||
export const validateAlias = (alias: string) => {
|
||||
|
||||
const valid = { status: true, message: 'ok' };
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
/**
|
||||
* @description Validates two time entries
|
||||
* @param {number} timeStart
|
||||
* @param {number} timeEnd
|
||||
* @returns {{catch: string, value: boolean}}
|
||||
*/
|
||||
export const validateTimes = (timeStart, timeEnd) => {
|
||||
const validate = { value: true, catch: '' };
|
||||
if (timeStart > timeEnd) {
|
||||
validate.catch = 'Start time later than end time';
|
||||
}
|
||||
return validate;
|
||||
};
|
||||
@@ -97,8 +97,8 @@ export const formatEventList = (events: OntimeEvent[], selectedId: string, nextI
|
||||
* @param {object} event
|
||||
* @return {object} clean event
|
||||
*/
|
||||
type DuplicatedEvent = OntimeEvent | { after?: string };
|
||||
export const duplicateEvent = (event: OntimeEvent, after?: string): DuplicatedEvent => {
|
||||
type ClonedEvent = OntimeEvent | { after?: string };
|
||||
export const cloneEvent = (event: OntimeEvent, after?: string): ClonedEvent => {
|
||||
return {
|
||||
type: 'event',
|
||||
title: event.title,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { customAlphabet } from 'nanoid';
|
||||
|
||||
const nanoid = customAlphabet('1234567890abcdef', 5);
|
||||
|
||||
/**
|
||||
@@ -5,5 +5,5 @@
|
||||
* @param {number} max - max value
|
||||
* @returns {number}
|
||||
*/
|
||||
export const clamp = (num, min, max) =>
|
||||
export const clamp = (num: number, min: number, max: number) =>
|
||||
Math.max(Math.min(num, Math.max(min, max)), Math.min(min, max));
|
||||
@@ -1,17 +1,17 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
import ProtectRoute from '../common/components/protectRoute/ProtectRoute';
|
||||
|
||||
import style from './FeatureWrapper.module.scss';
|
||||
|
||||
export default function FeatureWrapper({ children }) {
|
||||
interface FeatureWrapperProps {
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
export default function FeatureWrapper({ children }: FeatureWrapperProps) {
|
||||
return (
|
||||
<ProtectRoute>
|
||||
<div className={style.wrapper}>{children}</div>
|
||||
</ProtectRoute>
|
||||
);
|
||||
}
|
||||
|
||||
FeatureWrapper.propTypes = {
|
||||
children: PropTypes.element,
|
||||
};
|
||||
@@ -1,4 +1,5 @@
|
||||
@use '../../theme/main' as *;
|
||||
@use '../../theme/ontimeColours' as *;
|
||||
@use '../../theme/v2Styles' as *;
|
||||
|
||||
@mixin absolute-top-right($distance) {
|
||||
position: absolute;
|
||||
@@ -15,13 +16,13 @@
|
||||
}
|
||||
|
||||
.mainContainer {
|
||||
background: $bg-black;
|
||||
background: $ui-black;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: auto;
|
||||
color: $title-white;
|
||||
padding: max(16px, 2vh) max(8px, 1vh);
|
||||
font-family: "Open Sans", "Segoe UI", sans-serif;
|
||||
color: $ui-white;
|
||||
padding: 16px 8px;
|
||||
font-family: $ontime-font-family;
|
||||
|
||||
display: grid;
|
||||
grid-template-rows: auto 1fr;
|
||||
@@ -124,7 +125,7 @@
|
||||
.info {
|
||||
border-radius: 8px;
|
||||
height: 100%;
|
||||
background-color: $bg-container-l1;
|
||||
background-color: $bg-container-l2;
|
||||
padding: 0.8em 1.5em;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -133,16 +134,16 @@
|
||||
|
||||
.eventEditor {
|
||||
border-radius: 8px 8px 0 0;
|
||||
background-color: #202020;
|
||||
background-color: $bg-container-l2;
|
||||
box-shadow: rgba(0, 0, 0, 0.35) 0 3px 6px 6px;
|
||||
border-top: 1px solid $bg-gray-900;
|
||||
border-top: 1px solid $white-10;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100vw;
|
||||
left: 0;
|
||||
z-index: 10;
|
||||
color: white;
|
||||
transition: bottom 0.3s; // $transition-time
|
||||
transition: bottom $transition-time-feedback;
|
||||
|
||||
&.noEvent {
|
||||
bottom: -500px;
|
||||
@@ -156,7 +157,7 @@
|
||||
.header {
|
||||
background-color: #202020;
|
||||
padding: 8px;
|
||||
border-left: 1px solid $bg-container-l3;
|
||||
border-left: 1px solid $white-10;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-1
@@ -27,7 +27,6 @@ export default function InfoExport() {
|
||||
<div className={style.header}>
|
||||
<IconButton
|
||||
aria-label='Close Menu'
|
||||
size='lg'
|
||||
icon={<FiX />}
|
||||
onClick={() => setOpenId(null)}
|
||||
{...closeBtnStyle}
|
||||
@@ -33,7 +33,7 @@
|
||||
.interfaceList {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: $element-spacing;
|
||||
gap: $section-spacing;
|
||||
|
||||
.interface {
|
||||
@include action-link;
|
||||
@@ -41,7 +41,7 @@
|
||||
}
|
||||
|
||||
.linkIcon {
|
||||
margin-left: 8px;
|
||||
margin-left: $element-inner-spacing;
|
||||
display: inline-block;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ export default function InfoLogger() {
|
||||
<>
|
||||
<div className={style.buttonBar}>
|
||||
<Button
|
||||
variant={showUser ? 'ontime-filled' : 'ontime-outlined'}
|
||||
variant={showUser ? 'ontime-filled' : 'ontime-subtle'}
|
||||
size='xs'
|
||||
onClick={() => setShowUser((s) => !s)}
|
||||
onAuxClick={() => disableOthers(LOG_FILTER.USER)}
|
||||
@@ -80,7 +80,7 @@ export default function InfoLogger() {
|
||||
USER
|
||||
</Button>
|
||||
<Button
|
||||
variant={showClient ? 'ontime-filled' : 'ontime-outlined'}
|
||||
variant={showClient ? 'ontime-filled' : 'ontime-subtle'}
|
||||
size='xs'
|
||||
onClick={() => setShowClient((s) => !s)}
|
||||
onAuxClick={() => disableOthers(LOG_FILTER.CLIENT)}
|
||||
@@ -89,7 +89,7 @@ export default function InfoLogger() {
|
||||
CLIENT
|
||||
</Button>
|
||||
<Button
|
||||
variant={showServer ? 'ontime-filled' : 'ontime-outlined'}
|
||||
variant={showServer ? 'ontime-filled' : 'ontime-subtle'}
|
||||
size='xs'
|
||||
onClick={() => setShowServer((s) => !s)}
|
||||
onAuxClick={() => disableOthers(LOG_FILTER.SERVER)}
|
||||
@@ -98,7 +98,7 @@ export default function InfoLogger() {
|
||||
SERVER
|
||||
</Button>
|
||||
<Button
|
||||
variant={showPlayback ? 'ontime-filled' : 'ontime-outlined'}
|
||||
variant={showPlayback ? 'ontime-filled' : 'ontime-subtle'}
|
||||
size='xs'
|
||||
onClick={() => setShowPlayback((s) => !s)}
|
||||
onAuxClick={() => disableOthers(LOG_FILTER.PLAYBACK)}
|
||||
@@ -107,7 +107,7 @@ export default function InfoLogger() {
|
||||
PLAYBACK
|
||||
</Button>
|
||||
<Button
|
||||
variant={showRx ? 'ontime-filled' : 'ontime-outlined'}
|
||||
variant={showRx ? 'ontime-filled' : 'ontime-subtle'}
|
||||
size='xs'
|
||||
onClick={() => setShowRx((s) => !s)}
|
||||
onAuxClick={() => disableOthers(LOG_FILTER.RX)}
|
||||
@@ -116,7 +116,7 @@ export default function InfoLogger() {
|
||||
RX
|
||||
</Button>
|
||||
<Button
|
||||
variant={showTx ? 'ontime-filled' : 'ontime-outlined'}
|
||||
variant={showTx ? 'ontime-filled' : 'ontime-subtle'}
|
||||
size='xs'
|
||||
onClick={() => setShowTx((s) => !s)}
|
||||
onAuxClick={() => disableOthers(LOG_FILTER.TX)}
|
||||
@@ -125,7 +125,7 @@ export default function InfoLogger() {
|
||||
TX
|
||||
</Button>
|
||||
<Button
|
||||
variant='ontime-subtle'
|
||||
variant='ontime-outlined'
|
||||
size='xs'
|
||||
onClick={clearLog}
|
||||
>
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
@use '../../theme/v2Styles' as *;
|
||||
@use '../../theme/ontimeColours' as *;
|
||||
|
||||
.headerButtons {
|
||||
align-content: center;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
padding-top: 24px;
|
||||
}
|
||||
|
||||
.labelledSwitch {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
gap: $element-spacing;
|
||||
color: $gray-100;
|
||||
}
|
||||
|
||||
@@ -61,21 +61,21 @@ const RundownMenu = () => {
|
||||
size='sm'
|
||||
variant='ontime-subtle'
|
||||
>
|
||||
Add event
|
||||
Event...
|
||||
</MenuButton>
|
||||
<MenuList>
|
||||
<MenuItem icon={<IoAdd />} onClick={() => eventAction('event')}>
|
||||
Event at start
|
||||
Add event at start
|
||||
</MenuItem>
|
||||
<MenuItem icon={<IoTimerOutline />} onClick={() => eventAction('delay')}>
|
||||
Delay at start
|
||||
Add delay at start
|
||||
</MenuItem>
|
||||
<MenuItem icon={<FiMinusCircle />} onClick={() => eventAction('block')}>
|
||||
Block at start
|
||||
Add block at start
|
||||
</MenuItem>
|
||||
<MenuDivider />
|
||||
<MenuItem icon={<FiTrash2 />} onClick={() => eventAction('delete-all')} color='#D20300'>
|
||||
Delete All
|
||||
Delete all events
|
||||
</MenuItem>
|
||||
</MenuList>
|
||||
</Menu>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { createRef, Fragment, useCallback, useContext, useEffect } from 'react';
|
||||
import { DragDropContext, Droppable } from 'react-beautiful-dnd';
|
||||
import { Button } from '@chakra-ui/react';
|
||||
import { IoAdd } from '@react-icons/all-files/io5/IoAdd';
|
||||
import {
|
||||
defaultPublicAtom,
|
||||
showQuickEntryAtom,
|
||||
@@ -10,7 +11,7 @@ import Empty from 'common/components/state/Empty';
|
||||
import { CursorContext } from 'common/context/CursorContext';
|
||||
import { useEventAction } from 'common/hooks/useEventAction';
|
||||
import { useRundownEditor } from 'common/hooks/useSocket';
|
||||
import { duplicateEvent } from 'common/utils/eventsManager';
|
||||
import { cloneEvent } from 'common/utils/eventsManager';
|
||||
import { useAtomValue } from 'jotai';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
@@ -34,7 +35,7 @@ export default function Rundown(props) {
|
||||
const insertAtCursor = useCallback(
|
||||
(type, cursor) => {
|
||||
if (cursor === -1) {
|
||||
addEvent({ type: type });
|
||||
addEvent({ type });
|
||||
} else {
|
||||
const previousEvent = entries?.[cursor];
|
||||
const nextEvent = entries?.[cursor + 1];
|
||||
@@ -43,7 +44,7 @@ export default function Rundown(props) {
|
||||
const isPreviousDifferent = previousEvent?.type !== type;
|
||||
const isNextDifferent = nextEvent?.type !== type;
|
||||
if (type === 'clone' && previousEvent) {
|
||||
const newEvent = duplicateEvent(previousEvent);
|
||||
const newEvent = cloneEvent(previousEvent);
|
||||
newEvent.after = previousEvent.id;
|
||||
addEvent(newEvent);
|
||||
} else if (type === 'event') {
|
||||
@@ -57,7 +58,7 @@ export default function Rundown(props) {
|
||||
};
|
||||
addEvent(newEvent, options);
|
||||
} else if (isPreviousDifferent && isNextDifferent) {
|
||||
addEvent({ type: type, after: previousEvent.id });
|
||||
addEvent({ type, after: previousEvent.id });
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -73,7 +74,7 @@ export default function Rundown(props) {
|
||||
if (event.altKey && (!event.ctrlKey || !event.shiftKey)) {
|
||||
// Arrow down
|
||||
if (event.keyCode === 40) {
|
||||
if (cursor < entries.length - 1) moveCursorDown();
|
||||
if (cursor < entries.length - 2) moveCursorDown();
|
||||
}
|
||||
// Arrow up
|
||||
if (event.keyCode === 38) {
|
||||
@@ -165,8 +166,9 @@ export default function Rundown(props) {
|
||||
<Empty text='No data yet' style={{ marginTop: '7vh' }} />
|
||||
<Button
|
||||
onClick={() => insertAtCursor('event', cursor)}
|
||||
variant='solid'
|
||||
colorScheme='blue'
|
||||
variant='ontime-filled'
|
||||
className={style.spaceTop}
|
||||
leftIcon={<IoAdd />}
|
||||
>
|
||||
Create Event
|
||||
</Button>
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
@use '../../theme/main' as *;
|
||||
@use '../../theme/mixins' as *;
|
||||
|
||||
.eventContainer {
|
||||
margin-top: 1em;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 8px;
|
||||
padding: 8px 4px 8px 0;
|
||||
overflow-y: scroll;
|
||||
-ms-overflow-style: -ms-autohiding-scrollbar;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@@ -23,7 +21,7 @@
|
||||
.alignCenter {
|
||||
text-align: center;
|
||||
flex-direction: column;
|
||||
button {
|
||||
.spaceTop {
|
||||
margin-top: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import { LoggingContext } from 'common/context/LoggingContext';
|
||||
import { useEventAction } from 'common/hooks/useEventAction';
|
||||
import { OntimeEvent, OntimeRundownEntry } from 'common/models/EventTypes';
|
||||
import { Playstate } from 'common/models/OntimeTypes';
|
||||
import { duplicateEvent } from 'common/utils/eventsManager';
|
||||
import { cloneEvent } from 'common/utils/eventsManager';
|
||||
import { calculateDuration } from 'common/utils/timesManager';
|
||||
import { useAtom, useAtomValue } from 'jotai';
|
||||
|
||||
@@ -40,7 +40,17 @@ interface RundownEntryProps {
|
||||
}
|
||||
|
||||
export default function RundownEntry(props: RundownEntryProps) {
|
||||
const { index, eventIndex, data, selected, hasCursor, next, delay, previousEnd, playback } = props;
|
||||
const {
|
||||
index,
|
||||
eventIndex,
|
||||
data,
|
||||
selected,
|
||||
hasCursor,
|
||||
next,
|
||||
delay,
|
||||
previousEnd,
|
||||
playback,
|
||||
} = props;
|
||||
const { emitError } = useContext(LoggingContext);
|
||||
const startTimeIsLastEnd = useAtomValue(startTimeIsLastEndAtom);
|
||||
const defaultPublic = useAtomValue(defaultPublicAtom);
|
||||
@@ -88,7 +98,7 @@ export default function RundownEntry(props: RundownEntryProps) {
|
||||
break;
|
||||
}
|
||||
case 'clone': {
|
||||
const newEvent = duplicateEvent(data as OntimeEvent, data.id);
|
||||
const newEvent = cloneEvent(data as OntimeEvent, data.id);
|
||||
addEvent(newEvent);
|
||||
break;
|
||||
}
|
||||
@@ -161,7 +171,6 @@ export default function RundownEntry(props: RundownEntryProps) {
|
||||
return <BlockBlock index={index} data={data} actionHandler={actionHandler} />;
|
||||
} else if (data.type === 'delay') {
|
||||
return <DelayBlock index={index} data={data} actionHandler={actionHandler} />;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import { useContext, useEffect } from 'react';
|
||||
import Empty from 'common/components/state/Empty';
|
||||
import { LoggingContext } from 'common/context/LoggingContext';
|
||||
import RundownMenu from 'features/menu/RundownMenu';
|
||||
|
||||
import useRundown from '../../common/hooks-query/useRundown';
|
||||
@@ -10,14 +8,7 @@ import Rundown from './Rundown';
|
||||
import styles from '../editors/Editor.module.scss';
|
||||
|
||||
export default function RundownWrapper() {
|
||||
const { emitError } = useContext(LoggingContext);
|
||||
const { data, status, isError } = useRundown();
|
||||
|
||||
useEffect(() => {
|
||||
if (isError) {
|
||||
emitError('Error fetching data');
|
||||
}
|
||||
}, [emitError, isError]);
|
||||
const { data, status } = useRundown();
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -14,10 +14,10 @@ $secondary-block-height: 40px;
|
||||
@mixin block-styling() {
|
||||
box-sizing: content-box;
|
||||
background-color: $block-bg;
|
||||
border: 1px solid #383838;
|
||||
box-shadow: $block-box-shadow;
|
||||
border: 1px solid $white-10;
|
||||
font-family: $ontime-font-family;
|
||||
border-radius: $block-border-radius;
|
||||
margin: 4px 2px;
|
||||
}
|
||||
|
||||
@mixin block-spacing() {
|
||||
|
||||
@@ -3,10 +3,9 @@
|
||||
.block {
|
||||
@include block-spacing;
|
||||
@include block-styling;
|
||||
|
||||
box-sizing: content-box;
|
||||
display: grid;
|
||||
grid-template-columns: 32px 1fr;
|
||||
grid-template-columns: 32px 1fr auto;
|
||||
align-items: center;
|
||||
height: $secondary-block-height;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
@use '../../../theme/v2Styles' as *;
|
||||
@use '../../../theme/ontimeColours' as *;
|
||||
@use '../blockMixins' as *;
|
||||
|
||||
.eventBlock {
|
||||
@@ -15,20 +16,19 @@
|
||||
grid-template-columns: $block-binder-width auto 1fr auto;
|
||||
grid-template-rows: 4px 36px 36px 36px 4px;
|
||||
align-items: center;
|
||||
margin: 4px 2px;
|
||||
padding-right: $block-clearance;
|
||||
gap: 2px;
|
||||
|
||||
&.selected {
|
||||
background-color: #101010;
|
||||
background-color: $gray-1350;
|
||||
}
|
||||
|
||||
&.hasCursor {
|
||||
outline: 1px solid #779BE7;
|
||||
outline: 1px solid $blue-400;
|
||||
}
|
||||
|
||||
&.skip {
|
||||
border: 1px solid rgba(white, 0.03);
|
||||
border: 1px solid $white-3;
|
||||
box-shadow: none;
|
||||
|
||||
.delayNote,
|
||||
@@ -52,7 +52,7 @@
|
||||
|
||||
border-radius: $block-border-radius 0 0 $block-border-radius;
|
||||
|
||||
background-color: #303030; // to override inline
|
||||
background-color: $gray-1050; // to override inline
|
||||
color: $section-white;
|
||||
font-size: 17px;
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
.delayNote {
|
||||
font-size: 12px;
|
||||
line-height: 14px;
|
||||
color: #E69056;
|
||||
color: $ontime-delay-text;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
.progressBg {
|
||||
grid-area: progb;
|
||||
border-radius: 2px;
|
||||
background-color: #282828;
|
||||
background-color: $gray-1100;
|
||||
opacity: 1;
|
||||
height: 100%;
|
||||
}
|
||||
@@ -155,18 +155,10 @@
|
||||
.statusIcon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
color: #404040;
|
||||
color: $gray-1000;
|
||||
}
|
||||
|
||||
.statusNext.enabled {
|
||||
color: $playback-start;
|
||||
}
|
||||
|
||||
.statusDelay.enabled {
|
||||
color: $ontime-delay;
|
||||
}
|
||||
|
||||
.statusPublic.enabled {
|
||||
color: $action-blue;
|
||||
.statusIcon.active {
|
||||
color: $active-indicator;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { Draggable } from 'react-beautiful-dnd';
|
||||
import { Editable, EditableInput, EditablePreview, Tooltip } from '@chakra-ui/react';
|
||||
import { FiUsers } from '@react-icons/all-files/fi/FiUsers';
|
||||
import { IoOptions } from '@react-icons/all-files/io5/IoOptions';
|
||||
import { IoPeople } from '@react-icons/all-files/io5/IoPeople';
|
||||
import { IoPlay } from '@react-icons/all-files/io5/IoPlay';
|
||||
import { IoPlayOutline } from '@react-icons/all-files/io5/IoPlayOutline';
|
||||
import { IoPlaySkipForward } from '@react-icons/all-files/io5/IoPlaySkipForward';
|
||||
@@ -10,7 +10,6 @@ import { IoReload } from '@react-icons/all-files/io5/IoReload';
|
||||
import { IoRemoveCircle } from '@react-icons/all-files/io5/IoRemoveCircle';
|
||||
import { IoRemoveCircleOutline } from '@react-icons/all-files/io5/IoRemoveCircleOutline';
|
||||
import { IoReorderTwo } from '@react-icons/all-files/io5/IoReorderTwo';
|
||||
import { IoTimerOutline } from '@react-icons/all-files/io5/IoTimerOutline';
|
||||
import { editorEventId } from 'common/atoms/LocalEventSettings';
|
||||
import TooltipActionBtn from 'common/components/buttons/TooltipActionBtn';
|
||||
import { cx, getAccessibleColour } from 'common/utils/styleUtils';
|
||||
@@ -84,7 +83,6 @@ export default function EventBlock(props: EventBlockProps) {
|
||||
const [blockTitle, setBlockTitle] = useState<string>(title || '');
|
||||
|
||||
const binderColours = colour && getAccessibleColour(colour);
|
||||
const hasDelay = delay !== 0 && delay !== null;
|
||||
|
||||
// Todo: could I re-render the item without causing a state change here?
|
||||
// ?? use refs instead?
|
||||
@@ -173,7 +171,7 @@ export default function EventBlock(props: EventBlockProps) {
|
||||
{...blockBtnStyle}
|
||||
clickHandler={() => setEventPlayback.startEvent(eventId)}
|
||||
backgroundColor={eventIsPlaying ? '#58A151' : undefined}
|
||||
_hover={{backgroundColor: eventIsPlaying ? '#58A151' : undefined}}
|
||||
_hover={{ backgroundColor: eventIsPlaying ? '#58A151' : undefined }}
|
||||
tabIndex={-1}
|
||||
/>
|
||||
</div>
|
||||
@@ -207,25 +205,14 @@ export default function EventBlock(props: EventBlockProps) {
|
||||
shouldWrapChildren {...tooltipProps}
|
||||
>
|
||||
<IoPlaySkipForward
|
||||
className={`${style.statusIcon} ${style.statusNext} ${next ? style.enabled : ''}`} />
|
||||
</Tooltip>
|
||||
<Tooltip
|
||||
label='Event has delay'
|
||||
isDisabled={!hasDelay}
|
||||
shouldWrapChildren {...tooltipProps}
|
||||
>
|
||||
<IoTimerOutline className={`${style.statusIcon} ${style.statusDelay} ${
|
||||
hasDelay ? style.enabled : ''
|
||||
}`} />
|
||||
className={`${style.statusIcon} ${next ? style.active : ''}`} />
|
||||
</Tooltip>
|
||||
<Tooltip
|
||||
label={`${isPublic ? 'Event is public' : 'Event is private'}`}
|
||||
{...tooltipProps}
|
||||
shouldWrapChildren
|
||||
>
|
||||
<FiUsers className={`${style.statusIcon} ${style.statusPublic} ${
|
||||
isPublic ? style.enabled : ''
|
||||
}`} />
|
||||
<IoPeople className={`${style.statusIcon} ${isPublic ? style.active : ''}`} />
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
} from '@chakra-ui/react';
|
||||
import { IoAdd } from '@react-icons/all-files/io5/IoAdd';
|
||||
import { IoDuplicateOutline } from '@react-icons/all-files/io5/IoDuplicateOutline';
|
||||
import { IoEllipsisHorizontal } from '@react-icons/all-files/io5/IoEllipsisHorizontal';
|
||||
import { IoRemoveCircleOutline } from '@react-icons/all-files/io5/IoRemoveCircleOutline';
|
||||
import { IoTimerOutline } from '@react-icons/all-files/io5/IoTimerOutline';
|
||||
import { IoTrashBinSharp } from '@react-icons/all-files/io5/IoTrashBinSharp';
|
||||
@@ -34,7 +35,7 @@ export default function BlockActionMenu(props: BlockActionMenuProps) {
|
||||
<MenuButton
|
||||
as={IconButton}
|
||||
aria-label='Event options'
|
||||
icon={<IoAdd />}
|
||||
icon={<IoEllipsisHorizontal />}
|
||||
tabIndex={-1}
|
||||
variant='ontime-subtle'
|
||||
color='#f6f6f6'
|
||||
|
||||
@@ -15,19 +15,7 @@
|
||||
|
||||
.quickBtn {
|
||||
width: auto;
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
.createEvent {
|
||||
color: $light-bg;
|
||||
}
|
||||
|
||||
.createDelay {
|
||||
color: $block-delay-color;
|
||||
}
|
||||
|
||||
.createBlock {
|
||||
color: $block-block-color;
|
||||
padding: 0 32px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -67,32 +67,32 @@ export default function QuickAddBlock(props: QuickAddBlockProps) {
|
||||
<Button
|
||||
onClick={() => handleCreateEvent('event')}
|
||||
size='xs'
|
||||
variant='ontime-subtle'
|
||||
className={`${style.quickBtn} ${style.createBlock}`}
|
||||
variant='ontime-subtle-white'
|
||||
className={style.quickBtn}
|
||||
>
|
||||
E{showKbd && <span className={style.keyboard}>Alt + E</span>}
|
||||
Event {showKbd && <span className={style.keyboard}>Alt + E</span>}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Tooltip label='Add Delay' openDelay={tooltipDelayMid}>
|
||||
<Button
|
||||
onClick={() => handleCreateEvent('delay')}
|
||||
size='xs'
|
||||
variant='ontime-subtle'
|
||||
variant='ontime-subtle-white'
|
||||
disabled={disableAddDelay}
|
||||
className={`${style.quickBtn} ${style.createDelay}`}
|
||||
className={style.quickBtn}
|
||||
>
|
||||
D{showKbd && <span className={style.keyboard}>Alt + D</span>}
|
||||
Delay {showKbd && <span className={style.keyboard}>Alt + D</span>}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Tooltip label='Add Block' openDelay={tooltipDelayMid}>
|
||||
<Button
|
||||
onClick={() => handleCreateEvent('block')}
|
||||
size='xs'
|
||||
variant='ontime-subtle'
|
||||
variant='ontime-subtle-white'
|
||||
disabled={disableAddBlock}
|
||||
className={`${style.quickBtn} ${style.createEvent}`}
|
||||
className={style.quickBtn}
|
||||
>
|
||||
B{showKbd && <span className={style.keyboard}>Alt + B</span>}
|
||||
Block {showKbd && <span className={style.keyboard}>Alt + B</span>}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
@@ -54,7 +54,7 @@ export default function OntimeTable({ tableData, userFields, selectedId, handleU
|
||||
columns,
|
||||
data: tableData,
|
||||
initialState: {
|
||||
hiddenColumns: hiddenColumns,
|
||||
hiddenColumns,
|
||||
},
|
||||
handleUpdate,
|
||||
},
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { useCallback, useContext, useEffect } from 'react';
|
||||
|
||||
import { requestPatchEvent } from '../../common/api/eventsApi';
|
||||
import { TableSettingsContext } from '../../common/context/TableSettingsContext';
|
||||
import useMutateEvents from '../../common/hooks/useMutateEvents';
|
||||
import { useEventAction } from '../../common/hooks/useEventAction';
|
||||
import { useCuesheet } from '../../common/hooks/useSocket';
|
||||
import useRundown from '../../common/hooks-query/useRundown';
|
||||
import useUserFields from '../../common/hooks-query/useUserFields';
|
||||
@@ -17,9 +16,9 @@ export default function TableWrapper() {
|
||||
const { data: rundown } = useRundown();
|
||||
const { data: userFields } = useUserFields();
|
||||
const { data: featureData } = useCuesheet();
|
||||
|
||||
const mutation = useMutateEvents(requestPatchEvent);
|
||||
const { updateEvent } = useEventAction();
|
||||
const { theme } = useContext(TableSettingsContext);
|
||||
|
||||
// Set window title
|
||||
useEffect(() => {
|
||||
document.title = 'ontime - Cuesheet';
|
||||
@@ -55,11 +54,11 @@ export default function TableWrapper() {
|
||||
|
||||
// submit
|
||||
try {
|
||||
await mutation.mutateAsync(mutationObject);
|
||||
await updateEvent(mutationObject);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}, [mutation, rundown]);
|
||||
}, [updateEvent, rundown]);
|
||||
|
||||
const exportHandler = useCallback(
|
||||
(headerData) => {
|
||||
|
||||
@@ -56,10 +56,9 @@ const withSocket = (Component) => {
|
||||
const publicEvents = useMemo(() => {
|
||||
if (Array.isArray(eventsData)) {
|
||||
return eventsData.filter((d) => d.type === 'event' && d.title !== '' && d.isPublic);
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
},[eventsData])
|
||||
return [];
|
||||
}, [eventsData]);
|
||||
|
||||
/********************************************/
|
||||
/*** + titleManager ***/
|
||||
|
||||
@@ -46,7 +46,7 @@ export default function Countdown(props) {
|
||||
const eventId = searchParams.get('eventid');
|
||||
const eventIndex = searchParams.get('event');
|
||||
|
||||
let followThis = undefined;
|
||||
let followThis;
|
||||
const events = [...backstageEvents].filter((event) => event.type === 'event');
|
||||
|
||||
if (eventId !== null) {
|
||||
@@ -100,7 +100,7 @@ export default function Countdown(props) {
|
||||
<span className='event-select__title'>Select an event to follow</span>
|
||||
<ul className='event-select__events'>
|
||||
{backstageEvents.length === 0 ? (
|
||||
<Empty dark text='No events in database' />
|
||||
<Empty text='No events in database' />
|
||||
) : (
|
||||
backstageEvents
|
||||
.filter((e) => e.type === 'event')
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { StrictMode } from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
|
||||
import App from './App';
|
||||
@@ -5,10 +6,10 @@ import App from './App';
|
||||
import './index.scss';
|
||||
|
||||
const container = document.getElementById('root');
|
||||
const root = createRoot(container);
|
||||
const root = createRoot(container as Element);
|
||||
|
||||
root.render(
|
||||
// <StrictMode>
|
||||
<StrictMode>
|
||||
<App />
|
||||
// </StrictMode>
|
||||
</StrictMode>
|
||||
);
|
||||
@@ -10,8 +10,8 @@ $component-border-radius-sm: 2px;
|
||||
$action-blue: #3182ce;
|
||||
$action-text-color: $blue-400;
|
||||
$ontime-color: #ff7597;
|
||||
$error-red: $red-700;
|
||||
$warning-orange: $orange-700;
|
||||
$error-red: $red-500;
|
||||
$warning-orange: $orange-500;
|
||||
$opacity-disabled: 0.4;
|
||||
|
||||
// playback colours
|
||||
@@ -22,10 +22,11 @@ $ontime-delay-text: #E69056;
|
||||
$ontime-paused: #c05621;
|
||||
$ontime-stop: #E4281E;
|
||||
$playback-negative: $red-500;
|
||||
$active-indicator: #899948;
|
||||
|
||||
// interface panels
|
||||
// interface panels
|
||||
$bg-container-l1: $gray-1350;
|
||||
$bg-container-l2: $gray-1100;
|
||||
$bg-container-l2: $gray-1200;
|
||||
$bg-container-l3: $gray-1350;
|
||||
|
||||
$box-shadow-l1: rgba(0, 0, 0, 0.15) 0 3px 3px 0;
|
||||
|
||||
@@ -22,10 +22,11 @@ export const ontimeButtonFilled = {
|
||||
export const ontimeButtonOutlined = {
|
||||
...commonStyles,
|
||||
backgroundColor: '#2d2d2d', // $gray-1100
|
||||
color: '#779BE7', // $blue-400
|
||||
border: '1px solid #779BE7', // $blue-400
|
||||
color: '#9d9d9d', // $blue-400
|
||||
border: '1px solid rgba(255, 255, 255, 0.10)', // white-10
|
||||
_hover: {
|
||||
backgroundColor: '#404040', // $gray-1000
|
||||
color: '#e2e2e2', // $gray-200
|
||||
},
|
||||
_active: {
|
||||
backgroundColor: '#2d2d2d', // $gray-1100
|
||||
|
||||
@@ -15,7 +15,7 @@ export const ontimeCheckboxOnDark = {
|
||||
fontWeight: '200',
|
||||
color: '#9d9d9d', // $gray-500
|
||||
_checked: {
|
||||
color: '#779BE7', //$blue-400
|
||||
color: '#cfcfcf', // $gray-300
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
+395
-52
@@ -1527,33 +1527,38 @@
|
||||
"@svgr/hast-util-to-babel-ast" "^6.5.1"
|
||||
svg-parser "^2.0.4"
|
||||
|
||||
"@tanstack/match-sorter-utils@^8.1.1":
|
||||
version "8.5.14"
|
||||
resolved "https://registry.yarnpkg.com/@tanstack/match-sorter-utils/-/match-sorter-utils-8.5.14.tgz#12efcd536abe491d09521e0242bc4d51442f8a8a"
|
||||
integrity sha512-lVNhzTcOJ2bZ4IU+PeCPQ36vowBHvviJb2ZfdRFX5uhy7G0jM8N34zAMbmS5ZmVH8D2B7oU82OWo0e/5ZFzQrw==
|
||||
"@tanstack/eslint-plugin-query@^4.15.1":
|
||||
version "4.15.1"
|
||||
resolved "https://registry.yarnpkg.com/@tanstack/eslint-plugin-query/-/eslint-plugin-query-4.15.1.tgz#0be92fe6ffe10e7b0e47d192fa94af1d7fbb7b65"
|
||||
integrity sha512-SMj7OsOkutuJQ9LQLIoXxW5u0kx84V7RICmJEcjpKNkHsBd31QttJvtG1hLx9GXb3ZuFLZ0Y1dOD/D9b/GIzTg==
|
||||
|
||||
"@tanstack/match-sorter-utils@8.1.1":
|
||||
version "8.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@tanstack/match-sorter-utils/-/match-sorter-utils-8.1.1.tgz#895f407813254a46082a6bbafad9b39b943dc834"
|
||||
integrity sha512-IdmEekEYxQsoLOR0XQyw3jD1GujBpRRYaGJYQUw1eOT1eUugWxdc7jomh1VQ1EKHcdwDLpLaCz/8y4KraU4T9A==
|
||||
dependencies:
|
||||
remove-accents "0.4.2"
|
||||
|
||||
"@tanstack/query-core@4.10.3":
|
||||
version "4.10.3"
|
||||
resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-4.10.3.tgz#a6477bab9ed1ae4561ca0a59ae06f8c615c692b7"
|
||||
integrity sha512-+ME02sUmBfx3Pjd+0XtEthK8/4rVMD2jcxvnW9DSgFONpKtpjzfRzjY4ykzpDw1QEo2eoPvl7NS8J5mNI199aA==
|
||||
"@tanstack/query-core@4.18.0":
|
||||
version "4.18.0"
|
||||
resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-4.18.0.tgz#3e166ce319fd869c668536384ae94d174ea46a59"
|
||||
integrity sha512-PP4mG8MD08sq64RZCqMfXMYfaj7+Oulwg7xZ/fJoEOdTZNcPIgaOkHajZvUBsNLbi/0ViMvJB4cFkL2Jg2WPbw==
|
||||
|
||||
"@tanstack/react-query-devtools@^4.11.0":
|
||||
version "4.11.0"
|
||||
resolved "https://registry.yarnpkg.com/@tanstack/react-query-devtools/-/react-query-devtools-4.11.0.tgz#a2adf21fa644eae5b834ba4235b99818301ab702"
|
||||
integrity sha512-g/414SruE0TEp4jeMYxVUSXGXCc+zMY9j0gB8Q6B91gmyPseNqs9WLkVrqxRXoQDyRvDcphVOaEANNygGx+zGg==
|
||||
"@tanstack/react-query-devtools@^4.18.0":
|
||||
version "4.18.0"
|
||||
resolved "https://registry.yarnpkg.com/@tanstack/react-query-devtools/-/react-query-devtools-4.18.0.tgz#3c2d2295d11940a2c3cca356d247c6dd8443419c"
|
||||
integrity sha512-L51D0AUqLTs7J+W7RypJrUEKXsS0y0eEhXAgO+rhcZH6i8jVrKLhcNZStQSnE+UpZqPm73uxt2e8TJgYfzz0nw==
|
||||
dependencies:
|
||||
"@tanstack/match-sorter-utils" "^8.1.1"
|
||||
"@tanstack/match-sorter-utils" "8.1.1"
|
||||
superjson "^1.10.0"
|
||||
use-sync-external-store "^1.2.0"
|
||||
|
||||
"@tanstack/react-query@^4.10.3":
|
||||
version "4.10.3"
|
||||
resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-4.10.3.tgz#294deefa0fb6ada88bc4631d346ef5d5551c5443"
|
||||
integrity sha512-4OEJjkcsCTmG3ui7RjsVzsXerWQvInTe95CBKFyOV/GchMUlNztoFnnYmlMhX7hLUqJMhbG9l7M507V7+xU8Hw==
|
||||
"@tanstack/react-query@^4.18.0":
|
||||
version "4.18.0"
|
||||
resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-4.18.0.tgz#d9c661364b383fca79f5384cb97b445354068faa"
|
||||
integrity sha512-s1kdbGMdVcfUIllzsHUqVUdktBT5uuIRgnvrqFNLjl9TSOXEoBSDrhjsGjao0INQZv8cMpQlgOh3YH9YtN6cKw==
|
||||
dependencies:
|
||||
"@tanstack/query-core" "4.10.3"
|
||||
"@tanstack/query-core" "4.18.0"
|
||||
use-sync-external-store "^1.2.0"
|
||||
|
||||
"@testing-library/dom@^8.5.0":
|
||||
@@ -1969,6 +1974,14 @@ abab@^2.0.6:
|
||||
resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291"
|
||||
integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==
|
||||
|
||||
accepts@~1.3.8:
|
||||
version "1.3.8"
|
||||
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e"
|
||||
integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==
|
||||
dependencies:
|
||||
mime-types "~2.1.34"
|
||||
negotiator "0.6.3"
|
||||
|
||||
acorn-globals@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45"
|
||||
@@ -2078,6 +2091,11 @@ aria-query@^5.0.0:
|
||||
resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.0.0.tgz#210c21aaf469613ee8c9a62c7f86525e058db52c"
|
||||
integrity sha512-V+SM7AbUwJ+EBnB8+DXs0hPZHO0W6pqBcc0dW90OwtVG02PswOu/teuARoLQjdDOH+t9pJgGnW5/Qmouf3gPJg==
|
||||
|
||||
array-flatten@1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
|
||||
integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==
|
||||
|
||||
array-includes@^3.1.3:
|
||||
version "3.1.4"
|
||||
resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.4.tgz#f5b493162c760f3539631f005ba2bb46acb45ba9"
|
||||
@@ -2145,13 +2163,14 @@ autosize@^5.0.1:
|
||||
resolved "https://registry.yarnpkg.com/autosize/-/autosize-5.0.1.tgz#ed269b0fa9b7eb47627048a1bb3299e99e003a0f"
|
||||
integrity sha512-UIWUlE4TOVPNNj2jjrU39wI4hEYbneUypEqcyRmRFIx5CC2gNdg3rQr+Zh7/3h6egbBvm33TDQjNQKtj9Tk1HA==
|
||||
|
||||
axios@^0.27.2:
|
||||
version "0.27.2"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-0.27.2.tgz#207658cc8621606e586c85db4b41a750e756d972"
|
||||
integrity sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==
|
||||
axios@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-1.2.0.tgz#1cb65bd75162c70e9f8d118a905126c4a201d383"
|
||||
integrity sha512-zT7wZyNYu3N5Bu0wuZ6QccIf93Qk1eV8LOewxgjOZFd2DenOs98cJ7+Y6703d0wkaXGY6/nZd4EweJaHz9uzQw==
|
||||
dependencies:
|
||||
follow-redirects "^1.14.9"
|
||||
follow-redirects "^1.15.0"
|
||||
form-data "^4.0.0"
|
||||
proxy-from-env "^1.1.0"
|
||||
|
||||
babel-plugin-macros@^3.1.0:
|
||||
version "3.1.0"
|
||||
@@ -2177,6 +2196,24 @@ binary-extensions@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
|
||||
integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
|
||||
|
||||
body-parser@1.20.1:
|
||||
version "1.20.1"
|
||||
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668"
|
||||
integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==
|
||||
dependencies:
|
||||
bytes "3.1.2"
|
||||
content-type "~1.0.4"
|
||||
debug "2.6.9"
|
||||
depd "2.0.0"
|
||||
destroy "1.2.0"
|
||||
http-errors "2.0.0"
|
||||
iconv-lite "0.4.24"
|
||||
on-finished "2.4.1"
|
||||
qs "6.11.0"
|
||||
raw-body "2.5.1"
|
||||
type-is "~1.6.18"
|
||||
unpipe "1.0.0"
|
||||
|
||||
brace-expansion@^1.1.7:
|
||||
version "1.1.11"
|
||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
|
||||
@@ -2207,6 +2244,11 @@ browserslist@^4.21.3:
|
||||
node-releases "^2.0.6"
|
||||
update-browserslist-db "^1.0.9"
|
||||
|
||||
bytes@3.1.2:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5"
|
||||
integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==
|
||||
|
||||
call-bind@^1.0.0, call-bind@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
|
||||
@@ -2379,6 +2421,18 @@ concat-map@0.0.1:
|
||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
|
||||
|
||||
content-disposition@0.5.4:
|
||||
version "0.5.4"
|
||||
resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe"
|
||||
integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==
|
||||
dependencies:
|
||||
safe-buffer "5.2.1"
|
||||
|
||||
content-type@~1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
|
||||
integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
|
||||
|
||||
convert-source-map@^1.5.0, convert-source-map@^1.7.0:
|
||||
version "1.8.0"
|
||||
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369"
|
||||
@@ -2386,6 +2440,16 @@ convert-source-map@^1.5.0, convert-source-map@^1.7.0:
|
||||
dependencies:
|
||||
safe-buffer "~5.1.1"
|
||||
|
||||
cookie-signature@1.0.6:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
|
||||
integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==
|
||||
|
||||
cookie@0.5.0:
|
||||
version "0.5.0"
|
||||
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b"
|
||||
integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==
|
||||
|
||||
copy-anything@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/copy-anything/-/copy-anything-3.0.2.tgz#7189171ff5e1893b2287e8bf574b8cd448ed50b1"
|
||||
@@ -2487,6 +2551,13 @@ data-urls@^3.0.2:
|
||||
whatwg-mimetype "^3.0.0"
|
||||
whatwg-url "^11.0.0"
|
||||
|
||||
debug@2.6.9:
|
||||
version "2.6.9"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
||||
integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
|
||||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4:
|
||||
version "4.3.4"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
|
||||
@@ -2563,6 +2634,16 @@ delayed-stream@~1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
|
||||
integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
|
||||
|
||||
depd@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
|
||||
integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==
|
||||
|
||||
destroy@1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015"
|
||||
integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==
|
||||
|
||||
detect-node-es@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/detect-node-es/-/detect-node-es-1.1.0.tgz#163acdf643330caa0b4cd7c21e7ee7755d6fa493"
|
||||
@@ -2606,6 +2687,11 @@ domexception@^4.0.0:
|
||||
dependencies:
|
||||
webidl-conversions "^7.0.0"
|
||||
|
||||
ee-first@1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
|
||||
integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==
|
||||
|
||||
electron-to-chromium@^1.4.251:
|
||||
version "1.4.255"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.255.tgz#dc52d1095b876ed8acf25865db10265b02b1d6e1"
|
||||
@@ -2616,10 +2702,15 @@ emoji-regex@^8.0.0:
|
||||
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
|
||||
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
|
||||
|
||||
engine.io-client@~6.2.1:
|
||||
version "6.2.1"
|
||||
resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-6.2.1.tgz#b6d0be614c3f194faf6ab5505eba7eb456f56b0d"
|
||||
integrity sha512-5cu7xubVxEwoB6O9hJ6Zfu990yBVjXfyMlE1ZvfO5L8if3Kvc9bgDNEapV0C5pMp+5Om1UZFnljxoOuFm6dBKA==
|
||||
encodeurl@~1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
|
||||
integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==
|
||||
|
||||
engine.io-client@~6.2.3:
|
||||
version "6.2.3"
|
||||
resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-6.2.3.tgz#a8cbdab003162529db85e9de31575097f6d29458"
|
||||
integrity sha512-aXPtgF1JS3RuuKcpSrBtimSjYvrbhKW9froICH4s0F3XQWLxsKNxqzG39nnvQZQnva4CMvUK63T7shevxRyYHw==
|
||||
dependencies:
|
||||
"@socket.io/component-emitter" "~3.1.0"
|
||||
debug "~4.3.1"
|
||||
@@ -2850,6 +2941,11 @@ escalade@^3.1.1:
|
||||
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
|
||||
integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
|
||||
|
||||
escape-html@~1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
|
||||
integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==
|
||||
|
||||
escape-string-regexp@^1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
||||
@@ -3041,6 +3137,11 @@ esutils@^2.0.2:
|
||||
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
|
||||
integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
|
||||
|
||||
etag@~1.8.1:
|
||||
version "1.8.1"
|
||||
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
|
||||
integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==
|
||||
|
||||
execall@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/execall/-/execall-2.0.0.tgz#16a06b5fe5099df7d00be5d9c06eecded1663b45"
|
||||
@@ -3048,6 +3149,43 @@ execall@^2.0.0:
|
||||
dependencies:
|
||||
clone-regexp "^2.1.0"
|
||||
|
||||
express@^4.18.2:
|
||||
version "4.18.2"
|
||||
resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59"
|
||||
integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==
|
||||
dependencies:
|
||||
accepts "~1.3.8"
|
||||
array-flatten "1.1.1"
|
||||
body-parser "1.20.1"
|
||||
content-disposition "0.5.4"
|
||||
content-type "~1.0.4"
|
||||
cookie "0.5.0"
|
||||
cookie-signature "1.0.6"
|
||||
debug "2.6.9"
|
||||
depd "2.0.0"
|
||||
encodeurl "~1.0.2"
|
||||
escape-html "~1.0.3"
|
||||
etag "~1.8.1"
|
||||
finalhandler "1.2.0"
|
||||
fresh "0.5.2"
|
||||
http-errors "2.0.0"
|
||||
merge-descriptors "1.0.1"
|
||||
methods "~1.1.2"
|
||||
on-finished "2.4.1"
|
||||
parseurl "~1.3.3"
|
||||
path-to-regexp "0.1.7"
|
||||
proxy-addr "~2.0.7"
|
||||
qs "6.11.0"
|
||||
range-parser "~1.2.1"
|
||||
safe-buffer "5.2.1"
|
||||
send "0.18.0"
|
||||
serve-static "1.15.0"
|
||||
setprototypeof "1.2.0"
|
||||
statuses "2.0.1"
|
||||
type-is "~1.6.18"
|
||||
utils-merge "1.0.1"
|
||||
vary "~1.1.2"
|
||||
|
||||
fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
|
||||
version "3.1.3"
|
||||
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
|
||||
@@ -3100,6 +3238,19 @@ fill-range@^7.0.1:
|
||||
dependencies:
|
||||
to-regex-range "^5.0.1"
|
||||
|
||||
finalhandler@1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32"
|
||||
integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==
|
||||
dependencies:
|
||||
debug "2.6.9"
|
||||
encodeurl "~1.0.2"
|
||||
escape-html "~1.0.3"
|
||||
on-finished "2.4.1"
|
||||
parseurl "~1.3.3"
|
||||
statuses "2.0.1"
|
||||
unpipe "~1.0.0"
|
||||
|
||||
find-root@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4"
|
||||
@@ -3141,10 +3292,10 @@ focus-lock@^0.11.2:
|
||||
dependencies:
|
||||
tslib "^2.0.3"
|
||||
|
||||
follow-redirects@^1.14.9:
|
||||
version "1.15.1"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.1.tgz#0ca6a452306c9b276e4d3127483e29575e207ad5"
|
||||
integrity sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==
|
||||
follow-redirects@^1.15.0:
|
||||
version "1.15.2"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13"
|
||||
integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==
|
||||
|
||||
form-data@^4.0.0:
|
||||
version "4.0.0"
|
||||
@@ -3155,6 +3306,11 @@ form-data@^4.0.0:
|
||||
combined-stream "^1.0.8"
|
||||
mime-types "^2.1.12"
|
||||
|
||||
forwarded@0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811"
|
||||
integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==
|
||||
|
||||
framer-motion@^7.5.3:
|
||||
version "7.6.12"
|
||||
resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-7.6.12.tgz#a1f228e00da03ceb78482ae4a7fba63be39d34e4"
|
||||
@@ -3183,6 +3339,11 @@ framesync@6.1.2:
|
||||
dependencies:
|
||||
tslib "2.4.0"
|
||||
|
||||
fresh@0.5.2:
|
||||
version "0.5.2"
|
||||
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
|
||||
integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==
|
||||
|
||||
fs.realpath@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||
@@ -3444,6 +3605,17 @@ html-tags@^3.2.0:
|
||||
resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.2.0.tgz#dbb3518d20b726524e4dd43de397eb0a95726961"
|
||||
integrity sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg==
|
||||
|
||||
http-errors@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3"
|
||||
integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==
|
||||
dependencies:
|
||||
depd "2.0.0"
|
||||
inherits "2.0.4"
|
||||
setprototypeof "1.2.0"
|
||||
statuses "2.0.1"
|
||||
toidentifier "1.0.1"
|
||||
|
||||
http-proxy-agent@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43"
|
||||
@@ -3461,6 +3633,13 @@ https-proxy-agent@^5.0.1:
|
||||
agent-base "6"
|
||||
debug "4"
|
||||
|
||||
iconv-lite@0.4.24:
|
||||
version "0.4.24"
|
||||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
|
||||
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
|
||||
dependencies:
|
||||
safer-buffer ">= 2.1.2 < 3"
|
||||
|
||||
iconv-lite@0.6.3:
|
||||
version "0.6.3"
|
||||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501"
|
||||
@@ -3509,7 +3688,7 @@ inflight@^1.0.4:
|
||||
once "^1.3.0"
|
||||
wrappy "1"
|
||||
|
||||
inherits@2, inherits@^2.0.4:
|
||||
inherits@2, inherits@2.0.4, inherits@^2.0.4:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||
@@ -3535,6 +3714,11 @@ invariant@^2.2.4:
|
||||
dependencies:
|
||||
loose-envify "^1.0.0"
|
||||
|
||||
ipaddr.js@1.9.1:
|
||||
version "1.9.1"
|
||||
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
|
||||
integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==
|
||||
|
||||
is-arrayish@^0.2.1:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
|
||||
@@ -3720,10 +3904,10 @@ jest-get-type@^27.4.0:
|
||||
resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.4.0.tgz#7503d2663fffa431638337b3998d39c5e928e9b5"
|
||||
integrity sha512-tk9o+ld5TWq41DkK14L4wox4s2D9MtTpKaAVzXfr5CUKm5ZK2ExcaFE0qls2W71zE/6R2TxxrK9w2r6svAFDBQ==
|
||||
|
||||
jotai@^1.8.5:
|
||||
version "1.8.5"
|
||||
resolved "https://registry.yarnpkg.com/jotai/-/jotai-1.8.5.tgz#a1d64682cc7b12697782488d5b6c6cfb54051520"
|
||||
integrity sha512-c6MGQ3S0X8VctRUEmRLEL3FMib3F7Ppsx3x86c5XL+Gm6JjH6qIt0lb0F4yE2V5/9Tg+KhGiagfsdA5lg0D7cQ==
|
||||
jotai@^1.10.0:
|
||||
version "1.10.0"
|
||||
resolved "https://registry.yarnpkg.com/jotai/-/jotai-1.10.0.tgz#50c5224789282eca1cdc907a51e316d8d94c5976"
|
||||
integrity sha512-3Q8kQU3Ktds+80Ku4dVcvnwSXEcK0Fg0b6mC1+4wz3rmF64lOGNUySKXQ4njvYCWodR8bw2HygOKYSYkHxQQmA==
|
||||
|
||||
js-sdsl@^4.1.4:
|
||||
version "4.1.4"
|
||||
@@ -3904,10 +4088,10 @@ lru-cache@^6.0.0:
|
||||
dependencies:
|
||||
yallist "^4.0.0"
|
||||
|
||||
luxon@^3.0.1:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/luxon/-/luxon-3.0.3.tgz#573e65531efd3d92265feb640f02ba7a192e2388"
|
||||
integrity sha512-+EfHWnF+UT7GgTnq5zXg3ldnTKL2zdv7QJgsU5bjjpbH17E3qi/puMhQyJVYuCq+FRkogvB5WB6iVvUr+E4a7w==
|
||||
luxon@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/luxon/-/luxon-3.1.0.tgz#9ac33d7142b7ea18d4ec8583cdeb0b079abef60d"
|
||||
integrity sha512-7w6hmKC0/aoWnEsmPCu5Br54BmbmUp5GfcqBxQngRcXJ+q5fdfjEzn7dxmJh2YdDhgW8PccYtlWKSv4tQkrTQg==
|
||||
|
||||
lz-string@^1.4.4:
|
||||
version "1.4.4"
|
||||
@@ -3936,6 +4120,11 @@ mathml-tag-names@^2.1.3:
|
||||
resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz#4ddadd67308e780cf16a47685878ee27b736a0a3"
|
||||
integrity sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==
|
||||
|
||||
media-typer@0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
|
||||
integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==
|
||||
|
||||
memoize-one@^5.1.1:
|
||||
version "5.2.1"
|
||||
resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e"
|
||||
@@ -3959,11 +4148,21 @@ meow@^9.0.0:
|
||||
type-fest "^0.18.0"
|
||||
yargs-parser "^20.2.3"
|
||||
|
||||
merge-descriptors@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
|
||||
integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==
|
||||
|
||||
merge2@^1.3.0, merge2@^1.4.1:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
|
||||
integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
|
||||
|
||||
methods@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
|
||||
integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==
|
||||
|
||||
micromatch@^4.0.4, micromatch@^4.0.5:
|
||||
version "4.0.5"
|
||||
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6"
|
||||
@@ -3977,13 +4176,18 @@ mime-db@1.52.0:
|
||||
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
|
||||
integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
|
||||
|
||||
mime-types@^2.1.12:
|
||||
mime-types@^2.1.12, mime-types@~2.1.24, mime-types@~2.1.34:
|
||||
version "2.1.35"
|
||||
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
|
||||
integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
|
||||
dependencies:
|
||||
mime-db "1.52.0"
|
||||
|
||||
mime@1.6.0:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
|
||||
integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
|
||||
|
||||
min-indent@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869"
|
||||
@@ -4010,11 +4214,21 @@ minimist@^1.2.6:
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
|
||||
integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==
|
||||
|
||||
ms@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
||||
integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==
|
||||
|
||||
ms@2.1.2:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
||||
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||
|
||||
ms@2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
|
||||
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
|
||||
|
||||
nanoid@^3.3.4:
|
||||
version "3.3.4"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab"
|
||||
@@ -4025,6 +4239,11 @@ natural-compare@^1.4.0:
|
||||
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
|
||||
integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=
|
||||
|
||||
negotiator@0.6.3:
|
||||
version "0.6.3"
|
||||
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd"
|
||||
integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==
|
||||
|
||||
node-releases@^2.0.6:
|
||||
version "2.0.6"
|
||||
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503"
|
||||
@@ -4135,6 +4354,13 @@ object.values@^1.1.5:
|
||||
define-properties "^1.1.3"
|
||||
es-abstract "^1.19.1"
|
||||
|
||||
on-finished@2.4.1:
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f"
|
||||
integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==
|
||||
dependencies:
|
||||
ee-first "1.1.1"
|
||||
|
||||
once@^1.3.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
||||
@@ -4223,6 +4449,11 @@ parse5@^7.0.0:
|
||||
dependencies:
|
||||
entities "^4.4.0"
|
||||
|
||||
parseurl@~1.3.3:
|
||||
version "1.3.3"
|
||||
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
|
||||
integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
|
||||
|
||||
path-exists@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
|
||||
@@ -4243,6 +4474,11 @@ path-parse@^1.0.6, path-parse@^1.0.7:
|
||||
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
|
||||
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
|
||||
|
||||
path-to-regexp@0.1.7:
|
||||
version "0.1.7"
|
||||
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
|
||||
integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==
|
||||
|
||||
path-type@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
|
||||
@@ -4379,6 +4615,19 @@ prop-types@^15.8.1:
|
||||
object-assign "^4.1.1"
|
||||
react-is "^16.13.1"
|
||||
|
||||
proxy-addr@~2.0.7:
|
||||
version "2.0.7"
|
||||
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025"
|
||||
integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==
|
||||
dependencies:
|
||||
forwarded "0.2.0"
|
||||
ipaddr.js "1.9.1"
|
||||
|
||||
proxy-from-env@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
|
||||
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
|
||||
|
||||
psl@^1.1.33:
|
||||
version "1.8.0"
|
||||
resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24"
|
||||
@@ -4394,6 +4643,13 @@ qr.js@0.0.0:
|
||||
resolved "https://registry.yarnpkg.com/qr.js/-/qr.js-0.0.0.tgz#cace86386f59a0db8050fa90d9b6b0e88a1e364f"
|
||||
integrity sha1-ys6GOG9ZoNuAUPqQ2baw6IoeNk8=
|
||||
|
||||
qs@6.11.0:
|
||||
version "6.11.0"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a"
|
||||
integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==
|
||||
dependencies:
|
||||
side-channel "^1.0.4"
|
||||
|
||||
queue-microtask@^1.2.2:
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
|
||||
@@ -4409,6 +4665,21 @@ raf-schd@^4.0.2:
|
||||
resolved "https://registry.yarnpkg.com/raf-schd/-/raf-schd-4.0.3.tgz#5d6c34ef46f8b2a0e880a8fcdb743efc5bfdbc1a"
|
||||
integrity sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==
|
||||
|
||||
range-parser@~1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
|
||||
integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
|
||||
|
||||
raw-body@2.5.1:
|
||||
version "2.5.1"
|
||||
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857"
|
||||
integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==
|
||||
dependencies:
|
||||
bytes "3.1.2"
|
||||
http-errors "2.0.0"
|
||||
iconv-lite "0.4.24"
|
||||
unpipe "1.0.0"
|
||||
|
||||
react-beautiful-dnd@^13.1.1:
|
||||
version "13.1.1"
|
||||
resolved "https://registry.yarnpkg.com/react-beautiful-dnd/-/react-beautiful-dnd-13.1.1.tgz#b0f3087a5840920abf8bb2325f1ffa46d8c4d0a2"
|
||||
@@ -4723,12 +4994,17 @@ run-parallel@^1.1.9:
|
||||
dependencies:
|
||||
queue-microtask "^1.2.2"
|
||||
|
||||
safe-buffer@5.2.1:
|
||||
version "5.2.1"
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
||||
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
|
||||
|
||||
safe-buffer@~5.1.1:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
|
||||
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
|
||||
|
||||
"safer-buffer@>= 2.1.2 < 3.0.0":
|
||||
"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0":
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
|
||||
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
|
||||
@@ -4787,6 +5063,40 @@ semver@^7.3.5:
|
||||
dependencies:
|
||||
lru-cache "^6.0.0"
|
||||
|
||||
send@0.18.0:
|
||||
version "0.18.0"
|
||||
resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be"
|
||||
integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==
|
||||
dependencies:
|
||||
debug "2.6.9"
|
||||
depd "2.0.0"
|
||||
destroy "1.2.0"
|
||||
encodeurl "~1.0.2"
|
||||
escape-html "~1.0.3"
|
||||
etag "~1.8.1"
|
||||
fresh "0.5.2"
|
||||
http-errors "2.0.0"
|
||||
mime "1.6.0"
|
||||
ms "2.1.3"
|
||||
on-finished "2.4.1"
|
||||
range-parser "~1.2.1"
|
||||
statuses "2.0.1"
|
||||
|
||||
serve-static@1.15.0:
|
||||
version "1.15.0"
|
||||
resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540"
|
||||
integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==
|
||||
dependencies:
|
||||
encodeurl "~1.0.2"
|
||||
escape-html "~1.0.3"
|
||||
parseurl "~1.3.3"
|
||||
send "0.18.0"
|
||||
|
||||
setprototypeof@1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424"
|
||||
integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==
|
||||
|
||||
shebang-command@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
|
||||
@@ -4834,20 +5144,20 @@ slice-ansi@^4.0.0:
|
||||
astral-regex "^2.0.0"
|
||||
is-fullwidth-code-point "^3.0.0"
|
||||
|
||||
socket.io-client@^4.5.2:
|
||||
version "4.5.2"
|
||||
resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-4.5.2.tgz#9481518c560388c980c88b01e3cf62f367f04c96"
|
||||
integrity sha512-naqYfFu7CLDiQ1B7AlLhRXKX3gdeaIMfgigwavDzgJoIUYulc1qHH5+2XflTsXTPY7BlPH5rppJyUjhjrKQKLg==
|
||||
socket.io-client@^4.5.4:
|
||||
version "4.5.4"
|
||||
resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-4.5.4.tgz#d3cde8a06a6250041ba7390f08d2468ccebc5ac9"
|
||||
integrity sha512-ZpKteoA06RzkD32IbqILZ+Cnst4xewU7ZYK12aS1mzHftFFjpoMz69IuhP/nL25pJfao/amoPI527KnuhFm01g==
|
||||
dependencies:
|
||||
"@socket.io/component-emitter" "~3.1.0"
|
||||
debug "~4.3.2"
|
||||
engine.io-client "~6.2.1"
|
||||
socket.io-parser "~4.2.0"
|
||||
engine.io-client "~6.2.3"
|
||||
socket.io-parser "~4.2.1"
|
||||
|
||||
socket.io-parser@~4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.2.0.tgz#3f01e5bc525d94aa52a97ed5cbc12e229bbc4d6b"
|
||||
integrity sha512-tLfmEwcEwnlQTxFB7jibL/q2+q8dlVQzj4JdRLJ/W/G1+Fu9VSxCx1Lo+n1HvXxKnM//dUuD0xgiA7tQf57Vng==
|
||||
socket.io-parser@~4.2.1:
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.2.1.tgz#01c96efa11ded938dcb21cbe590c26af5eff65e5"
|
||||
integrity sha512-V4GrkLy+HeF1F/en3SpUaM+7XxYXpuMUWLGde1kSSh5nQMN4hLrbPIkD+otwh6q9R6NOQBN4AMaOZ2zVjui82g==
|
||||
dependencies:
|
||||
"@socket.io/component-emitter" "~3.1.0"
|
||||
debug "~4.3.1"
|
||||
@@ -4906,6 +5216,11 @@ spdx-license-ids@^3.0.0:
|
||||
resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz#50c0d8c40a14ec1bf449bae69a0ea4685a9d9f95"
|
||||
integrity sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==
|
||||
|
||||
statuses@2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63"
|
||||
integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==
|
||||
|
||||
string-width@^4.2.3:
|
||||
version "4.2.3"
|
||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
||||
@@ -5205,6 +5520,11 @@ toggle-selection@^1.0.6:
|
||||
resolved "https://registry.yarnpkg.com/toggle-selection/-/toggle-selection-1.0.6.tgz#6e45b1263f2017fa0acc7d89d78b15b8bf77da32"
|
||||
integrity sha1-bkWxJj8gF/oKzH2J14sVuL932jI=
|
||||
|
||||
toidentifier@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35"
|
||||
integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==
|
||||
|
||||
tough-cookie@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.0.0.tgz#d822234eeca882f991f0f908824ad2622ddbece4"
|
||||
@@ -5306,6 +5626,14 @@ type-fest@^0.8.1:
|
||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"
|
||||
integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==
|
||||
|
||||
type-is@~1.6.18:
|
||||
version "1.6.18"
|
||||
resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
|
||||
integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==
|
||||
dependencies:
|
||||
media-typer "0.3.0"
|
||||
mime-types "~2.1.24"
|
||||
|
||||
typeface-open-sans@^1.1.13:
|
||||
version "1.1.13"
|
||||
resolved "https://registry.yarnpkg.com/typeface-open-sans/-/typeface-open-sans-1.1.13.tgz#32a09ebd7df59601e01ad81216f98ce641eeafd1"
|
||||
@@ -5341,6 +5669,11 @@ universalify@^0.1.2:
|
||||
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
|
||||
integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
|
||||
|
||||
unpipe@1.0.0, unpipe@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
|
||||
integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==
|
||||
|
||||
update-browserslist-db@^1.0.9:
|
||||
version "1.0.9"
|
||||
resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.9.tgz#2924d3927367a38d5c555413a7ce138fc95fcb18"
|
||||
@@ -5386,6 +5719,11 @@ util-deprecate@^1.0.2:
|
||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
|
||||
|
||||
utils-merge@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
|
||||
integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==
|
||||
|
||||
v8-compile-cache@^2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"
|
||||
@@ -5399,6 +5737,11 @@ validate-npm-package-license@^3.0.1:
|
||||
spdx-correct "^3.0.0"
|
||||
spdx-expression-parse "^3.0.0"
|
||||
|
||||
vary@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
|
||||
integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==
|
||||
|
||||
vite-plugin-svgr@^2.2.2:
|
||||
version "2.2.2"
|
||||
resolved "https://registry.yarnpkg.com/vite-plugin-svgr/-/vite-plugin-svgr-2.2.2.tgz#c5c9cb573bf455bb079550531847ddc5d2e122af"
|
||||
|
||||
@@ -2,3 +2,4 @@ node_modules/
|
||||
/test-results/
|
||||
/playwright-report/
|
||||
/playwright/.cache/
|
||||
/src/version.js
|
||||
|
||||
+6
-6
@@ -28,6 +28,11 @@ const appIcon = path.join(__dirname, './assets/logo.png');
|
||||
let loaded = 'Nothing loaded';
|
||||
let isQuitting = false;
|
||||
|
||||
// initialise
|
||||
let win;
|
||||
let splash;
|
||||
let tray = null;
|
||||
|
||||
(async () => {
|
||||
try {
|
||||
const loadDepPath = isProduction
|
||||
@@ -56,7 +61,7 @@ let isQuitting = false;
|
||||
*/
|
||||
function showNotification(title, text) {
|
||||
new Notification({
|
||||
title: title,
|
||||
title,
|
||||
body: text,
|
||||
silent: true,
|
||||
}).show();
|
||||
@@ -82,13 +87,8 @@ function askToQuit() {
|
||||
win.send('user-request-shutdown');
|
||||
}
|
||||
|
||||
let win;
|
||||
let splash;
|
||||
let tray = null;
|
||||
|
||||
// Ensure there isn't another instance of the app running already
|
||||
const lock = app.requestSingleInstanceLock();
|
||||
|
||||
if (!lock) {
|
||||
dialog.showErrorBox('Multiple instances', 'An instance if the App is already running.');
|
||||
app.quit();
|
||||
|
||||
+3
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ontime",
|
||||
"version": "1.9.6",
|
||||
"version": "2.0.0-alpha",
|
||||
"author": "Carlos Valente",
|
||||
"description": "Time keeping for live events",
|
||||
"repository": "https://github.com/cpvalente/ontime",
|
||||
@@ -26,6 +26,8 @@
|
||||
"supertest": "^6.2.2"
|
||||
},
|
||||
"scripts": {
|
||||
"setup": "yarn install && yarn setdb && yarn addversion",
|
||||
"addversion": "node -p \"'export const ONTIME_VERSION = ' + JSON.stringify(require('./package.json').version) + ';'\" > src/version.js",
|
||||
"nodestart": "NODE_ENV=development node src/app.js",
|
||||
"setdb": "cp demo-db/db.json src/preloaded-db/db.json",
|
||||
"clean": "rm -rf ../client/build/ && rm -rf ../client/node_modules && rm -rf src/node_modules && rm -rf ./node_modules && rm -rf ./dist",
|
||||
|
||||
+2
-1
@@ -26,6 +26,7 @@ import { socketProvider } from './classes/socket/SocketController.js';
|
||||
import { initiateOSC, shutdownOSCServer } from './controllers/OscController.js';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { DataProvider } from './classes/data-provider/DataProvider.js';
|
||||
import { ONTIME_VERSION } from './version.js';
|
||||
|
||||
// get environment
|
||||
const env = process.env.NODE_ENV || 'production';
|
||||
@@ -33,7 +34,7 @@ const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
const isTest = process.env.IS_TEST;
|
||||
|
||||
console.log(`Starting ontime version ${process.env.npm_package_version}`);
|
||||
console.log(`Starting ontime version ${ONTIME_VERSION}`);
|
||||
|
||||
// import socket provider
|
||||
const socket = socketProvider;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Class Event Provider is a mediator for handling the local db
|
||||
* and adds logic specific to ontime data
|
||||
*/
|
||||
import { db, data } from '../../modules/loadDb.js';
|
||||
import { data, db } from '../../modules/loadDb.js';
|
||||
|
||||
export class DataProvider {
|
||||
static getData() {
|
||||
@@ -42,7 +42,7 @@ export class DataProvider {
|
||||
await this.persist();
|
||||
}
|
||||
|
||||
static getNumEvents() {
|
||||
static getRundownLenght() {
|
||||
return data.rundown.length;
|
||||
}
|
||||
|
||||
|
||||
@@ -99,17 +99,16 @@ export class EventLoader {
|
||||
*/
|
||||
findPrevious() {
|
||||
const timedEvents = EventLoader.getPlayableEvents();
|
||||
if (timedEvents === null || this.selectedEventIndex === 0) {
|
||||
if (timedEvents === null || !timedEvents.length || this.selectedEventIndex === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// if there is no event running, go to first
|
||||
if (this.selectedEventIndex === null) {
|
||||
return { id: timedEvents[0].id };
|
||||
} else {
|
||||
const newIndex = this.selectedEventIndex - 1;
|
||||
return { id: timedEvents?.[newIndex].id };
|
||||
}
|
||||
const newIndex = this.selectedEventIndex - 1;
|
||||
return { id: timedEvents?.[newIndex].id };
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -118,17 +117,20 @@ export class EventLoader {
|
||||
*/
|
||||
findNext() {
|
||||
const timedEvents = EventLoader.getPlayableEvents();
|
||||
if (timedEvents === null || this.selectedEventIndex === this.numEvents - 1) {
|
||||
if (
|
||||
timedEvents === null ||
|
||||
!timedEvents.length ||
|
||||
this.selectedEventIndex === this.numEvents - 1
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// if there is no event running, go to first
|
||||
if (this.selectedEventIndex === null) {
|
||||
return { id: timedEvents[0].id };
|
||||
} else {
|
||||
const newIndex = this.selectedEventIndex + 1;
|
||||
return { id: timedEvents?.[newIndex].id };
|
||||
}
|
||||
const newIndex = this.selectedEventIndex + 1;
|
||||
return { id: timedEvents?.[newIndex].id };
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,7 +4,6 @@ import { OSCIntegration } from './integrations/Osc.js';
|
||||
import { HTTPIntegration } from './integrations/Http.js';
|
||||
import { cleanURL } from '../../utils/url.js';
|
||||
import { EventLoader, eventLoader } from '../event-loader/EventLoader.js';
|
||||
import { DataProvider } from '../data-provider/DataProvider.js';
|
||||
|
||||
/*
|
||||
* Class EventTimer adds functions specific to APP
|
||||
@@ -143,7 +142,7 @@ export class EventTimer extends Timer {
|
||||
* @private
|
||||
*/
|
||||
_broadcastFeaturePlaybackControl() {
|
||||
const numEvents = DataProvider.getNumEvents();
|
||||
const numEvents = EventLoader.getNumEvents();
|
||||
const featureData = {
|
||||
playback: this.state,
|
||||
selectedEventId: this.selectedEventId,
|
||||
@@ -157,7 +156,7 @@ export class EventTimer extends Timer {
|
||||
* @private
|
||||
*/
|
||||
_broadcastFeatureInfo() {
|
||||
const numEvents = DataProvider.getNumEvents();
|
||||
const numEvents = EventLoader.getNumEvents();
|
||||
const featureData = {
|
||||
titles: this.titles,
|
||||
playback: this.state,
|
||||
@@ -169,7 +168,7 @@ export class EventTimer extends Timer {
|
||||
}
|
||||
|
||||
_broadcastFeatureCuesheet() {
|
||||
const numEvents = DataProvider.getNumEvents();
|
||||
const numEvents = EventLoader.getNumEvents();
|
||||
const featureData = {
|
||||
playback: this.state,
|
||||
selectedEventId: this.selectedEventId,
|
||||
@@ -426,7 +425,7 @@ export class EventTimer extends Timer {
|
||||
return;
|
||||
}
|
||||
|
||||
const { loadedEvent, loadedEventIndex, selectedEventId, nextEventId, titles, titlesPublic } =
|
||||
const { loadedEvent, selectedEventIndex, selectedEventId, nextEventId, titles, titlesPublic } =
|
||||
loadedData;
|
||||
|
||||
const start = loadedEvent.timeStart || 0;
|
||||
@@ -438,7 +437,7 @@ export class EventTimer extends Timer {
|
||||
}
|
||||
|
||||
this.duration = end - start;
|
||||
this.selectedEventIndex = loadedEventIndex;
|
||||
this.selectedEventIndex = selectedEventIndex;
|
||||
this.selectedEventId = selectedEventId;
|
||||
this.nextEventId = nextEventId;
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ export const dbDownload = async (req, res) => {
|
||||
res.download(dbInDisk, `${fileTitle}.json`, (err) => {
|
||||
if (err) {
|
||||
res.status(500).send({
|
||||
message: 'Could not download the file. ' + err,
|
||||
message: `Could not download the file: ${err}`,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -5,8 +5,8 @@ import { fileURLToPath } from 'url';
|
||||
import { ensureDirectory, getAppDataPath } from '../utils/fileManagement.js';
|
||||
import { config } from '../config/config.js';
|
||||
import { validateFile } from '../utils/parserUtils.js';
|
||||
import { dbModel as dbModel } from '../models/dataModel.js';
|
||||
import { parseJson as parseJson } from '../utils/parser.js';
|
||||
import { dbModel } from '../models/dataModel.js';
|
||||
import { parseJson } from '../utils/parser.js';
|
||||
|
||||
/**
|
||||
* @description Decides which path the database is in
|
||||
|
||||
@@ -10,12 +10,12 @@
|
||||
"express-validator": "^6.14.2",
|
||||
"lowdb": "3.0.0",
|
||||
"multer": "^1.4.4",
|
||||
"nanoid": "^3.3.3",
|
||||
"nanoid": "^4.0.0",
|
||||
"node-osc": "^8.0.6",
|
||||
"node-xlsx": "^0.21.0",
|
||||
"passport": "^0.6.0",
|
||||
"passport-local": "~1.0.0",
|
||||
"socket.io": "^4.5.2"
|
||||
"socket.io": "^4.5.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^8.25.0"
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
event as eventDef,
|
||||
} from '../models/eventsDefinition.js';
|
||||
import { MAX_EVENTS } from '../settings.js';
|
||||
import { eventLoader } from '../classes/event-loader/EventLoader.js';
|
||||
import { EventLoader, eventLoader } from '../classes/event-loader/EventLoader.js';
|
||||
|
||||
const affectedLoaded = (affectedIds) => {
|
||||
const now = eventLoader.selectedEventId;
|
||||
@@ -23,7 +23,7 @@ const affectedLoaded = (affectedIds) => {
|
||||
};
|
||||
|
||||
const isNewNext = () => {
|
||||
const timedEvents = getTimedEvents();
|
||||
const timedEvents = EventLoader.getTimedEvents();
|
||||
const now = eventLoader.selectedEventId;
|
||||
const next = eventLoader.nextEventId;
|
||||
|
||||
@@ -88,23 +88,13 @@ export function updateTimer(affectedIds) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description returns all events of type event
|
||||
* @return {unknown[]}
|
||||
*/
|
||||
export function getTimedEvents() {
|
||||
// return data.events.filter((e) => e.type === 'event');
|
||||
const rundown = DataProvider.getRundown();
|
||||
return rundown.filter((e) => e.type === 'event');
|
||||
}
|
||||
|
||||
/**
|
||||
* @description creates a new event with given data
|
||||
* @param {object} eventData
|
||||
* @return {unknown[]}
|
||||
*/
|
||||
export async function addEvent(eventData) {
|
||||
const numEvents = DataProvider.getNumEvents();
|
||||
const numEvents = DataProvider.getRundownLenght();
|
||||
if (numEvents > MAX_EVENTS) {
|
||||
throw new Error(`ERROR: Reached limit number of ${MAX_EVENTS} events`);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// test cleanURL()
|
||||
|
||||
import {cleanURL} from "../url";
|
||||
import { cleanURL } from '../url';
|
||||
|
||||
describe('url is correctly formatted', () => {
|
||||
it('has no leading spaces', () => {
|
||||
@@ -22,7 +22,7 @@ describe('url is correctly formatted', () => {
|
||||
});
|
||||
|
||||
it('only contains allowed characters', () => {
|
||||
const test = 'http://<>[]{}|\^';
|
||||
const test = 'http://<>[]{}|^';
|
||||
const expected = 'http://';
|
||||
expect(cleanURL(test)).toBe(expected);
|
||||
});
|
||||
@@ -32,5 +32,4 @@ describe('url is correctly formatted', () => {
|
||||
const expected = 'http://ontime.com';
|
||||
expect(cleanURL(test)).toBe(expected);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
+40
-40
@@ -2,6 +2,29 @@ const mts = 1000; // millis to seconds
|
||||
const mtm = 1000 * 60; // millis to minutes
|
||||
const mth = 1000 * 60 * 60; // millis to hours
|
||||
|
||||
export const timeFormat = 'HH:mm';
|
||||
export const timeFormatSeconds = 'HH:mm:ss';
|
||||
|
||||
/**
|
||||
* @description Validates a time string
|
||||
* @param {string} string - time string "23:00:12"
|
||||
* @returns {boolean} string represents time
|
||||
*/
|
||||
export const isTimeString = (string) => {
|
||||
// ^ # Start of string
|
||||
// (?: # Try to match...
|
||||
// (?: # Try to match...
|
||||
// ([01]?\d|2[0-3]): # HH:
|
||||
// )? # (optionally).
|
||||
// ([0-5]?\d): # MM: (required)
|
||||
// )? # (entire group optional, so either HH:MM:, MM: or nothing)
|
||||
// ([0-5]?\d) # SS (required)
|
||||
// $ # End of string
|
||||
|
||||
const regex = /^(?:(?:([01]?\d|2[0-3])[:,.])?([0-5]?\d)[:,.])?([0-5]?\d)$/;
|
||||
return regex.test(string);
|
||||
};
|
||||
|
||||
/**
|
||||
* @description Converts milliseconds to string representing time
|
||||
* @param {number} ms - time in milliseconds
|
||||
@@ -46,46 +69,6 @@ export const dateToMillis = (date) => {
|
||||
return h * mth + m * mtm + s * mts;
|
||||
};
|
||||
|
||||
/**
|
||||
* @description Parses an excel date using the correct parser
|
||||
* @param {string} excelDate
|
||||
* @returns {number} - time in milliseconds
|
||||
|
||||
*/
|
||||
export const parseExcelDate = (excelDate) => {
|
||||
// attempt converting to date object
|
||||
const date = new Date(excelDate);
|
||||
if (date instanceof Date && !isNaN(date)) {
|
||||
return dateToMillis(date);
|
||||
} else if (isTimeString(excelDate)) {
|
||||
return forgivingStringToMillis(excelDate);
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
export const timeFormat = 'HH:mm';
|
||||
export const timeFormatSeconds = 'HH:mm:ss';
|
||||
|
||||
/**
|
||||
* @description Validates a time string
|
||||
* @param {string} string - time string "23:00:12"
|
||||
* @returns {boolean} string represents time
|
||||
*/
|
||||
export const isTimeString = (string) => {
|
||||
// ^ # Start of string
|
||||
// (?: # Try to match...
|
||||
// (?: # Try to match...
|
||||
// ([01]?\d|2[0-3]): # HH:
|
||||
// )? # (optionally).
|
||||
// ([0-5]?\d): # MM: (required)
|
||||
// )? # (entire group optional, so either HH:MM:, MM: or nothing)
|
||||
// ([0-5]?\d) # SS (required)
|
||||
// $ # End of string
|
||||
|
||||
const regex = /^(?:(?:([01]?\d|2[0-3])[:,.])?([0-5]?\d)[:,.])?([0-5]?\d)$/;
|
||||
return regex.test(string);
|
||||
};
|
||||
|
||||
/**
|
||||
* @description safe parse string to int, copied from client code
|
||||
* @param valueAsString
|
||||
@@ -146,3 +129,20 @@ export const forgivingStringToMillis = (value, fillLeft = true) => {
|
||||
}
|
||||
return millis;
|
||||
};
|
||||
|
||||
/**
|
||||
* @description Parses an excel date using the correct parser
|
||||
* @param {string} excelDate
|
||||
* @returns {number} - time in milliseconds
|
||||
|
||||
*/
|
||||
export const parseExcelDate = (excelDate) => {
|
||||
// attempt converting to date object
|
||||
const date = new Date(excelDate);
|
||||
if (date instanceof Date && !isNaN(date)) {
|
||||
return dateToMillis(date);
|
||||
} else if (isTimeString(excelDate)) {
|
||||
return forgivingStringToMillis(excelDate);
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
+15
-15
@@ -409,10 +409,10 @@ engine.io-parser@~5.0.3:
|
||||
resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.0.4.tgz#0b13f704fa9271b3ec4f33112410d8f3f41d0fc0"
|
||||
integrity sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg==
|
||||
|
||||
engine.io@~6.2.0:
|
||||
version "6.2.0"
|
||||
resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-6.2.0.tgz#003bec48f6815926f2b1b17873e576acd54f41d0"
|
||||
integrity sha512-4KzwW3F3bk+KlzSOY57fj/Jx6LyRQ1nbcyIadehl+AnXjKT7gDO0ORdRi/84ixvMKTym6ZKuxvbzN62HDDU1Lg==
|
||||
engine.io@~6.2.1:
|
||||
version "6.2.1"
|
||||
resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-6.2.1.tgz#e3f7826ebc4140db9bbaa9021ad6b1efb175878f"
|
||||
integrity sha512-ECceEFcAaNRybd3lsGQKas3ZlMVjN3cyWwMP25D2i0zWfyiytVbTpRPa34qrr+FHddtpBVOmq4H/DCv1O0lZRA==
|
||||
dependencies:
|
||||
"@types/cookie" "^0.4.1"
|
||||
"@types/cors" "^2.8.12"
|
||||
@@ -991,10 +991,10 @@ multer@^1.4.4:
|
||||
type-is "^1.6.4"
|
||||
xtend "^4.0.0"
|
||||
|
||||
nanoid@^3.3.3:
|
||||
version "3.3.3"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25"
|
||||
integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==
|
||||
nanoid@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-4.0.0.tgz#6e144dee117609232c3f415c34b0e550e64999a5"
|
||||
integrity sha512-IgBP8piMxe/gf73RTQx7hmnhwz0aaEXYakvqZyE302IXW3HyVNhdNGC+O2MwMAVhLEnvXlvKtGbtJf6wvHihCg==
|
||||
|
||||
natural-compare@^1.4.0:
|
||||
version "1.4.0"
|
||||
@@ -1349,7 +1349,7 @@ socket.io-adapter@~2.4.0:
|
||||
resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.4.0.tgz#b50a4a9ecdd00c34d4c8c808224daa1a786152a6"
|
||||
integrity sha512-W4N+o69rkMEGVuk2D/cvca3uYsvGlMwsySWV447y99gUPghxq42BxqLNMndb+a1mm/5/7NeXVQS7RLa2XyXvYg==
|
||||
|
||||
socket.io-parser@~4.2.0:
|
||||
socket.io-parser@~4.2.1:
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.2.1.tgz#01c96efa11ded938dcb21cbe590c26af5eff65e5"
|
||||
integrity sha512-V4GrkLy+HeF1F/en3SpUaM+7XxYXpuMUWLGde1kSSh5nQMN4hLrbPIkD+otwh6q9R6NOQBN4AMaOZ2zVjui82g==
|
||||
@@ -1357,17 +1357,17 @@ socket.io-parser@~4.2.0:
|
||||
"@socket.io/component-emitter" "~3.1.0"
|
||||
debug "~4.3.1"
|
||||
|
||||
socket.io@^4.5.2:
|
||||
version "4.5.2"
|
||||
resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.5.2.tgz#1eb25fd380ab3d63470aa8279f8e48d922d443ac"
|
||||
integrity sha512-6fCnk4ARMPZN448+SQcnn1u8OHUC72puJcNtSgg2xS34Cu7br1gQ09YKkO1PFfDn/wyUE9ZgMAwosJed003+NQ==
|
||||
socket.io@^4.5.4:
|
||||
version "4.5.4"
|
||||
resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.5.4.tgz#a4513f06e87451c17013b8d13fdfaf8da5a86a90"
|
||||
integrity sha512-m3GC94iK9MfIEeIBfbhJs5BqFibMtkRk8ZpKwG2QwxV0m/eEhPIV4ara6XCF1LWNAus7z58RodiZlAH71U3EhQ==
|
||||
dependencies:
|
||||
accepts "~1.3.4"
|
||||
base64id "~2.0.0"
|
||||
debug "~4.3.2"
|
||||
engine.io "~6.2.0"
|
||||
engine.io "~6.2.1"
|
||||
socket.io-adapter "~2.4.0"
|
||||
socket.io-parser "~4.2.0"
|
||||
socket.io-parser "~4.2.1"
|
||||
|
||||
ssf@~0.11.2:
|
||||
version "0.11.2"
|
||||
|
||||
Reference in New Issue
Block a user