diff --git a/client/package.json b/client/package.json index e771174ae..7f6b0a7c8 100644 --- a/client/package.json +++ b/client/package.json @@ -3,9 +3,9 @@ "version": "0.1.0", "private": true, "dependencies": { - "@chakra-ui/react": "^1.4.1", - "@emotion/react": "^11", - "@emotion/styled": "^11", + "@chakra-ui/react": "^1.6.10", + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", "@testing-library/jest-dom": "^5.11.4", "@testing-library/react": "^11.1.0", "@testing-library/user-event": "^12.1.10", diff --git a/client/src/app/api/ontimeApi.js b/client/src/app/api/ontimeApi.js index e23ab1e9d..d5fd4e568 100644 --- a/client/src/app/api/ontimeApi.js +++ b/client/src/app/api/ontimeApi.js @@ -3,6 +3,11 @@ import { ontimeURL } from './apiConstants'; export const ontimePlaceholderInfo = { networkInterfaces: [], + version: '', + serverPort: 4001, + oscInPort: '', + oscOutPort: '', + oscOutIP: '', }; export const getInfo = async () => { @@ -10,6 +15,11 @@ export const getInfo = async () => { return res.data; }; +export const postInfo = async (data) => { + const res = await axios.post(ontimeURL + '/info', data); + return res; +}; + export const downloadEvents = async () => { await axios({ url: ontimeURL + '/db', diff --git a/client/src/features/info/Info.jsx b/client/src/features/info/Info.jsx index 4f0f51e18..fc04fdcbe 100644 --- a/client/src/features/info/Info.jsx +++ b/client/src/features/info/Info.jsx @@ -1,10 +1,9 @@ -import { useEffect } from 'react'; +import { useState, useEffect } from 'react'; import { useSocket } from 'app/context/socketContext'; import style from './Info.module.css'; import InfoTitle from './InfoTitle'; import InfoLogger from './InfoLogger'; import InfoNif from './InfoNif'; -import { useState } from 'react'; export default function Info() { const socket = useSocket(); diff --git a/client/src/features/info/InfoNif.jsx b/client/src/features/info/InfoNif.jsx index 4935733ea..d86f9c138 100644 --- a/client/src/features/info/InfoNif.jsx +++ b/client/src/features/info/InfoNif.jsx @@ -11,8 +11,7 @@ export default function InfoNif() { placeholderData: ontimePlaceholderInfo, }); const [collapsed, setCollapsed] = useState(false); - - const baseURL = `http://__IP__:${4001}`; + const baseURL = 'http://__IP__:4001'; const handleLink = (url) => { if (window.process?.type === 'renderer') { diff --git a/client/src/features/modals/AliasesModal.jsx b/client/src/features/modals/AliasesModal.jsx new file mode 100644 index 000000000..3962b8768 --- /dev/null +++ b/client/src/features/modals/AliasesModal.jsx @@ -0,0 +1,152 @@ +import { IconButton } from '@chakra-ui/button'; +import { FiPlus, FiMinus } from 'react-icons/fi'; +import { ModalBody } from '@chakra-ui/modal'; +import { Input } from '@chakra-ui/react'; +import { fetchEvent } from 'app/api/eventApi'; +import { useState } from 'react'; +import { useFetch } from 'app/hooks/useFetch'; +import { EVENT_TABLE } from 'app/api/apiConstants'; +import style from './Modals.module.css'; + +export default function AliasesModal() { + const { data, status, isError } = useFetch(EVENT_TABLE, fetchEvent); + const [submitting, setSubmitting] = useState(false); + + const submitHandler = async (event) => { + event.preventDefault(); + // NOTHING HERE YET + }; + + // Hardcoded links for now + // it will need dynamic PORT assignment + const speakerLink = 'http://localhost:4001/speaker'; + const smLink = 'http://localhost:4001/sm'; + const publicLink = 'http://localhost:4001/public'; + const pipLink = 'http://localhost:4001/pip'; + + return ( + <> +
+ > + ); +} diff --git a/client/src/features/modals/AppSettingsModal.jsx b/client/src/features/modals/AppSettingsModal.jsx new file mode 100644 index 000000000..bdc8d1c35 --- /dev/null +++ b/client/src/features/modals/AppSettingsModal.jsx @@ -0,0 +1,185 @@ +import { ModalBody } from '@chakra-ui/modal'; +import { FormLabel, FormControl, Input, Button } from '@chakra-ui/react'; +import { getInfo, ontimePlaceholderInfo, postInfo } from 'app/api/ontimeApi'; +import { useEffect, useState } from 'react'; +import { useFetch } from 'app/hooks/useFetch'; +import { APP_TABLE } from 'app/api/apiConstants'; +import { showErrorToast } from 'common/helpers/toastManager'; +import style from './Modals.module.css'; + +export default function AppSettingsModal() { + const { data, status } = useFetch(APP_TABLE, getInfo); + const [formData, setFormData] = useState(ontimePlaceholderInfo); + const [changed, setChanged] = useState(false); + const [submitting, setSubmitting] = useState(false); + + useEffect(() => { + if (data == null) return; + + setFormData({ + oscInPort: data.oscInPort, + oscOutPort: data.oscOutPort, + oscOutIP: data.oscOutIP, + }); + }, [data]); + + const submitHandler = async (event) => { + event.preventDefault(); + + const f = formData; + let e = { status: false, message: '' }; + + // Validate fields + if (f.oscInPort < 1024 || f.oscInPort > 65535) { + // Port in incorrect range + e.status = true; + e.message += 'OSC IN Port in incorrect range (1024 - 65535)'; + } else if (f.oscOutPort < 1024 || f.oscOutPort > 65535) { + // Port in incorrect range + e.status = true; + e.message += 'OSC OUT Port in incorrect range (1024 - 65535)'; + } else if (f.oscInPort === f.oscOutPort) { + // Cant use the same port + e.status = true; + e.message += 'OSC IN and OUT Ports cant be the same'; + } + + // set fields with error + if (e.status) { + showErrorToast('Invalid Input', e.message); + return; + } + + // Post here + postInfo(formData); + + setChanged(false); + setSubmitting(false); + }; + + return ( + <> + + > + ); +} diff --git a/client/src/features/modals/SettingsModal.jsx b/client/src/features/modals/EventSettingsModal.jsx similarity index 57% rename from client/src/features/modals/SettingsModal.jsx rename to client/src/features/modals/EventSettingsModal.jsx index 7188ab4c3..58238f042 100644 --- a/client/src/features/modals/SettingsModal.jsx +++ b/client/src/features/modals/EventSettingsModal.jsx @@ -10,15 +10,18 @@ import { fetchEvent, postEvent } from 'app/api/eventApi'; import { useEffect, useState } from 'react'; import { useFetch } from 'app/hooks/useFetch'; import { EVENT_TABLE } from 'app/api/apiConstants'; +import style from './Modals.module.css'; export default function SettingsModal() { - const { data, status, isError } = useFetch(EVENT_TABLE, fetchEvent); + const { data, status } = useFetch(EVENT_TABLE, fetchEvent); const [formData, setFormData] = useState({ title: '', url: '', publicInfo: '', backstageInfo: '', + endMessage: '', }); + const [changed, setChanged] = useState(false); const [submitting, setSubmitting] = useState(false); useEffect(() => { @@ -29,6 +32,7 @@ export default function SettingsModal() { url: data.url, publicInfo: data.publicInfo, backstageInfo: data.backstageInfo, + endMessage: data.endMessage, }); }, [data]); @@ -36,41 +40,47 @@ export default function SettingsModal() { event.preventDefault(); setSubmitting(true); - await postEvent(formData).then(setSubmitting(false)); + await postEvent(formData); + + setChanged(false); + setSubmitting(false); }; return ( <>