Skip to content

Commit

Permalink
Merge pull request #36 from Mattallmighty/Scene-Activation-=-PUT
Browse files Browse the repository at this point in the history
Scene activation = put
  • Loading branch information
YeonV authored Oct 30, 2022
2 parents 8e3e389 + c988b90 commit de336fa
Show file tree
Hide file tree
Showing 6 changed files with 271 additions and 14 deletions.
2 changes: 2 additions & 0 deletions src/components/Bars/BarBottom.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -213,6 +214,7 @@ export default function BarBottom() {
<AddDeviceDialog />
<AddVirtualDialog />
<AddIntegrationDialog />
<EditSceneDialog />
<AddButton
setBackdrop={setBackdrop}
className={`${clsx(classes.addButton, {
Expand Down
59 changes: 51 additions & 8 deletions src/components/Dialogs/AddSceneDialog.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState } from 'react';
import { useEffect, useState } from 'react';
import {
Link,
TextField,
Expand All @@ -14,26 +14,42 @@ import useStore from '../../store/useStore';
const AddSceneDialog = () => {
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?.open || false);
const viewMode = useStore((state) => state.viewMode);
const setDialogOpenAddScene = useStore(
(state) => state.setDialogOpenAddScene
);

useEffect(() => {
setInvalid(false);
}, []);
function isValidURL(string: string) {
const res = string.match(
/(?![\s\S])|\d^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w.-]+)+[\w\-._~:/?#[\]@!$&'()*+,;=.]+$/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 (
Expand Down Expand Up @@ -107,6 +123,33 @@ const AddSceneDialog = () => {
onChange={(e) => setImage(e.target.value)}
fullWidth
/>
{viewMode !== 'user' && (
<>
<TextField
margin="dense"
id="scene_url"
label="Url"
type="url"
value={url}
onChange={(e) => setUrl(e.target.value)}
fullWidth
error={invalid}
helperText={invalid && 'Enter valid URL!'}
onBlur={(e) => {
setInvalid(!isValidURL(e.target.value));
}}
/>
<TextField
margin="dense"
id="scene_payload"
label="Payload"
type="text"
value={payload}
onChange={(e) => setPayload(e.target.value)}
fullWidth
/>
</>
)}
</DialogContent>
<DialogActions>
<Button onClick={handleClose}>Cancel</Button>
Expand Down
171 changes: 171 additions & 0 deletions src/components/Dialogs/EditSceneDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
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 viewMode = useStore((state) => state.viewMode);
const setDialogOpenAddScene = useStore(
(state) => state.setDialogOpenAddScene
);

function isValidURL(string: string) {
const res = string.match(
/(?![\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;
}

useEffect(() => {
if (data) {
setName(data?.name);
setImage(data?.scene_image);
setUrl(data?.scene_puturl);
setPayload(data?.scene_payload);
}
}, [data]);
const handleClose = () => {
setDialogOpenAddScene(false, false);
};

const handleAddScene = () => {
addScene(name, image, url, payload).then(() => {
getScenes();
});
setName('');
setImage('');
setUrl('');
setPayload('');
setDialogOpenAddScene(false, false);
};

return (
<Dialog
open={open}
onClose={handleClose}
aria-labelledby="form-dialog-title"
>
<DialogTitle id="form-dialog-title">Edit Scene</DialogTitle>
<DialogContent>
Image is optional and can be one of:
<ul style={{ paddingLeft: '1rem' }}>
<li>
iconName{' '}
<Link
href="https://material-ui.com/components/material-icons/"
target="_blank"
>
Find MUI icons here
</Link>
<Typography color="textSecondary" variant="subtitle1">
<em>eg. flare, AccessAlarms</em>
</Typography>
</li>
<li>
mdi:icon-name{' '}
<Link href="https://materialdesignicons.com" target="_blank">
Find Material Design icons here
</Link>
<Typography color="textSecondary" variant="subtitle1">
<em>eg. mdi:balloon, mdi:led-strip-variant</em>
</Typography>
</li>
<li>
image:custom-url
<Typography
color="textSecondary"
variant="subtitle1"
style={{ wordBreak: 'break-all' }}
>
<em>
eg. image:https://i.ytimg.com/vi/4G2unzNoOnY/maxresdefault.jpg
</em>
</Typography>
</li>
</ul>
<TextField
autoFocus
margin="dense"
id="name"
label="Name"
type="text"
value={name}
onChange={(e) => 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
/>
<TextField
margin="dense"
id="scene_image"
label="Image"
type="text"
value={image}
onChange={(e) => setImage(e.target.value)}
fullWidth
/>
{viewMode !== 'user' && (
<>
<TextField
margin="dense"
id="url"
label="Url"
type="url"
value={url}
onChange={(e) => setUrl(e.target.value)}
fullWidth
error={invalid}
helperText={invalid && 'Enter valid URL!'}
onBlur={(e) => {
setInvalid(!isValidURL(e.target.value));
}}
/>
<TextField
margin="dense"
id="payload"
label="Payload"
type="text"
value={payload}
onChange={(e) => setPayload(e.target.value)}
fullWidth
/>
</>
)}
</DialogContent>
<DialogActions>
<Button onClick={handleClose}>Cancel</Button>
<Button onClick={handleAddScene}>
{overwrite ? 'Overwrite' : 'Save'}
</Button>
</DialogActions>
</Dialog>
);
};

export default EditSceneDialog;
23 changes: 20 additions & 3 deletions src/pages/Scenes/Scenes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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) => {
Expand Down Expand Up @@ -199,10 +205,21 @@ const Scenes = () => {
{scenes[s].name || s}
</Typography>
<div>
<Button
onClick={() =>
setDialogOpenAddScene(false, true, s, scenes[s])
}
variant="outlined"
color="inherit"
size="small"
>
<Edit />
</Button>
<Popover
onConfirm={() => handleDeleteScene(s)}
variant="outlined"
color="inherit"
style={{ marginLeft: '0.5rem' }}
/>
<Button
onClick={() => handleInfoOpen(s)}
Expand Down
18 changes: 16 additions & 2 deletions src/store/api/storeScenes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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) => ({
Expand All @@ -18,8 +19,18 @@ const storeScenes = (set: any) => ({
);
}
},
addScene: async (name: string, scene_image: string) =>
await Ledfx('/api/scenes', 'POST', { name, scene_image }),
addScene: async (
name: string,
scene_image: string,
scene_puturl: string,
scene_payload: string
) =>
await Ledfx('/api/scenes', 'POST', {
name,
scene_image,
scene_puturl,
scene_payload,
}),
activateScene: async (id: string) =>
await Ledfx('/api/scenes', 'PUT', {
id,
Expand All @@ -33,6 +44,9 @@ 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', JSON.parse(scene_payload)),
});

export default storeScenes;
Loading

0 comments on commit de336fa

Please sign in to comment.