From 1dc42eacafb903fdd6c4e056e4dce7d196a788de Mon Sep 17 00:00:00 2001 From: Mattallmighty Date: Sat, 22 Oct 2022 14:53:25 +1100 Subject: [PATCH 1/8] Starting on it --- src/components/Bars/BarBottom.tsx | 2 + src/components/Dialogs/AddSceneDialog.tsx | 54 ++++++- src/components/Dialogs/EditSceneDialog.tsx | 166 +++++++++++++++++++++ src/pages/Scenes/Scenes.tsx | 23 ++- src/store/api/storeScenes.tsx | 16 +- src/store/ui/storeDialogs.tsx | 12 +- 6 files changed, 259 insertions(+), 14 deletions(-) create mode 100644 src/components/Dialogs/EditSceneDialog.tsx diff --git a/src/components/Bars/BarBottom.tsx b/src/components/Bars/BarBottom.tsx index 2366c52b..1c880aaa 100644 --- a/src/components/Bars/BarBottom.tsx +++ b/src/components/Bars/BarBottom.tsx @@ -26,6 +26,7 @@ import AddButton from '../AddButton'; import useStyles from './BarBottom.styles'; import YoutubeWidget from '../Integrations/Youtube/YoutubeWidget'; import SpotifyFabPro from '../Integrations/Spotify/SpotifyFabPro'; +import EditSceneDialog from '../Dialogs/EditSceneDialog'; export default function BarBottom() { const classes = useStyles(); @@ -214,6 +215,7 @@ export default function BarBottom() { + { const [name, setName] = useState(''); const [image, setImage] = useState(''); + const [url, setUrl] = useState(''); + const [payload, setPayload] = useState(''); const [overwrite, setOverwrite] = useState(false); + const [invalid, setInvalid] = useState(false); const addScene = useStore((state) => state.addScene); const getScenes = useStore((state) => state.getScenes); @@ -23,17 +26,29 @@ const AddSceneDialog = () => { const setDialogOpenAddScene = useStore( (state) => state.setDialogOpenAddScene ); - + useEffect(() => { + setInvalid(false); + }, []); + function isValidURL(string: string) { + const res = string.match( + /(http(s)?:\/\/.)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/g + ); + return res !== null; + } const handleClose = () => { setDialogOpenAddScene(false); }; const handleAddScene = () => { - addScene(name, image).then(() => { - getScenes(); - }); - setName(''); - setImage(''); - setDialogOpenAddScene(false); + if (!invalid) { + addScene(name, image, url, payload).then(() => { + getScenes(); + }); + setName(''); + setImage(''); + setUrl(''); + setPayload(''); + setDialogOpenAddScene(false); + } }; return ( @@ -107,6 +122,29 @@ const AddSceneDialog = () => { onChange={(e) => setImage(e.target.value)} fullWidth /> + setUrl(e.target.value)} + fullWidth + error={invalid} + helperText={invalid && 'Enter valid URL!'} + onBlur={(e) => { + setInvalid(!isValidURL(e.target.value)); + }} + /> + setPayload(e.target.value)} + fullWidth + /> diff --git a/src/components/Dialogs/EditSceneDialog.tsx b/src/components/Dialogs/EditSceneDialog.tsx new file mode 100644 index 00000000..ecd18150 --- /dev/null +++ b/src/components/Dialogs/EditSceneDialog.tsx @@ -0,0 +1,166 @@ +import { useEffect, useState } from 'react'; +import { + Link, + TextField, + Dialog, + DialogActions, + DialogContent, + DialogTitle, + Button, + Typography, +} from '@material-ui/core'; +import useStore from '../../store/useStore'; + +const EditSceneDialog = () => { + const [name, setName] = useState(''); + const [image, setImage] = useState(''); + const [url, setUrl] = useState(''); + const [payload, setPayload] = useState(''); + const [overwrite, setOverwrite] = useState(false); + const [invalid, setInvalid] = useState(false); + const addScene = useStore((state) => state.addScene); + const getScenes = useStore((state) => state.getScenes); + const scenes = useStore((state) => state.scenes); + const open = useStore((state) => state.dialogs.addScene?.edit || false); + // const key = useStore((state: any) => state.dialogs.addScene?.sceneKey || ''); + const data = useStore((state: any) => state.dialogs.addScene?.editData || ''); + const setDialogOpenAddScene = useStore( + (state) => state.setDialogOpenAddScene + ); + + function isValidURL(string: string) { + const res = string.match( + /(http(s)?:\/\/.)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/g + ); + return res !== null; + } + + useEffect(() => { + if (data) { + setName(data?.name); + setImage(data?.scene_image); + setUrl(data?.url); + setPayload(data?.payload); + } + }, [data]); + const handleClose = () => { + setDialogOpenAddScene(false, false); + }; + + const handleAddScene = () => { + addScene(name, image, url, payload).then(() => { + getScenes(); + }); + setName(''); + setImage(''); + setUrl(''); + setPayload(''); + setDialogOpenAddScene(false, false); + }; + + return ( + + Edit Scene + + Image is optional and can be one of: +
    +
  • + iconName{' '} + + Find MUI icons here + + + eg. flare, AccessAlarms + +
  • +
  • + mdi:icon-name{' '} + + Find Material Design icons here + + + eg. mdi:balloon, mdi:led-strip-variant + +
  • +
  • + image:custom-url + + + eg. image:https://i.ytimg.com/vi/4G2unzNoOnY/maxresdefault.jpg + + +
  • +
+ setName(e.target.value)} + onBlur={(e) => { + setOverwrite( + Object.keys(scenes).indexOf(e.target.value.toLowerCase()) > -1 + ); + }} + error={overwrite} + helperText={overwrite && 'Scene already existing!'} + required + fullWidth + /> + setImage(e.target.value)} + fullWidth + /> + setUrl(e.target.value)} + fullWidth + error={invalid} + helperText={invalid && 'Enter valid URL!'} + onBlur={(e) => { + setInvalid(!isValidURL(e.target.value)); + }} + /> + setPayload(e.target.value)} + fullWidth + /> +
+ + + + +
+ ); +}; + +export default EditSceneDialog; diff --git a/src/pages/Scenes/Scenes.tsx b/src/pages/Scenes/Scenes.tsx index 8d86bed1..42e2506d 100644 --- a/src/pages/Scenes/Scenes.tsx +++ b/src/pages/Scenes/Scenes.tsx @@ -14,7 +14,7 @@ import { CardMedia, Typography, } from '@material-ui/core'; -import { Info } from '@material-ui/icons'; +import { Info, Edit } from '@material-ui/icons'; import { Grid } from '@mui/material'; import useStore from '../../store/useStore'; import Popover from '../../components/Popover/Popover'; @@ -63,7 +63,7 @@ const SceneDialog = ({ info, setInfo, scene }: any) => { }; const handleUpdateScene = (s: any) => { - addScene(s.name, s.scene_image).then(() => { + addScene(s.name, s.scene_image, s.url, s.payload).then(() => { getScenes(); }); setDialogOpenAddScene(false); @@ -132,12 +132,18 @@ const Scenes = () => { const getScenes = useStore((state) => state.getScenes); const scenes = useStore((state) => state.scenes); const activateScene = useStore((state) => state.activateScene); + const captivateScene = useStore((state) => state.captivateScene); const deleteScene = useStore((state) => state.deleteScene); const [info, setInfo] = useState(false); const [scene, setScene] = useState(); - + const setDialogOpenAddScene = useStore( + (state) => state.setDialogOpenAddScene + ); const handleActivateScene = (e: string) => { + // console.log('captivate', e, scenes[e]); activateScene(e); + if (scenes[e]?.scene_puturl && scenes[e]?.scene_payload) + captivateScene(scenes[e]?.scene_puturl, scenes[e]?.scene_payload); }; const handleDeleteScene = (e: any) => { @@ -199,10 +205,21 @@ const Scenes = () => { {scenes[s].name || s}
+ handleDeleteScene(s)} variant="outlined" color="inherit" + style={{ marginLeft: '0.5rem' }} /> diff --git a/src/components/Dialogs/EditSceneDialog.tsx b/src/components/Dialogs/EditSceneDialog.tsx index ecd18150..51998e35 100644 --- a/src/components/Dialogs/EditSceneDialog.tsx +++ b/src/components/Dialogs/EditSceneDialog.tsx @@ -24,13 +24,14 @@ const EditSceneDialog = () => { const open = useStore((state) => state.dialogs.addScene?.edit || false); // const key = useStore((state: any) => state.dialogs.addScene?.sceneKey || ''); const data = useStore((state: any) => state.dialogs.addScene?.editData || ''); + const viewMode = useStore((state) => state.viewMode); const setDialogOpenAddScene = useStore( (state) => state.setDialogOpenAddScene ); function isValidURL(string: string) { const res = string.match( - /(http(s)?:\/\/.)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/g + /(http(s)?:\/\/.)?(www\.)?[-a-zA-Z0-9@:%._~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_.~#?&//=]*)/g ); return res !== null; } @@ -39,8 +40,8 @@ const EditSceneDialog = () => { if (data) { setName(data?.name); setImage(data?.scene_image); - setUrl(data?.url); - setPayload(data?.payload); + setUrl(data?.scene_puturl); + setPayload(data?.scene_payload); } }, [data]); const handleClose = () => { @@ -129,29 +130,33 @@ const EditSceneDialog = () => { onChange={(e) => setImage(e.target.value)} fullWidth /> - setUrl(e.target.value)} - fullWidth - error={invalid} - helperText={invalid && 'Enter valid URL!'} - onBlur={(e) => { - setInvalid(!isValidURL(e.target.value)); - }} - /> - setPayload(e.target.value)} - fullWidth - /> + {viewMode !== 'user' && ( + <> + setUrl(e.target.value)} + fullWidth + error={invalid} + helperText={invalid && 'Enter valid URL!'} + onBlur={(e) => { + setInvalid(!isValidURL(e.target.value)); + }} + /> + setPayload(e.target.value)} + fullWidth + /> + + )} From ffd3f79c9ce3efb352840f6724f883a8277a80b3 Mon Sep 17 00:00:00 2001 From: Mattallmighty Date: Sat, 29 Oct 2022 12:01:55 +1100 Subject: [PATCH 4/8] Headers JSON attempt... --- src/pages/Scenes/Scenes.tsx | 7 ++++++- src/store/api/storeScenes.tsx | 8 ++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/pages/Scenes/Scenes.tsx b/src/pages/Scenes/Scenes.tsx index 42e2506d..bd138798 100644 --- a/src/pages/Scenes/Scenes.tsx +++ b/src/pages/Scenes/Scenes.tsx @@ -140,10 +140,15 @@ const Scenes = () => { (state) => state.setDialogOpenAddScene ); const handleActivateScene = (e: string) => { + const headers = { 'Content-Type': 'application/json' }; // console.log('captivate', e, scenes[e]); activateScene(e); if (scenes[e]?.scene_puturl && scenes[e]?.scene_payload) - captivateScene(scenes[e]?.scene_puturl, scenes[e]?.scene_payload); + captivateScene( + scenes[e]?.scene_puturl, + scenes[e]?.scene_payload, + headers + ); }; const handleDeleteScene = (e: any) => { diff --git a/src/store/api/storeScenes.tsx b/src/store/api/storeScenes.tsx index a9f225fd..8995a237 100644 --- a/src/store/api/storeScenes.tsx +++ b/src/store/api/storeScenes.tsx @@ -43,8 +43,12 @@ const storeScenes = (set: any) => ({ }), deleteScene: async (name: string) => await Ledfx('/api/scenes', 'DELETE', { data: { id: name } }), - captivateScene: async (scene_puturl: string, scene_payload: string) => - await Ledfx(scene_puturl, 'PUT', scene_payload), + + captivateScene: async ( + scene_puturl: string, + scene_payload: string, + headers: any + ) => await Ledfx(scene_puturl, 'PUT', scene_payload, headers), }); export default storeScenes; From 21e86e43d3117c6e5a4a7eb116429a2b68ee50c0 Mon Sep 17 00:00:00 2001 From: Mattallmighty Date: Sat, 29 Oct 2022 13:55:58 +1100 Subject: [PATCH 5/8] fix headers, now body needs fixing --- src/pages/Scenes/Scenes.tsx | 7 +------ src/store/api/storeScenes.tsx | 9 ++++----- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/src/pages/Scenes/Scenes.tsx b/src/pages/Scenes/Scenes.tsx index bd138798..42e2506d 100644 --- a/src/pages/Scenes/Scenes.tsx +++ b/src/pages/Scenes/Scenes.tsx @@ -140,15 +140,10 @@ const Scenes = () => { (state) => state.setDialogOpenAddScene ); const handleActivateScene = (e: string) => { - const headers = { 'Content-Type': 'application/json' }; // console.log('captivate', e, scenes[e]); activateScene(e); if (scenes[e]?.scene_puturl && scenes[e]?.scene_payload) - captivateScene( - scenes[e]?.scene_puturl, - scenes[e]?.scene_payload, - headers - ); + captivateScene(scenes[e]?.scene_puturl, scenes[e]?.scene_payload); }; const handleDeleteScene = (e: any) => { diff --git a/src/store/api/storeScenes.tsx b/src/store/api/storeScenes.tsx index 8995a237..0b0555bc 100644 --- a/src/store/api/storeScenes.tsx +++ b/src/store/api/storeScenes.tsx @@ -44,11 +44,10 @@ const storeScenes = (set: any) => ({ deleteScene: async (name: string) => await Ledfx('/api/scenes', 'DELETE', { data: { id: name } }), - captivateScene: async ( - scene_puturl: string, - scene_payload: string, - headers: any - ) => await Ledfx(scene_puturl, 'PUT', scene_payload, headers), + captivateScene: async (scene_puturl: string, scene_payload: string) => + await Ledfx(scene_puturl, 'PUT', { + scene_payload, + }), }); export default storeScenes; From 9a779011a168d0c74081a9c4a701fb3261827872 Mon Sep 17 00:00:00 2001 From: Mattallmighty Date: Sun, 30 Oct 2022 11:39:46 +1100 Subject: [PATCH 6/8] Update storeScenes.tsx --- src/store/api/storeScenes.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/store/api/storeScenes.tsx b/src/store/api/storeScenes.tsx index 0b0555bc..0aa99026 100644 --- a/src/store/api/storeScenes.tsx +++ b/src/store/api/storeScenes.tsx @@ -2,6 +2,7 @@ /* eslint-disable no-param-reassign */ /* eslint-disable import/no-cycle */ import produce from 'immer'; +// import { string } from 'prop-types'; import { Ledfx } from '../../api/ledfx'; const storeScenes = (set: any) => ({ @@ -44,10 +45,8 @@ const storeScenes = (set: any) => ({ deleteScene: async (name: string) => await Ledfx('/api/scenes', 'DELETE', { data: { id: name } }), - captivateScene: async (scene_puturl: string, scene_payload: string) => - await Ledfx(scene_puturl, 'PUT', { - scene_payload, - }), + captivateScene: async (scene_puturl: string, scene_payload: JSON) => + await Ledfx(scene_puturl, 'PUT', scene_payload), }); export default storeScenes; From 9795eaf4ac445882ffbfcd8d02f0fc49a6807b75 Mon Sep 17 00:00:00 2001 From: Mattallmighty Date: Mon, 31 Oct 2022 08:58:12 +1100 Subject: [PATCH 7/8] Update storeScenes.tsx --- src/store/api/storeScenes.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/store/api/storeScenes.tsx b/src/store/api/storeScenes.tsx index 0aa99026..9167acb0 100644 --- a/src/store/api/storeScenes.tsx +++ b/src/store/api/storeScenes.tsx @@ -45,8 +45,8 @@ const storeScenes = (set: any) => ({ deleteScene: async (name: string) => await Ledfx('/api/scenes', 'DELETE', { data: { id: name } }), - captivateScene: async (scene_puturl: string, scene_payload: JSON) => - await Ledfx(scene_puturl, 'PUT', scene_payload), + captivateScene: async (scene_puturl: string, scene_payload: string) => + await Ledfx(scene_puturl, 'PUT', JSON.parse(scene_payload)), }); export default storeScenes; From c988b90ee1ef5ca47cda4a3c917591082dfab8b0 Mon Sep 17 00:00:00 2001 From: Mattallmighty Date: Mon, 31 Oct 2022 09:51:45 +1100 Subject: [PATCH 8/8] Fix if blank URL --- src/components/Dialogs/AddSceneDialog.tsx | 2 +- src/components/Dialogs/EditSceneDialog.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Dialogs/AddSceneDialog.tsx b/src/components/Dialogs/AddSceneDialog.tsx index 400a70f1..18a7d6af 100644 --- a/src/components/Dialogs/AddSceneDialog.tsx +++ b/src/components/Dialogs/AddSceneDialog.tsx @@ -32,7 +32,7 @@ const AddSceneDialog = () => { }, []); function isValidURL(string: string) { const res = string.match( - /^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w.-]+)+[\w\-._~:/?#[\]@!$&'()*+,;=.]+$/g + /(?![\s\S])|\d^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w.-]+)+[\w\-._~:/?#[\]@!$&'()*+,;=.]+$/g ); return res !== null; } diff --git a/src/components/Dialogs/EditSceneDialog.tsx b/src/components/Dialogs/EditSceneDialog.tsx index 51998e35..86afc7e6 100644 --- a/src/components/Dialogs/EditSceneDialog.tsx +++ b/src/components/Dialogs/EditSceneDialog.tsx @@ -31,7 +31,7 @@ const EditSceneDialog = () => { function isValidURL(string: string) { const res = string.match( - /(http(s)?:\/\/.)?(www\.)?[-a-zA-Z0-9@:%._~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_.~#?&//=]*)/g + /(?![\s\S])|\d(http(s)?:\/\/.)?(www\.)?[-a-zA-Z0-9@:%._~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_.~#?&//=]*)/g ); return res !== null; }