feat: components implement their notifications now

- removing nestedObjectUtils and useNotification hook
- passing addNotification method to all components
- components can use the addNotification method to create their
  notifications
This commit is contained in:
Mose Müller committed 2023-08-10 15:07:49 +02:00
1 parent 8205e4d463
commit f7579c3a89
21 files changed
+235 -167

No files matched your search

+63 -46
View File
@@ -1,4 +1,4 @@
import { useEffect, useReducer, useRef, useState } from 'react';
import { useCallback, useEffect, useReducer, useRef, useState } from 'react';
import { Navbar, Form, Offcanvas, Container } from 'react-bootstrap';
import { hostname, port, socket } from './socket';
import {
@@ -6,9 +6,7 @@ import {
DataServiceJSON
} from './components/DataServiceComponent';
import './App.css';
import { getDataServiceJSONValueByPathAndKey } from './utils/nestedObjectUtils';
import { Notifications } from './components/NotificationsComponent';
import { useNotification } from './hooks/useNotification';
type ValueType = boolean | string | number | object;
@@ -114,51 +112,11 @@ const reducer = (state: State, action: Action): State => {
const App = () => {
const [state, dispatch] = useReducer(reducer, null);
const stateRef = useRef(state); // Declare a reference to hold the current state
const [isInstantUpdate, setIsInstantUpdate] = useState(true);
const [showSettings, setShowSettings] = useState(false);
const [showNotification, setShowNotification] = useState(false);
const { notifications, notify, removeNotificationById } = useNotification();
const {
notifications: exceptions,
notify: notifyException,
removeNotificationById: removeExceptionById
} = useNotification();
const handleCloseSettings = () => setShowSettings(false);
const handleShowSettings = () => setShowSettings(true);
function onNotify(value: UpdateMessage) {
// Extracting data from the notification
const { parent_path: parentPath, name, value: newValue } = value.data;
// Dispatching the update to the reducer
dispatch({
type: 'UPDATE_ATTRIBUTE',
parentPath,
name,
value: newValue
});
// Formatting the value if it is of type 'Quantity'
let notificationMsg: object | string = newValue;
const path = parentPath.concat('.', name);
if (
getDataServiceJSONValueByPathAndKey(stateRef.current, path, 'type') === 'Quantity'
) {
notificationMsg = `${newValue['magnitude']} ${newValue['unit']}`;
}
// Creating a new notification
const newNotification = `${parentPath}.${name} changed to ${notificationMsg}.`;
// Adding the new notification to the list
notify(newNotification);
}
function onException(value: ExceptionMessage) {
const newNotification = `${value.data.type}: ${value.data.exception}.`;
notifyException(newNotification);
}
const [showNotification, setShowNotification] = useState(true);
const [notifications, setNotifications] = useState([]);
const [exceptions, setExceptions] = useState([]);
// Keep the state reference up to date
useEffect(() => {
@@ -180,6 +138,64 @@ const App = () => {
};
}, []);
// Adding useCallback to prevent notify to change causing a re-render of all
// components
const addNotification = useCallback((text: string) => {
// Getting the current time in the required format
const timeString = new Date().toISOString().substring(11, 19);
// Adding an id to the notification to provide a way of removing it
const id = Math.random();
// Custom logic for notifications
setNotifications((prevNotifications) => [
{ id, text, time: timeString },
...prevNotifications
]);
}, []);
const notifyException = (text: string) => {
// Getting the current time in the required format
const timeString = new Date().toISOString().substring(11, 19);
// Adding an id to the notification to provide a way of removing it
const id = Math.random();
// Custom logic for notifications
setExceptions((prevNotifications) => [
{ id, text, time: timeString },
...prevNotifications
]);
};
const removeNotificationById = (id: number) => {
setNotifications((prevNotifications) =>
prevNotifications.filter((n) => n.id !== id)
);
};
const removeExceptionById = (id: number) => {
setExceptions((prevNotifications) => prevNotifications.filter((n) => n.id !== id));
};
const handleCloseSettings = () => setShowSettings(false);
const handleShowSettings = () => setShowSettings(true);
function onNotify(value: UpdateMessage) {
// Extracting data from the notification
const { parent_path: parentPath, name, value: newValue } = value.data;
// Dispatching the update to the reducer
dispatch({
type: 'UPDATE_ATTRIBUTE',
parentPath,
name,
value: newValue
});
}
function onException(value: ExceptionMessage) {
const newException = `${value.data.type}: ${value.data.exception}.`;
notifyException(newException);
}
// While the data is loading
if (!state) {
return <p>Loading...</p>;
@@ -230,6 +246,7 @@ const App = () => {
<DataServiceComponent
props={state as DataServiceJSON}
isInstantUpdate={isInstantUpdate}
addNotification={addNotification}
/>
</div>
</>
@@ -10,29 +10,13 @@ interface AsyncMethodProps {
value: Record<string, string>;
docString?: string;
hideOutput?: boolean;
addNotification: (string) => void;
}
export const AsyncMethodComponent = React.memo((props: AsyncMethodProps) => {
const { name, parentPath, docString, value: runningTask, addNotification } = props;
const renderCount = useRef(0);
const formRef = useRef(null);
const { name, parentPath, docString, value: runningTask } = props;
const execute = async (event: React.FormEvent) => {
event.preventDefault();
let method_name: string;
const args = {};
if (runningTask !== undefined && runningTask !== null) {
method_name = `stop_${name}`;
} else {
Object.keys(props.parameters).forEach(
(name) => (args[name] = event.target[name].value)
);
method_name = `start_${name}`;
}
emit_update(method_name, parentPath, { args: args });
};
useEffect(() => {
renderCount.current++;
@@ -52,6 +36,38 @@ export const AsyncMethodComponent = React.memo((props: AsyncMethodProps) => {
}
}, [runningTask]);
useEffect(() => {
let message: string;
if (runningTask === null) {
message = `${parentPath}.${name} task was stopped.`;
} else {
const runningTaskEntries = Object.entries(runningTask)
.map(([key, value]) => `${key}: "${value}"`)
.join(', ');
message = `${parentPath}.${name} was started with parameters { ${runningTaskEntries} }.`;
}
addNotification(message);
}, [props.value]);
const execute = async (event: React.FormEvent) => {
event.preventDefault();
let method_name: string;
const args = {};
if (runningTask !== undefined && runningTask !== null) {
method_name = `stop_${name}`;
} else {
Object.keys(props.parameters).forEach(
(name) => (args[name] = event.target[name].value)
);
method_name = `start_${name}`;
}
emit_update(method_name, parentPath, { args: args });
};
const args = Object.entries(props.parameters).map(([name, type], index) => {
const form_name = `${name} (${type})`;
const value = runningTask && runningTask[name];
+8 -2
View File
@@ -10,17 +10,23 @@ interface ButtonComponentProps {
readOnly: boolean;
docString: string;
mapping?: [string, string]; // Enforce a tuple of two strings
addNotification: (string) => void;
}
export const ButtonComponent = React.memo((props: ButtonComponentProps) => {
const { name, parentPath, value, readOnly, docString, mapping, addNotification } =
props;
const buttonName = mapping ? (value ? mapping[0] : mapping[1]) : name;
const renderCount = useRef(0);
useEffect(() => {
renderCount.current++;
});
const { name, parentPath, value, readOnly, docString, mapping } = props;
const buttonName = mapping ? (value ? mapping[0] : mapping[1]) : name;
useEffect(() => {
addNotification(`${parentPath}.${name} changed to ${value}.`);
}, [props.value]);
const setChecked = (checked: boolean) => {
emit_update(name, parentPath, checked);
@@ -8,12 +8,18 @@ type DataServiceProps = {
props: DataServiceJSON;
parentPath?: string;
isInstantUpdate: boolean;
addNotification: (string) => void;
};
export type DataServiceJSON = Record<string, Attribute>;
export const DataServiceComponent = React.memo(
({ props, parentPath = 'DataService', isInstantUpdate }: DataServiceProps) => {
({
props,
parentPath = 'DataService',
isInstantUpdate,
addNotification
}: DataServiceProps) => {
const [open, setOpen] = useState(true);
return (
@@ -35,6 +41,7 @@ export const DataServiceComponent = React.memo(
name={key}
parentPath={parentPath}
isInstantUpdate={isInstantUpdate}
addNotification={addNotification}
/>
);
})}
+13 -1
View File
@@ -9,16 +9,28 @@ interface EnumComponentProps {
value: string;
docString?: string;
enumDict: Record<string, string>;
addNotification: (string) => void;
}
export const EnumComponent = React.memo((props: EnumComponentProps) => {
const {
name,
parentPath: parentPath,
value,
docString,
enumDict,
addNotification
} = props;
const renderCount = useRef(0);
useEffect(() => {
renderCount.current++;
});
const { name, parentPath: parentPath, value, docString, enumDict } = props;
useEffect(() => {
addNotification(`${parentPath}.${name} changed to ${value}.`);
}, [props.value]);
const handleValueChange = (newValue: string) => {
emit_update(name, parentPath, newValue);
+19 -1
View File
@@ -38,10 +38,17 @@ type GenericComponentProps = {
name: string;
parentPath: string;
isInstantUpdate: boolean;
addNotification: (string) => void;
};
export const GenericComponent = React.memo(
({ attribute, name, parentPath, isInstantUpdate }: GenericComponentProps) => {
({
attribute,
name,
parentPath,
isInstantUpdate,
addNotification
}: GenericComponentProps) => {
if (attribute.type === 'bool') {
return (
<ButtonComponent
@@ -50,6 +57,7 @@ export const GenericComponent = React.memo(
docString={attribute.doc}
readOnly={attribute.readonly}
value={Boolean(attribute.value)}
addNotification={addNotification}
/>
);
} else if (attribute.type === 'float' || attribute.type === 'int') {
@@ -62,6 +70,7 @@ export const GenericComponent = React.memo(
readOnly={attribute.readonly}
value={Number(attribute.value)}
isInstantUpdate={isInstantUpdate}
addNotification={addNotification}
/>
);
} else if (attribute.type === 'Quantity') {
@@ -75,6 +84,7 @@ export const GenericComponent = React.memo(
value={Number(attribute.value['magnitude'])}
unit={attribute.value['unit']}
isInstantUpdate={isInstantUpdate}
addNotification={addNotification}
/>
);
} else if (attribute.type === 'NumberSlider') {
@@ -89,6 +99,7 @@ export const GenericComponent = React.memo(
max={attribute.value['max']['value']}
stepSize={attribute.value['step_size']['value']}
isInstantUpdate={isInstantUpdate}
addNotification={addNotification}
/>
);
} else if (attribute.type === 'Enum') {
@@ -99,6 +110,7 @@ export const GenericComponent = React.memo(
docString={attribute.doc}
value={String(attribute.value)}
enumDict={attribute.enum}
addNotification={addNotification}
/>
);
} else if (attribute.type === 'method') {
@@ -109,6 +121,7 @@ export const GenericComponent = React.memo(
parentPath={parentPath}
docString={attribute.doc}
parameters={attribute.parameters}
addNotification={addNotification}
/>
);
} else {
@@ -119,6 +132,7 @@ export const GenericComponent = React.memo(
docString={attribute.doc}
parameters={attribute.parameters}
value={attribute.value as Record<string, string>}
addNotification={addNotification}
/>
);
}
@@ -131,6 +145,7 @@ export const GenericComponent = React.memo(
docString={attribute.doc}
parentPath={parentPath}
isInstantUpdate={isInstantUpdate}
addNotification={addNotification}
/>
);
} else if (attribute.type === 'DataService') {
@@ -139,6 +154,7 @@ export const GenericComponent = React.memo(
props={attribute.value as DataServiceJSON}
parentPath={parentPath.concat('.', name)}
isInstantUpdate={isInstantUpdate}
addNotification={addNotification}
/>
);
} else if (attribute.type === 'list') {
@@ -149,6 +165,7 @@ export const GenericComponent = React.memo(
docString={attribute.doc}
parentPath={parentPath}
isInstantUpdate={isInstantUpdate}
addNotification={addNotification}
/>
);
} else if (attribute.type === 'Image') {
@@ -161,6 +178,7 @@ export const GenericComponent = React.memo(
docString={attribute.doc}
// Add any other specific props for the ImageComponent here
format={attribute.value['format']['value'] as string}
addNotification={addNotification}
/>
);
} else {
+7 -2
View File
@@ -1,5 +1,4 @@
import React, { useEffect, useRef } from 'react';
import { emit_update } from '../socket';
import { Card, Image } from 'react-bootstrap';
import { DocStringComponent } from './DocStringComponent';
@@ -10,16 +9,22 @@ interface ImageComponentProps {
readOnly: boolean;
docString: string;
format: string;
addNotification: (string) => void;
}
export const ImageComponent = React.memo((props: ImageComponentProps) => {
const { name, parentPath, value, docString, format, addNotification } = props;
const renderCount = useRef(0);
const { name, parentPath, value, docString, format } = props;
useEffect(() => {
renderCount.current++;
});
useEffect(() => {
addNotification(`${parentPath}.${name} changed.`);
}, [props.value]);
return (
<div className={'imageComponent'} id={parentPath.concat('.' + name)}>
<Card>
+6 -3
View File
@@ -8,16 +8,18 @@ interface ListComponentProps {
value: Attribute[];
docString: string;
isInstantUpdate: boolean;
addNotification: (string) => void;
}
export const ListComponent = React.memo((props: ListComponentProps) => {
const { name, parentPath, value, docString, isInstantUpdate, addNotification } =
props;
const renderCount = useRef(0);
useEffect(() => {
renderCount.current++;
});
const { name, parentPath, value, docString, isInstantUpdate } = props;
}, [props]);
return (
<div className={'listComponent'} id={parentPath.concat(name)}>
@@ -33,6 +35,7 @@ export const ListComponent = React.memo((props: ListComponentProps) => {
name={`${name}[${index}]`}
parentPath={parentPath}
isInstantUpdate={isInstantUpdate}
addNotification={addNotification}
/>
);
})}
+25 -9
View File
@@ -9,16 +9,37 @@ interface MethodProps {
parameters: Record<string, string>;
docString?: string;
hideOutput?: boolean;
addNotification: (string) => void;
}
export const MethodComponent = React.memo((props: MethodProps) => {
const { name, parentPath, docString, addNotification } = props;
const renderCount = useRef(0);
const [hideOutput, setHideOutput] = useState(false);
// Add a new state variable to hold the list of function calls
const [functionCalls, setFunctionCalls] = useState([]);
const { name, parentPath, docString } = props;
useEffect(() => {
renderCount.current++;
if (props.hideOutput !== undefined) {
setHideOutput(props.hideOutput);
}
});
const triggerNotification = (args: Record<string, string>) => {
const argsString = Object.entries(args)
.map(([key, value]) => `${key}: "${value}"`)
.join(', ');
let message = `Method ${parentPath}.${name} was triggered`;
if (argsString === '') {
message += '.';
} else {
message += ` with arguments {${argsString}}.`;
}
addNotification(message);
};
const execute = async (event: React.FormEvent) => {
event.preventDefault();
@@ -33,14 +54,9 @@ export const MethodComponent = React.memo((props: MethodProps) => {
setFunctionCalls((prevCalls) => [...prevCalls, { name, args, result: ack }]);
}
});
};
useEffect(() => {
renderCount.current++;
if (props.hideOutput !== undefined) {
setHideOutput(props.hideOutput);
}
});
triggerNotification(args);
};
const args = Object.entries(props.parameters).map(([name, type], index) => {
const form_name = `${name} (${type})`;
+19 -1
View File
@@ -22,6 +22,7 @@ interface NumberComponentProps {
value: number,
callback?: (ack: unknown) => void
) => void;
addNotification: (string) => void;
}
// TODO: highlight the digit that is being changed by setting both selectionStart and
@@ -108,7 +109,15 @@ const handleDeleteKey = (
};
export const NumberComponent = React.memo((props: NumberComponentProps) => {
const { name, parentPath, readOnly, docString, isInstantUpdate, unit } = props;
const {
name,
parentPath,
readOnly,
docString,
isInstantUpdate,
unit,
addNotification
} = props;
// Whether to show the name infront of the component (false if used with a slider)
const showName = props.showName !== undefined ? props.showName : true;
@@ -143,6 +152,15 @@ export const NumberComponent = React.memo((props: NumberComponentProps) => {
if (props.value !== numericInputString) {
setInputString(props.value.toString());
}
// emitting notification
let notificationMsg = `${parentPath}.${name} changed to ${props.value}`;
if (unit === undefined) {
notificationMsg += '.';
} else {
notificationMsg += ` ${unit}.`;
}
addNotification(notificationMsg);
}, [props.value]);
const handleNumericKey = (key: string, value: string, selectionStart: number) => {
+20 -1
View File
@@ -15,6 +15,7 @@ interface SliderComponentProps {
docString: string;
stepSize: number;
isInstantUpdate: boolean;
addNotification: (string) => void;
}
export const SliderComponent = React.memo((props: SliderComponentProps) => {
@@ -34,9 +35,26 @@ export const SliderComponent = React.memo((props: SliderComponentProps) => {
stepSize,
readOnly,
docString,
isInstantUpdate
isInstantUpdate,
addNotification
} = props;
useEffect(() => {
addNotification(`${parentPath}.${name} changed to ${value}.`);
}, [props.value]);
useEffect(() => {
addNotification(`${parentPath}.${name}.min changed to ${min}.`);
}, [props.min]);
useEffect(() => {
addNotification(`${parentPath}.${name}.max changed to ${max}.`);
}, [props.max]);
useEffect(() => {
addNotification(`${parentPath}.${name}.stepSize changed to ${stepSize}.`);
}, [props.stepSize]);
const emitSliderUpdate = (
name: string,
parentPath: string,
@@ -122,6 +140,7 @@ export const SliderComponent = React.memo((props: SliderComponentProps) => {
value={value}
showName={false}
customEmitUpdate={emitSliderUpdate}
addNotification={() => null}
/>
</Col>
<Col xs="auto">
+5 -1
View File
@@ -13,13 +13,16 @@ interface StringComponentProps {
readOnly: boolean;
docString: string;
isInstantUpdate: boolean;
addNotification: (string) => void;
}
export const StringComponent = React.memo((props: StringComponentProps) => {
const { name, parentPath, readOnly, docString, isInstantUpdate, addNotification } =
props;
const renderCount = useRef(0);
const [inputString, setInputString] = useState(props.value);
const { name, parentPath, readOnly, docString, isInstantUpdate } = props;
useEffect(() => {
renderCount.current++;
}, [isInstantUpdate, inputString, renderCount]);
@@ -29,6 +32,7 @@ export const StringComponent = React.memo((props: StringComponentProps) => {
if (props.value !== inputString) {
setInputString(props.value);
}
addNotification(`${parentPath}.${name} changed to ${props.value}.`);
}, [props.value]);
const handleChange = (event) => {
-27
View File
@@ -1,27 +0,0 @@
import { useState } from 'react';
import { Notification } from '../components/NotificationsComponent';
export const useNotification = () => {
const [notifications, setNotifications] = useState<Notification[]>([]);
const notify = (text: string) => {
// Getting the current time in the required format
const timeString = new Date().toISOString().substring(11, 19);
// Adding an id to the notification to provide a way of removing it
const id = Math.random();
// Custom logic for notifications
setNotifications((prevNotifications) => [
{ id, text, time: timeString },
...prevNotifications
]);
};
const removeNotificationById = (id: number) => {
setNotifications((prevNotifications) =>
prevNotifications.filter((n) => n.id !== id)
);
};
return { notifications, notify, removeNotificationById };
};
-46
View File
@@ -1,46 +0,0 @@
type Data = {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[key: string]: any;
};
const STANDARD_TYPES = [
'int',
'float',
'bool',
'str',
'Enum',
'method',
'NoneType',
'Quantity'
];
export function getDataServiceJSONValueByPathAndKey(
data: Data,
path: string,
key = 'value'
): string {
// Split the path into parts
const parts = path.split(/\.|(?=\[\d+\])/);
parts.shift(); // Remove the first element
// Traverse the dictionary according to the path parts
for (const part of parts) {
if (part.startsWith('[')) {
// List index
const idx = parseInt(part.substring(1, part.length - 1)); // Strip the brackets and convert to integer
data = data[idx];
} else {
// Dictionary key
data = data[part];
}
// When the attribute is a class instance, the attributes are nested in the
// "value" key
if (!STANDARD_TYPES.includes(data['type'])) {
data = data['value'];
}
}
// Return the value at the terminal point of the path
return data[key];
}
+3 -3
View File
@@ -1,13 +1,13 @@
{
"files": {
"main.css": "/static/css/main.398bc7f8.css",
"main.js": "/static/js/main.799e0879.js",
"main.js": "/static/js/main.39f6b50e.js",
"index.html": "/index.html",
"main.398bc7f8.css.map": "/static/css/main.398bc7f8.css.map",
"main.799e0879.js.map": "/static/js/main.799e0879.js.map"
"main.39f6b50e.js.map": "/static/js/main.39f6b50e.js.map"
},
"entrypoints": [
"static/css/main.398bc7f8.css",
"static/js/main.799e0879.js"
"static/js/main.39f6b50e.js"
]
}
+1 -1
View File
@@ -1 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site displaying a pydase UI."/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><title>pydase App</title><script defer="defer" src="/static/js/main.799e0879.js"></script><link href="/static/css/main.398bc7f8.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site displaying a pydase UI."/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><title>pydase App</title><script defer="defer" src="/static/js/main.39f6b50e.js"></script><link href="/static/css/main.398bc7f8.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
@@ -0,0 +1,3 @@
/*! For license information please see main.39f6b50e.js.LICENSE.txt */
!function(){var e={694:function(e,t){var n;!function(){"use strict";var r={}.hasOwnProperty;function a(){for(var e=[],t=0;t<arguments.length;t++){var n=arguments[t];if(n){var o=typeof n;if("string"===o||"number"===o)e.push(n);else if(Array.isArray(n)){if(n.length){var i=a.apply(null,n);i&&e.push(i)}}else if("object"===o){if(n.toString!==Object.prototype.toString&&!n.toString.toString().includes("[native code]")){e.push(n.toString());continue}for(var l in n)r.call(n,l)&&n[l]&&e.push(l)}}}return e.join(" ")}e.exports?(a.default=a,e.exports=a):void 0===(n=function(){return a}.apply(t,[]))||(e.exports=n)}()},176:function(e){"use strict";e.exports=function(e,t,n,r,a,o,i,l){if(!e){var s;if(void 0===t)s=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var u=[n,r,a,o,i,l],c=0;(s=new Error(t.replace(/%s/g,(function(){return u[c++]})))).name="Invariant Violation"}throw s.framesToPop=1,s}}},888:function(e,t,n){"use strict";var r=n(47);function a(){}function o(){}o.resetWarningCache=a,e.exports=function(){function e(e,t,n,a,o,i){if(i!==r){var l=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw l.name="Invariant Violation",l}}function t(){return e}e.isRequired=e;var n={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:o,resetWarningCache:a};return n.PropTypes=n,n}},7:function(e,t,n){e.exports=n(888)()},47:function(e){"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},463:function(e,t,n){"use strict";var r=n(791),a=n(296);function o(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n<arguments.length;n++)t+="&args[]="+encodeURIComponent(arguments[n]);return"Minified React error #"+e+"; visit "+t+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}var i=new Set,l={};function s(e,t){u(e,t),u(e+"Capture",t)}function u(e,t){for(l[e]=t,e=0;e<t.length;e++)i.add(t[e])}var c=!("undefined"===typeof window||"undefined"===typeof window.document||"undefined"===typeof window.document.createElement),f=Object.prototype.hasOwnProperty,d=/^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/,p={},h={};function v(e,t,n,r,a,o,i){this.acceptsBooleans=2===t||3===t||4===t,this.attributeName=r,this.attributeNamespace=a,this.mustUseProperty=n,this.propertyName=e,this.type=t,this.sanitizeURL=o,this.removeEmptyString=i}var m={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach((function(e){m[e]=new v(e,0,!1,e,null,!1,!1)})),[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach((function(e){var t=e[0];m[t]=new v(t,1,!1,e[1],null,!1,!1)})),["contentEditable","draggable","spellCheck","value"].forEach((function(e){m[e]=new v(e,2,!1,e.toLowerCase(),null,!1,!1)})),["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach((function(e){m[e]=new v(e,2,!1,e,null,!1,!1)})),"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture disableRemotePlayback formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope".split(" ").forEach((function(e){m[e]=new v(e,3,!1,e.toLowerCase(),null,!1,!1)})),["checked","multiple","muted","selected"].forEach((function(e){m[e]=new v(e,3,!0,e,null,!1,!1)})),["capture","download"].forEach((function(e){m[e]=new v(e,4,!1,e,null,!1,!1)})),["cols","rows","size","span"].forEach((function(e){m[e]=new v(e,6,!1,e,null,!1,!1)})),["rowSpan","start"].forEach((function(e){m[e]=new v(e,5,!1,e.toLowerCase(),null,!1,!1)}));var y=/[\-:]([a-z])/g;function g(e){return e[1].toUpperCase()}function b(e,t,n,r){var a=m.hasOwnProperty(t)?m[t]:null;(null!==a?0!==a.type:r||!(2<t.length)||"o"!==t[0]&&"O"!==t[0]||"n"!==t[1]&&"N"!==t[1])&&(function(e,t,n,r){if(null===t||"undefined"===typeof t||function(e,t,n,r){if(null!==n&&0===n.type)return!1;switch(typeof t){case"function":case"symbol":return!0;case"boolean":return!r&&(null!==n?!n.acceptsBooleans:"data-"!==(e=e.toLowerCase().slice(0,5))&&"aria-"!==e);default:return!1}}(e,t,n,r))return!0;if(r)return!1;if(null!==n)switch(n.type){case 3:return!t;case 4:return!1===t;case 5:return isNaN(t);case 6:return isNaN(t)||1>t}return!1}(t,n,a,r)&&(n=null),r||null===a?function(eLine truncated
//# sourceMappingURL=main.39f6b50e.js.map
@@ -0,0 +1 @@
{"version":3,"file":"static/js/main.39f6b50e.js","mappings":"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 truncated
@@ -1,3 +0,0 @@
/*! For license information please see main.799e0879.js.LICENSE.txt */
!function(){var e={694:function(e,t){var n;!function(){"use strict";var r={}.hasOwnProperty;function a(){for(var e=[],t=0;t<arguments.length;t++){var n=arguments[t];if(n){var o=typeof n;if("string"===o||"number"===o)e.push(n);else if(Array.isArray(n)){if(n.length){var i=a.apply(null,n);i&&e.push(i)}}else if("object"===o){if(n.toString!==Object.prototype.toString&&!n.toString.toString().includes("[native code]")){e.push(n.toString());continue}for(var l in n)r.call(n,l)&&n[l]&&e.push(l)}}}return e.join(" ")}e.exports?(a.default=a,e.exports=a):void 0===(n=function(){return a}.apply(t,[]))||(e.exports=n)}()},176:function(e){"use strict";e.exports=function(e,t,n,r,a,o,i,l){if(!e){var s;if(void 0===t)s=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var u=[n,r,a,o,i,l],c=0;(s=new Error(t.replace(/%s/g,(function(){return u[c++]})))).name="Invariant Violation"}throw s.framesToPop=1,s}}},888:function(e,t,n){"use strict";var r=n(47);function a(){}function o(){}o.resetWarningCache=a,e.exports=function(){function e(e,t,n,a,o,i){if(i!==r){var l=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw l.name="Invariant Violation",l}}function t(){return e}e.isRequired=e;var n={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:o,resetWarningCache:a};return n.PropTypes=n,n}},7:function(e,t,n){e.exports=n(888)()},47:function(e){"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},463:function(e,t,n){"use strict";var r=n(791),a=n(296);function o(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n<arguments.length;n++)t+="&args[]="+encodeURIComponent(arguments[n]);return"Minified React error #"+e+"; visit "+t+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}var i=new Set,l={};function s(e,t){u(e,t),u(e+"Capture",t)}function u(e,t){for(l[e]=t,e=0;e<t.length;e++)i.add(t[e])}var c=!("undefined"===typeof window||"undefined"===typeof window.document||"undefined"===typeof window.document.createElement),f=Object.prototype.hasOwnProperty,d=/^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/,p={},h={};function v(e,t,n,r,a,o,i){this.acceptsBooleans=2===t||3===t||4===t,this.attributeName=r,this.attributeNamespace=a,this.mustUseProperty=n,this.propertyName=e,this.type=t,this.sanitizeURL=o,this.removeEmptyString=i}var m={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach((function(e){m[e]=new v(e,0,!1,e,null,!1,!1)})),[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach((function(e){var t=e[0];m[t]=new v(t,1,!1,e[1],null,!1,!1)})),["contentEditable","draggable","spellCheck","value"].forEach((function(e){m[e]=new v(e,2,!1,e.toLowerCase(),null,!1,!1)})),["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach((function(e){m[e]=new v(e,2,!1,e,null,!1,!1)})),"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture disableRemotePlayback formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope".split(" ").forEach((function(e){m[e]=new v(e,3,!1,e.toLowerCase(),null,!1,!1)})),["checked","multiple","muted","selected"].forEach((function(e){m[e]=new v(e,3,!0,e,null,!1,!1)})),["capture","download"].forEach((function(e){m[e]=new v(e,4,!1,e,null,!1,!1)})),["cols","rows","size","span"].forEach((function(e){m[e]=new v(e,6,!1,e,null,!1,!1)})),["rowSpan","start"].forEach((function(e){m[e]=new v(e,5,!1,e.toLowerCase(),null,!1,!1)}));var y=/[\-:]([a-z])/g;function g(e){return e[1].toUpperCase()}function b(e,t,n,r){var a=m.hasOwnProperty(t)?m[t]:null;(null!==a?0!==a.type:r||!(2<t.length)||"o"!==t[0]&&"O"!==t[0]||"n"!==t[1]&&"N"!==t[1])&&(function(e,t,n,r){if(null===t||"undefined"===typeof t||function(e,t,n,r){if(null!==n&&0===n.type)return!1;switch(typeof t){case"function":case"symbol":return!0;case"boolean":return!r&&(null!==n?!n.acceptsBooleans:"data-"!==(e=e.toLowerCase().slice(0,5))&&"aria-"!==e);default:return!1}}(e,t,n,r))return!0;if(r)return!1;if(null!==n)switch(n.type){case 3:return!t;case 4:return!1===t;case 5:return isNaN(t);case 6:return isNaN(t)||1>t}return!1}(t,n,a,r)&&(n=null),r||null===a?function(eLine truncated
//# sourceMappingURL=main.799e0879.js.map
@@ -1 +0,0 @@
{"version":3,"file":"static/js/main.799e0879.js","mappings":"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 truncated