- {m.map((yzrow, currentRowIndex) =>
- {yzrow.map((yzcolumn: IMCell, currentColIndex: number) => (
-
{
+ if (virtual.segments.length === 0) {
+ if (!Object.values(devices).some((d) => d.id === `gap-${virtual.id}`)) {
+ // add new device
+ addDevice({
+ type: 'dummy',
+ config: {
+ center_offset: 0,
+ icon_name: 'mdi:eye-off',
+ name: `gap-${virtual.id}`,
+ pixel_count: 4096,
+ refresh_rate: 64
+ }
+ }).then(() => {
+ Ledfx(`/api/virtuals/${virtual.id}`, 'POST', {
+ segments: [
+ [
+ `gap-${virtual.id}`,
+ 0,
+ virtual.config.rows * virtual.config.rows - 1,
+ false
+ ]
+ ]
+ }).then(() => {
+ getDevices()
+ getVirtuals().then(() => {
+ setEffect(
+ virtual.id,
+ 'equalizer2d',
+ { bands: virtual.config.rows },
+ true
+ ).then(() => {
+ updateVirtual(virtual.id, true)
+ })
+ })
+ })
+ })
+ }
+ }
+ }, [])
+
+ /**
+ * Update the row and column numbers when the virtual changes
+ */
+ useEffect(() => {
+ setRowNumber(virtual.config.rows || 8)
+ setColNumber(
+ Math.ceil(virtual.pixel_count / (virtual.config.rows || 1)) || 8
+ )
+ }, [virtual])
- opacity: yzcolumn.deviceId !== '' ? 1 : 0.3,
- }} onContextMenu={(e) => {
- e.preventDefault()
- setCurrentCell([currentColIndex, currentRowIndex])
- setCurrentDevice(yzcolumn.deviceId !== '' ? yzcolumn.deviceId : '')
- setSelectedPixel(yzcolumn.pixel || 0)
- setOpen(true)
- }}>
- {yzcolumn.deviceId !== '' && (
-
- {devices[yzcolumn.deviceId].config.name}
- {yzcolumn.pixel}
-
- )}
-
- ))}
+ /**
+ * Update the matrix when a new point is added from the video mapper
+ */
+ useEffect(() => {
+ if (points.length > 0) {
+ const updatedM = clone(m)
+ const p = points[points.length - 1]
+ if (
+ !isNaN(p.x) &&
+ !isNaN(p.y) &&
+ p.x > 0 &&
+ p.y > 0 &&
+ p.x <= colN &&
+ p.y <= rowN
+ ) {
+ updatedM[p.y - 1][p.x - 1] = {
+ deviceId: p.device,
+ pixel: p.led,
+ group: p.segment + 1
+ }
+ setM(updatedM)
+ }
+ }
+ }, [points])
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
handleDragEnd(e)}
+ onDragOver={(e) =>
+ setHoveringCell(
+ (e.over?.id as any)?.split('-').map(Number) || [-1, -1]
+ )
+ }
+ onDragStart={() => {
+ // console.log('zy', e.active?.id, hoveringCell, selectedGroup)
+ setIsDragging(true)
+ }}
+ >
+ {m.map((yzrow, currentRowIndex) => (
+
+ {yzrow.map((yzcolumn: IMCell, currentColIndex: number) => {
+ const bg = getBackgroundColor(
+ mode,
+ decodedPixels,
+ pixels,
+ currentRowIndex,
+ colN,
+ currentColIndex
+ )
+ const op = getOpacity(move, yzcolumn, selectedGroup)
+ return (
+
-1 && hoveringCell[1] > -1
+ ? m[hoveringCell[1]][hoveringCell[0]]
+ : undefined
+ }
+ id={`${currentColIndex}-${currentRowIndex}`}
+ key={`col-${currentColIndex}`}
+ bg={bg}
+ opacity={op}
+ onContextMenu={(e) =>
+ handleContextMenu(
+ e,
+ currentColIndex,
+ currentRowIndex,
+ yzcolumn
+ )
+ }
+ >
+
+ handleContextMenu(
+ e,
+ currentColIndex,
+ currentRowIndex,
+ yzcolumn
+ )
+ }
+ sx={{
+ backgroundColor: bg,
+ opacity: op
+ }}
+ >
+ {dnd ? (
+ m[currentRowIndex][currentColIndex].deviceId !==
+ '' ? (
+
+
+ ) => setAnchorEl(e.currentTarget)}
+ isDragging={isDragging}
+ />
+
+ ) : null
+ ) : (
+
+ ) => setAnchorEl(e.currentTarget)}
+ isDragging={isDragging}
+ />
+ )}
+
+
+ )
+ })}
+
+ ))}
+
- )}
+
setAnchorEl(null)}
+ currentCell={currentCell}
+ m={m}
+ setOpen={setOpen}
+ setMove={setMove}
+ />
+
-
-
-
-
- }
+
+
+
+ )
+}
export default EditMatrix
diff --git a/src/pages/Devices/EditVirtuals/EditMatrix/M.utils.tsx b/src/pages/Devices/EditVirtuals/EditMatrix/M.utils.tsx
index 9d332320..31f8b912 100644
--- a/src/pages/Devices/EditVirtuals/EditMatrix/M.utils.tsx
+++ b/src/pages/Devices/EditVirtuals/EditMatrix/M.utils.tsx
@@ -19,9 +19,10 @@ export type IDir =
export type IMCell = {
deviceId: string
pixel: number
+ group?: string
}
-export const MCell: IMCell = { deviceId: '', pixel: 0 }
+export const MCell: IMCell = { deviceId: '', pixel: 0, group: '0-0' }
/**
* Calculates the maximum available pixel given the input data
@@ -62,3 +63,41 @@ export const getMaxRange = (
* deep clone
*/
export const clone = (input: any) => JSON.parse(JSON.stringify(input))
+
+export const getOpacity = (
+ move: boolean,
+ yzcolumn: IMCell,
+ selectedGroup: string
+) => {
+ if (move && yzcolumn?.group === selectedGroup) {
+ return 1
+ } else if (
+ (move && yzcolumn?.group !== selectedGroup) ||
+ selectedGroup === ''
+ ) {
+ return 0.3
+ } else if (yzcolumn.deviceId !== '') {
+ return 1
+ } else {
+ return 0.3
+ }
+}
+
+export const getBackgroundColor = (
+ mode: 'compressed' | 'uncompressed' | undefined,
+ decodedPixels: any[] | undefined,
+ pixels: any[][],
+ currentRowIndex: number,
+ colN: number,
+ currentColIndex: number
+) => {
+ if (mode === 'compressed' && decodedPixels) {
+ return decodedPixels[currentRowIndex * colN + currentColIndex]
+ ? `rgb(${Object.values(decodedPixels[currentRowIndex * colN + currentColIndex])})`
+ : '#222'
+ } else if (pixels && pixels[0] && pixels[0].length) {
+ return `rgb(${pixels[0][currentRowIndex * colN + currentColIndex]},${pixels[1][currentRowIndex * colN + currentColIndex]},${pixels[2][currentRowIndex * colN + currentColIndex]})`
+ } else {
+ return '#222'
+ }
+}
diff --git a/src/pages/Devices/EditVirtuals/EditMatrix/MContextMenu.tsx b/src/pages/Devices/EditVirtuals/EditMatrix/MContextMenu.tsx
new file mode 100644
index 00000000..a7c229fa
--- /dev/null
+++ b/src/pages/Devices/EditVirtuals/EditMatrix/MContextMenu.tsx
@@ -0,0 +1,67 @@
+import { Menu, MenuItem } from '@mui/material'
+
+const MContextMenu = ({
+ anchorEl,
+ closeContextMenu,
+ setOpen,
+ setSelectedGroup,
+ setMove,
+ currentCell,
+ m,
+ setDnd
+}: {
+ anchorEl: any
+ closeContextMenu: any
+ setOpen: any
+ setSelectedGroup: any
+ setMove: any
+ currentCell: [number, number]
+ m: any
+ setDnd: any
+}) => {
+ const contextMenuOpen = Boolean(anchorEl)
+ return (
+
+ )
+}
+
+export default MContextMenu
diff --git a/src/pages/Devices/EditVirtuals/EditMatrix/MControls.tsx b/src/pages/Devices/EditVirtuals/EditMatrix/MControls.tsx
index a480f15f..4d97267d 100644
--- a/src/pages/Devices/EditVirtuals/EditMatrix/MControls.tsx
+++ b/src/pages/Devices/EditVirtuals/EditMatrix/MControls.tsx
@@ -1,14 +1,43 @@
import {
+ ArrowBack,
+ ArrowDownward,
+ ArrowForward,
+ ArrowUpward,
+ Cancel,
+ ControlCamera,
+ PanTool,
Rotate90DegreesCw,
Save,
SwapHoriz,
SwapVert
} from '@mui/icons-material'
-import { Box, Button, Slider, Stack } from '@mui/material'
+import {
+ Alert,
+ Box,
+ Button,
+ // Collapse,
+ IconButton,
+ Slider,
+ Stack,
+ Typography
+} from '@mui/material'
+import { useEffect, useState } from 'react'
+import Tab from '@mui/material/Tab'
+import TabContext from '@mui/lab/TabContext'
+import TabList from '@mui/lab/TabList'
+import TabPanel from '@mui/lab/TabPanel'
import { Ledfx } from '../../../../api/ledfx'
import Popover from '../../../../components/Popover/Popover'
import { transpose } from '../../../../utils/helpers'
import { MCell } from './M.utils'
+import { processArray } from './processMatrix'
+import moveSelectedGroupUp from './Actions/moveSelectedGroupUp'
+import moveSelectedGroupLeft from './Actions/moveSelectedGroupLeft'
+import moveSelectedGroupRight from './Actions/moveSelectedGroupRight'
+import moveSelectedGroupDown from './Actions/moveSelectedGroupDown'
+import useStore from '../../../../store/useStore'
+import Webcam from '../../../../components/Webcam/Webcam'
+// import useStore from '../../../../store/useStore'
const MControls = ({
rowN,
@@ -17,99 +46,308 @@ const MControls = ({
setColNumber,
virtual,
m,
- setM
-}: any) => {
+ setM,
+ move,
+ dnd,
+ setMove,
+ setDnd,
+ selectedGroup,
+ setError
+}: {
+ rowN: number
+ colN: number
+ setRowNumber: any
+ setColNumber: any
+ virtual: any
+ m: any
+ setM: any
+ move: boolean
+ dnd: boolean
+ setMove: any
+ setDnd: any
+ selectedGroup: string
+ setError: any
+}) => {
+ // const infoAlerts = useStore((state) => state.ui.infoAlerts)
+ // const setInfoAlerts = useStore((state) => state.ui.setInfoAlerts)
+ const [tab, setTab] = useState('1')
+ const getVirtuals = useStore((state) => state.getVirtuals)
+ const getDevices = useStore((state) => state.getDevices)
+ const features = useStore((state) => state.features)
+
+ const handleChange = (event: React.SyntheticEvent, newValue: string) => {
+ if (newValue === '1') setDnd(false)
+ if (newValue === '2') setDnd(true)
+ setTab(newValue)
+ }
+
+ useEffect(() => {
+ if (dnd && tab !== '2') setTab('2')
+ if (!dnd && tab !== '1') setTab('1')
+ }, [dnd])
+
return (
- <>
-
- Rows:
-
-
- typeof newRowNumber === 'number' && setRowNumber(newRowNumber)
- }
- />
-
- {rowN}
-
-
- Columns:
-
-
- typeof newColNumber === 'number' && setColNumber(newColNumber)
- }
- />
-
- {colN}
-
-
-
-
-
-
+ />
+
+ {rowN}
-
- {
- setM(Array(rowN).fill(Array(colN).fill(MCell)))
- }}
- />
+
+
+ Columns:
+
+
+
+ typeof newColNumber === 'number' && setColNumber(newColNumber)
+ }
+ />
+
+ {colN}
+
+
+
+
+
+
+
+
+ {
+ setM(Array(rowN).fill(Array(colN).fill(MCell)))
+ }}
+ />
-
+
+
- >
+
+ }
+ iconPosition="start"
+ label="Move Group"
+ value
+ />
+
+ {move ? (
+
+
+
+ moveSelectedGroupUp({
+ m,
+ rowN,
+ colN,
+ selectedGroup,
+ setError,
+ setM
+ })
+ }
+ >
+
+
+
+
+ moveSelectedGroupLeft({
+ m,
+ rowN,
+ colN,
+ selectedGroup,
+ setM
+ })
+ }
+ >
+
+
+ setMove(false)}>
+
+
+
+ moveSelectedGroupRight({
+ m,
+ rowN,
+ colN,
+ selectedGroup,
+ setM
+ })
+ }
+ >
+
+
+
+
+ moveSelectedGroupDown({
+ m,
+ rowN,
+ colN,
+ selectedGroup,
+ setError,
+ setM
+ })
+ }
+ >
+
+
+
+
+ ) : (
+
+
+ Right-Click an element to move a group.
+
+ Groups can only be moved with the UI buttons
+
+
+ )}
+
+
+
+ }
+ iconPosition="start"
+ label="Canvas"
+ value="1"
+ />
+ }
+ iconPosition="start"
+ label="DND"
+ value="2"
+ />
+
+
+
+
+ Canvas Mode
+
+ - Use Mousewheel to Zoom
+ - Use left-click with drag&drop to move around
+ - Use right-click to:
+
+ - assign pixel or pixel-group
+ - edit a pixel
+ - clear a pixel
+ - move a pixel-group
+
+ - Enter DND mode to move pixels individually
+
+
+
+
+
+ DND Mode
+
+ - move pixels individually with your mouse
+
+
+
+
+ {features.matrix_cam && }
+
)
}
-
export default MControls
diff --git a/src/pages/Devices/EditVirtuals/EditMatrix/MWrapper.tsx b/src/pages/Devices/EditVirtuals/EditMatrix/MWrapper.tsx
index b5297a18..f076cef1 100644
--- a/src/pages/Devices/EditVirtuals/EditMatrix/MWrapper.tsx
+++ b/src/pages/Devices/EditVirtuals/EditMatrix/MWrapper.tsx
@@ -1,26 +1,25 @@
-import { Alert } from '@mui/material'
+import { Box } from '@mui/material'
-const MWrapper = ({ children }: any) => {
+const MWrapper = ({ children, move }: any) => {
return (
-
-
- Concept Draft
-
- - Use Mousewheel to Zoom
- - Use left-click with drag&drop to move around
- - Use right-click to assign Pixels
-
-
{children}
-
+
)
}
diff --git a/src/pages/Devices/EditVirtuals/EditMatrix/Pixel.tsx b/src/pages/Devices/EditVirtuals/EditMatrix/Pixel.tsx
new file mode 100644
index 00000000..ab621995
--- /dev/null
+++ b/src/pages/Devices/EditVirtuals/EditMatrix/Pixel.tsx
@@ -0,0 +1,104 @@
+import { Box, Typography } from '@mui/material'
+import { IMCell } from './M.utils'
+import useStore from '../../../../store/useStore'
+
+const Pixel = ({
+ m,
+ currentColIndex,
+ classes,
+ currentRowIndex,
+ move,
+ decodedPixels,
+ colN,
+ pixels,
+ yzcolumn,
+ selectedGroup,
+ error,
+ setCurrentCell,
+ setCurrentDevice,
+ setSelectedPixel,
+ openContextMenu,
+ isDragging
+}: {
+ m: IMCell[][]
+ currentColIndex: number
+ classes: any
+ currentRowIndex: number
+ move: boolean
+ decodedPixels: any
+ colN: number
+ pixels: any
+ yzcolumn: IMCell
+ selectedGroup: string
+ error: {
+ row: number
+ col: number
+ }[]
+ setCurrentCell: any
+ setCurrentDevice: any
+ setSelectedPixel: any
+ openContextMenu: any
+ isDragging: boolean
+}) => {
+ const devices = useStore((state) => state.devices)
+ const mode = useStore((state) => state.config).transmission_mode
+ if (error.length > 0) console.log(isDragging, error)
+ return (
+
e.row === currentRowIndex && e.col === currentColIndex
+ // )
+ // ? '1px solid red'
+ // : '1px solid #000',
+ backgroundColor:
+ mode === 'compressed' && decodedPixels
+ ? decodedPixels[currentRowIndex * colN + currentColIndex]
+ ? `rgb(${Object.values(decodedPixels[currentRowIndex * colN + currentColIndex])})`
+ : '#222'
+ : pixels && pixels[0] && pixels[0].length
+ ? `rgb(${pixels[0][currentRowIndex * colN + currentColIndex]},${pixels[1][currentRowIndex * colN + currentColIndex]},${pixels[2][currentRowIndex * colN + currentColIndex]})`
+ : '#222',
+ opacity: isDragging
+ ? 0.3
+ : move && yzcolumn?.group === selectedGroup
+ ? 1
+ : (move && yzcolumn?.group !== selectedGroup) ||
+ selectedGroup === ''
+ ? 0.9
+ : yzcolumn.deviceId !== ''
+ ? 1
+ : 0.3
+ }}
+ onContextMenu={(e) => {
+ e.preventDefault()
+ setCurrentCell([currentColIndex, currentRowIndex])
+ setCurrentDevice(yzcolumn.deviceId !== '' ? yzcolumn.deviceId : '')
+ setSelectedPixel(yzcolumn.pixel || 0)
+
+ if (
+ currentRowIndex > -1 &&
+ currentColIndex > -1 &&
+ m[currentRowIndex][currentColIndex]?.deviceId !== ''
+ ) {
+ // console.log(m[currentCell[1]][currentCell[0]].group)
+
+ openContextMenu(e)
+ }
+ // setOpen(true)
+ }}
+ >
+ {yzcolumn.deviceId !== '' && (
+
+
+ {devices[yzcolumn.deviceId].config.name}
+
+ {yzcolumn.pixel}
+
+ )}
+
+ )
+}
+
+export default Pixel
diff --git a/src/pages/Devices/EditVirtuals/EditMatrix/processMatrix.ts b/src/pages/Devices/EditVirtuals/EditMatrix/processMatrix.ts
new file mode 100644
index 00000000..13a6dbce
--- /dev/null
+++ b/src/pages/Devices/EditVirtuals/EditMatrix/processMatrix.ts
@@ -0,0 +1,112 @@
+type InputType = { deviceId: string; pixel: number; group?: string }
+type OutputType = [string, number, number, boolean]
+
+export function processArray(
+ inputArray: InputType[],
+ gapname = ''
+): OutputType[] {
+ const outputArray: OutputType[] = []
+ let startPixel: number | null = null
+ let endPixel: number | null = null
+ let deviceId: string = ''
+ let flip: boolean = false
+ let gapStart: number | null = null
+
+ for (let i = 0; i < inputArray.length; i += 1) {
+ if (inputArray[i].deviceId !== '') {
+ if (deviceId === '') {
+ if (gapStart !== null) {
+ outputArray.push([`gap-${gapname}`, gapStart, i - 1, false])
+ gapStart = null
+ }
+ deviceId = inputArray[i].deviceId
+ startPixel = inputArray[i].pixel
+ endPixel = inputArray[i].pixel
+ flip = false
+ } else if (
+ inputArray[i].deviceId === deviceId &&
+ Math.abs(inputArray[i].pixel - (endPixel as number)) === 1
+ ) {
+ endPixel = inputArray[i].pixel
+ flip = inputArray[i].pixel < (endPixel as number)
+ } else {
+ outputArray.push([
+ deviceId,
+ startPixel as number,
+ endPixel as number,
+ flip
+ ])
+ deviceId = inputArray[i].deviceId
+ startPixel = inputArray[i].pixel
+ endPixel = inputArray[i].pixel
+ flip = false
+ }
+ } else {
+ if (deviceId !== '') {
+ outputArray.push([
+ deviceId,
+ startPixel as number,
+ endPixel as number,
+ flip
+ ])
+ deviceId = ''
+ }
+ if (gapStart === null) {
+ gapStart = i
+ }
+ }
+ }
+
+ if (deviceId !== '') {
+ outputArray.push([deviceId, startPixel as number, endPixel as number, flip])
+ }
+ if (gapStart !== null) {
+ outputArray.push([`gap-${gapname}`, gapStart, inputArray.length - 1, false])
+ }
+
+ for (let i = 0; i < outputArray.length; i++) {
+ const item = outputArray[i]
+ if (item[1] > item[2]) {
+ item[3] = item[1] > item[2]
+ ;[item[1], item[2]] = [item[2], item[1]]
+ }
+ }
+
+ return outputArray
+}
+
+export function reverseProcessArray(
+ outputArray: OutputType[],
+ rows?: number
+): InputType[][] {
+ const inputArray: InputType[] = []
+ const finalArray: InputType[][] = []
+ let group: string = '0-0'
+
+ for (let i = 0; i < outputArray.length; i += 1) {
+ const [deviceId, startPixel, endPixel, flip] = outputArray[i]
+ if (deviceId.startsWith('gap-')) {
+ for (let j = startPixel; j <= endPixel; j += 1) {
+ inputArray.push({ deviceId: '', pixel: j, group: '0-0' })
+ }
+ } else if (flip) {
+ for (let j = endPixel; j >= startPixel; j -= 1) {
+ group = `${Math.floor(i / (rows || 1))}-${i % (rows || 1)}`
+ inputArray.push({ deviceId, pixel: j, group })
+ }
+ } else {
+ for (let j = startPixel; j <= endPixel; j += 1) {
+ group = `${Math.floor(i / (rows || 1))}-${i % (rows || 1)}`
+ inputArray.push({ deviceId, pixel: j, group })
+ }
+ }
+ }
+
+ if (rows) {
+ for (let i = 0; i < inputArray.length; i += rows) {
+ finalArray.push(inputArray.slice(i, i + rows))
+ }
+ return finalArray
+ }
+ return [inputArray]
+}
diff --git a/src/pages/Devices/EditVirtuals/EditVirtuals.tsx b/src/pages/Devices/EditVirtuals/EditVirtuals.tsx
index ae63cadb..2738c277 100644
--- a/src/pages/Devices/EditVirtuals/EditVirtuals.tsx
+++ b/src/pages/Devices/EditVirtuals/EditVirtuals.tsx
@@ -1,6 +1,3 @@
-/* eslint-disable react/prop-types */
-/* eslint-disable react/require-default-props */
-/* eslint-disable @typescript-eslint/no-empty-function */
import React, { useEffect, useState } from 'react'
import Button from '@mui/material/Button'
import Dialog from '@mui/material/Dialog'
@@ -68,7 +65,6 @@ export default function EditVirtuals({
innerKey
}: any) {
const [matrix, setMatrix] = useState(false)
- const features = useStore((state) => state.features)
const currentVirtual = useStore((state) => state.currentVirtual)
const setCurrentVirtual = useStore((state) => state.setCurrentVirtual)
const calibrationMode = useStore((state) => state.calibrationMode)
@@ -183,7 +179,7 @@ export default function EditVirtuals({
>
back
- {features.matrix && (
+ {virtual.config.rows > 1 && (
{
const [range, setRange] = useState([s[1], s[2]])
+ const handleChange = (_event: any, newValue: any) => {
+ if (newValue !== pixelRange) {
+ handleRangeSegment(newValue[0], newValue[1])
+ }
+ }
+
+ const throttled = useThrottledCallback(handleChange, 100)
+
useEffect(() => {
getDevices()
}, [getDevices])
@@ -24,13 +32,6 @@ const PixelSlider = ({ s, handleRangeSegment }: any) => {
const pixelRange = [s[1], s[2]]
- const handleChange = (_event: any, newValue: any) => {
- if (newValue !== pixelRange) {
- handleRangeSegment(newValue[0], newValue[1])
- }
- }
- const throttled = useThrottledCallback(handleChange, 100)
-
const marks = [
{ value: 0, label: 1 },
{
diff --git a/src/pages/Graph/Graph.tsx b/src/pages/Graph/Graph.tsx
index ce8621a5..df2dbd20 100644
--- a/src/pages/Graph/Graph.tsx
+++ b/src/pages/Graph/Graph.tsx
@@ -1,6 +1,5 @@
/* eslint-disable @typescript-eslint/indent */
-/* eslint-disable consistent-return */
-/* eslint-disable no-restricted-syntax */
+
import { useEffect, useState } from 'react'
import { Box } from '@mui/material'
import { useParams } from 'react-router-dom'
diff --git a/src/pages/Home/Dashboard.tsx b/src/pages/Home/Dashboard.tsx
index 6b77f95b..f1c2f8b0 100644
--- a/src/pages/Home/Dashboard.tsx
+++ b/src/pages/Home/Dashboard.tsx
@@ -1,9 +1,5 @@
/* eslint-disable @typescript-eslint/indent */
-/* eslint-disable no-console */
-/* eslint-disable @typescript-eslint/no-unused-vars */
-/* eslint-disable no-promise-executor-return */
-/* eslint-disable no-plusplus */
-/* eslint-disable no-await-in-loop */
+
import { useEffect, useState } from 'react'
import {
Box,
diff --git a/src/pages/Home/DbConfig.tsx b/src/pages/Home/DbConfig.tsx
index 0c18f7a8..95058d3b 100644
--- a/src/pages/Home/DbConfig.tsx
+++ b/src/pages/Home/DbConfig.tsx
@@ -1,37 +1,33 @@
-/* eslint-disable prettier/prettier */
-import { useTheme, Stack } from '@mui/material';
-import BladeFrame from '../../components/SchemaForm/components/BladeFrame';
-import DbRow from './DbRow';
-import useStore from '../../store/useStore';
+import { useTheme, Stack } from '@mui/material'
+import BladeFrame from '../../components/SchemaForm/components/BladeFrame'
+import DbRow from './DbRow'
+import useStore from '../../store/useStore'
const DbConfig = () => {
- const theme = useTheme();
- const config = useStore((state) => state.config);
-
+ const theme = useTheme()
+ const config = useStore((state) => state.config)
return (
-
-
- {config.port_s && (
-
- )}
+
+
+ {config.port_s && }
- );
-};
+ )
+}
-export default DbConfig;
+export default DbConfig
diff --git a/src/pages/Home/DbDevices.tsx b/src/pages/Home/DbDevices.tsx
index 6b6bd892..2f98dc30 100644
--- a/src/pages/Home/DbDevices.tsx
+++ b/src/pages/Home/DbDevices.tsx
@@ -1,4 +1,4 @@
-import { useTheme, Stack, Chip } from '@mui/material'
+import { useTheme, Stack, Chip, IconButton } from '@mui/material'
import {
DataGrid,
GridColDef,
@@ -8,28 +8,154 @@ import {
} from '@mui/x-data-grid'
import { useNavigate } from 'react-router-dom'
import { useEffect, useState } from 'react'
+import {
+ Clear,
+ DeleteForever,
+ Edit,
+ Fullscreen,
+ Pause,
+ PlayArrow,
+ Settings,
+ SyncProblem
+} from '@mui/icons-material'
import BladeFrame from '../../components/SchemaForm/components/BladeFrame'
import useStore from '../../store/useStore'
import BladeIcon from '../../components/Icons/BladeIcon/BladeIcon'
import PixelGraph from '../../components/PixelGraph'
-// import BladeIcon from '../../components/Icons/BladeIcon/BladeIcon';
+const DeviceActions = ({
+ virtId,
+ effect
+}: {
+ virtId: string
+ effect?: boolean
+}) => {
+ const navigate = useNavigate()
+
+ const virtuals = useStore((state) => state.virtuals)
+ const updateVirtual = useStore((state) => state.updateVirtual)
+ const getVirtuals = useStore((state) => state.getVirtuals)
+ const getDevices = useStore((state) => state.getDevices)
+ const clearEffect = useStore((state) => state.clearEffect)
+
+ const handlePlayPause = () => {
+ if (virtId && virtuals[virtId])
+ updateVirtual(virtId, !virtuals[virtId].active).then(() => getVirtuals())
+ }
+ const handleClearEffect = () => {
+ clearEffect(virtId).then(() => {
+ setTimeout(() => {
+ getVirtuals()
+ getDevices()
+ }, virtuals[virtId].config.transition_time * 1000)
+ })
+ }
+
+ return (
+ <>
+ {effect && (
+ <>
+ {
+ e.preventDefault()
+ e.stopPropagation()
+ handlePlayPause()
+ }}
+ >
+ {virtuals[virtId]?.active ? : }
+
+ {
+ e.preventDefault()
+ e.stopPropagation()
+ handleClearEffect()
+ }}
+ >
+
+
+ {virtuals[virtId]?.config.rows > 1 && (
+ {
+ e.preventDefault()
+ e.stopPropagation()
+ navigate(`/graph/${virtId}`)
+ }}
+ >
+
+
+ )}
+ >
+ )}
+ 1 ? 0 : 4.2)
+ }}
+ size="small"
+ onClick={(e) => {
+ e.preventDefault()
+ e.stopPropagation()
+ handlePlayPause()
+ }}
+ >
+
+
+ {
+ e.preventDefault()
+ e.stopPropagation()
+ handlePlayPause()
+ }}
+ >
+
+
+ {
+ e.preventDefault()
+ e.stopPropagation()
+ handlePlayPause()
+ }}
+ >
+
+
+ >
+ )
+}
+
+const ReconnectButton = ({ onClick }: { onClick: () => void }) => (
+ {
+ e.preventDefault()
+ onClick()
+ }}
+ >
+
+
+)
const DbDevices = () => {
const theme = useTheme()
const navigate = useNavigate()
+ const devices = useStore((state) => state.devices)
const virtuals = useStore((state) => state.virtuals)
const graphs = useStore((state) => state.graphs)
const graphsMulti = useStore((state) => state.graphsMulti)
const [fade] = useState(false)
const showMatrix = useStore((state) => state.showMatrix)
const setPixelGraphs = useStore((state) => state.setPixelGraphs)
- // const activateDevice = useStore((state) => state.activateDevice)
+ const activateDevice = useStore((state) => state.activateDevice)
useEffect(() => {
if (graphs && graphsMulti) {
setPixelGraphs(Object.keys(virtuals))
}
- }, [graphs, graphsMulti, setPixelGraphs])
+ }, [graphs, graphsMulti, setPixelGraphs, virtuals])
const handleEvent: GridEventListener<'rowClick'> = (params) =>
navigate(`/device/${params.row.id}`)
@@ -93,67 +219,35 @@ const DbDevices = () => {
renderCell: (params: GridRenderCellParams) => (
)
+ },
+ {
+ field: 'status',
+ headerName: 'Status',
+ width: 200,
+ align: 'left',
+ renderCell: (params: GridRenderCellParams) =>
+ devices[Object.keys(devices).find((d) => d === params.row.id) || '']
+ ?.online
+ ? virtuals[params.row.id]?.effect?.name
+ ? `Effect: ${virtuals[params.row.id]?.effect?.name}`
+ : 'Online'
+ : virtuals[params.row.id]?.effect?.name
+ ? `Effect: ${virtuals[params.row.id]?.effect?.name}`
+ : 'Offline'
+ },
+ {
+ field: 'actions',
+ headerName: 'Actions',
+ width: 300, // eslint-disable-next-line
+ renderCell: (params: GridRenderCellParams) => // eslint-disable-next-line
+ devices[Object.keys(devices).find((d) => d === params.row.id) || '']?.online // eslint-disable-next-line
+ ? (virtuals[params.row.id]?.effect.name // eslint-disable-next-line
+ ? () // eslint-disable-next-line
+ : ()) // eslint-disable-next-line
+ : virtuals[params.row.id]?.effect.name // eslint-disable-next-line
+ ? ()
+ : ( activateDevice(params.row.id)} />)
}
- // {
- // field: 'status',
- // headerName: 'Status',
- // width: 200,
- // renderCell: (params: GridRenderCellParams) =>
- // devices[Object.keys(devices).find((d) => d === params.row.id) || '']
- // ?.online
- // ? virtuals[params.row.id]?.effect.name
- // ? `Effect: ${virtuals[params.row.id]?.effect.name}`
- // : 'Online'
- // : 'Offline'
- // },
- // {
- // field: 'actions',
- // headerName: 'Actions',
- // width: 300,
- // renderCell: (params: GridRenderCellParams) =>
- // devices[Object.keys(devices).find((d) => d === params.row.id) || '']
- // ?.online ? (
- // virtuals[params.row.id]?.effect.name ? (
- // <>
- //
- //
- // >
- // ) : (
- // 'Online'
- // )
- // ) : (
- //
- // )
- // }
]
const rows: any = Object.values(virtuals).map((v: any) => ({
diff --git a/src/pages/Home/DbGlobalActions.tsx b/src/pages/Home/DbGlobalActions.tsx
index 8b66ca50..cf50ba09 100644
--- a/src/pages/Home/DbGlobalActions.tsx
+++ b/src/pages/Home/DbGlobalActions.tsx
@@ -1,5 +1,3 @@
-/* eslint-disable no-await-in-loop */
-/* eslint-disable no-plusplus */
import { useTheme, Stack, Box, Button } from '@mui/material'
import { useState } from 'react'
import BladeFrame from '../../components/SchemaForm/components/BladeFrame'
diff --git a/src/pages/Home/DbStats.tsx b/src/pages/Home/DbStats.tsx
index 9c94c0ca..65fff5e3 100644
--- a/src/pages/Home/DbStats.tsx
+++ b/src/pages/Home/DbStats.tsx
@@ -1,37 +1,36 @@
-/* eslint-disable prettier/prettier */
-import { useTheme, Stack } from '@mui/material';
-import BladeFrame from '../../components/SchemaForm/components/BladeFrame';
-import DbRow from './DbRow';
-import useStore from '../../store/useStore';
+import { useTheme, Stack } from '@mui/material'
+import BladeFrame from '../../components/SchemaForm/components/BladeFrame'
+import DbRow from './DbRow'
+import useStore from '../../store/useStore'
const DbStats = () => {
- const theme = useTheme();
- const config = useStore((state) => state.config);
- const devices = useStore((state) => state.devices);
- const virtuals = useStore((state) => state.virtuals);
- const scenes = useStore((state) => state.scenes);
- const devicesOnline = Object.keys(devices).filter((d) => devices[d].online);
+ const theme = useTheme()
+ const config = useStore((state) => state.config)
+ const devices = useStore((state) => state.devices)
+ const virtuals = useStore((state) => state.virtuals)
+ const scenes = useStore((state) => state.scenes)
+ const devicesOnline = Object.keys(devices).filter((d) => devices[d].online)
const virtualsReal = Object.keys(virtuals).filter(
(d) => !virtuals[d].is_device
- );
+ )
const pixelTotalOnline = Object.keys(devices)
.map((d) => devices[d].online && devices[d].config.pixel_count)
- .reduce((a, b) => a + b, 0);
+ .reduce((a, b) => a + b, 0)
const pixelTotal = Object.keys(devices)
.map((d) => devices[d].config.pixel_count)
- .reduce((a, b) => a + b, 0);
+ .reduce((a, b) => a + b, 0)
return (
@@ -47,20 +46,22 @@ const DbStats = () => {
Object.keys(e).length)
- .reduce((a: number, b: number) => a + b, 0)
- : 0)}
+ right={String(
+ Object.values(config.user_presets).length // eslint-disable-next-line
+ ? Object.values(config.user_presets).map((e: any) => Object.keys(e).length).reduce((a: number, b: number) => a + b, 0)
+ : 0
+ )}
/>
- );
-};
+ )
+}
-export default DbStats;
+export default DbStats
diff --git a/src/pages/Home/Gauge.tsx b/src/pages/Home/Gauge.tsx
index d4d01dbb..22c01e2b 100644
--- a/src/pages/Home/Gauge.tsx
+++ b/src/pages/Home/Gauge.tsx
@@ -1,4 +1,3 @@
-/* eslint-disable prettier/prettier */
import { useTheme } from '@mui/material/styles'
import { Box, CircularProgress, Typography, useMediaQuery } from '@mui/material'
@@ -8,13 +7,7 @@ export default function Gauge(props: any) {
const xSmallHeight = useMediaQuery('(max-height: 730px)')
const smallHeight = useMediaQuery('(max-height: 800px)')
const mediumHeight = useMediaQuery('(max-height: 900px)')
- const size = xSmallHeight
- ? 6
- : smallHeight
- ? 8
- : mediumHeight
- ? 10
- :12
+ const size = xSmallHeight ? 6 : smallHeight ? 8 : mediumHeight ? 10 : 12
return (
{current}
@@ -63,7 +56,7 @@ export default function Gauge(props: any) {
{unit}
diff --git a/src/pages/Home/Home.tsx b/src/pages/Home/Home.tsx
index ef978686..ef928379 100644
--- a/src/pages/Home/Home.tsx
+++ b/src/pages/Home/Home.tsx
@@ -1,6 +1,3 @@
-/* eslint-disable no-promise-executor-return */
-/* eslint-disable no-plusplus */
-/* eslint-disable no-await-in-loop */
import { useEffect, useState } from 'react'
import { useSnackbar } from 'notistack'
@@ -20,7 +17,7 @@ export default function Home() {
const scanForDevices = useStore((state) => state.scanForDevices)
const getDevices = useStore((state) => state.getDevices)
const getVirtuals = useStore((state) => state.getVirtuals)
- // eslint-disable-next-line @typescript-eslint/no-unused-vars, no-unused-vars
+
const [scanning, setScanning] = useState(-1)
const [lastFound, setLastFound] = useState([] as string[])
const features = useStore((state) => state.features)
diff --git a/src/pages/Integrations/IntegrationCard/IntegrationCardQLC.tsx b/src/pages/Integrations/IntegrationCard/IntegrationCardQLC.tsx
index 4776aad6..9de13516 100644
--- a/src/pages/Integrations/IntegrationCard/IntegrationCardQLC.tsx
+++ b/src/pages/Integrations/IntegrationCard/IntegrationCardQLC.tsx
@@ -1,7 +1,3 @@
-/* eslint-disable react/jsx-no-undef */
-/* eslint-disable no-console */
-/* eslint-disable @typescript-eslint/indent */
-/* eslint-disable prettier/prettier */
import { useState } from 'react'
import Card from '@mui/material/Card'
import Button from '@mui/material/Button'
@@ -68,12 +64,12 @@ const IntegrationCardQLC = ({ integration }: any) => {
integrations[integration].status === 3
? 'Connecting...'
: integrations[integration].status === 2
- ? 'Disconnecting'
- : integrations[integration].status === 1
- ? 'Connected'
- : integrations[integration].status === 0
- ? 'Disconnected'
- : 'Unknown'
+ ? 'Disconnecting'
+ : integrations[integration].status === 1
+ ? 'Connected'
+ : integrations[integration].status === 0
+ ? 'Disconnected'
+ : 'Unknown'
}`}
action={
) {
- return ;
-});
+ return
+})
Transition.defaultProps = {
- children: loading
,
-};
+ children: loading
+}
export const MuiMenuItem = React.forwardRef(
(props: any, ref: React.Ref) => {
- return ;
+ return
}
-);
+)
diff --git a/src/pages/Integrations/Spotify/SpotifyLoginRedirect.tsx b/src/pages/Integrations/Spotify/SpotifyLoginRedirect.tsx
index 1058fc34..111b8651 100644
--- a/src/pages/Integrations/Spotify/SpotifyLoginRedirect.tsx
+++ b/src/pages/Integrations/Spotify/SpotifyLoginRedirect.tsx
@@ -1,22 +1,28 @@
-/* eslint-disable no-extra-boolean-cast */
-/* eslint-disable no-return-assign */
-/* eslint-disable prettier/prettier */
import { useState, useEffect } from 'react'
-import isElectron from 'is-electron';
-import { Avatar, Dialog, Stack , CircularProgress } from '@mui/material'
+import isElectron from 'is-electron'
+import { Avatar, Dialog, Stack, CircularProgress } from '@mui/material'
import { CheckCircle } from '@mui/icons-material'
-import {
- finishAuth,
- refreshAuth
-} from '../../../utils/spotifyProxies'
+import { finishAuth, refreshAuth } from '../../../utils/spotifyProxies'
import logoAsset from '../../../assets/logo.png'
import BladeIcon from '../../../components/Icons/BladeIcon/BladeIcon'
+const baseURL = isElectron()
+ ? 'http://localhost:8888'
+ : window.location.href.split('/#')[0].replace(/\/+$/, '') ||
+ 'http://localhost:8888'
+const storedURL = window.localStorage.getItem('ledfx-host')
-const baseURL = isElectron() ? 'http://localhost:8888' : window.location.href.split('/#')[0].replace(/\/+$/, '') || 'http://localhost:8888';
-const storedURL = window.localStorage.getItem('ledfx-host');
-
-const Circle = () =>
+const Circle = () => (
+
+)
const SpotifyLoginRedirect = () => {
const [ready, setReady] = useState(false)
@@ -24,49 +30,89 @@ const SpotifyLoginRedirect = () => {
useEffect(() => {
finishAuth()
refreshAuth()
- localStorage.setItem('Spotify-Token', window.location.search.replace('?code=', ''))
- setTimeout(() => { setReady(true) }, 1500)
- setTimeout( () =>
- (window.location.href = `${
- process.env.NODE_ENV === 'production'
- ? storedURL || baseURL
- : 'http://localhost:3000'
- }/#/Integrations?`),
- 3000
+ localStorage.setItem(
+ 'Spotify-Token',
+ window.location.search.replace('?code=', '')
+ )
+ setTimeout(() => {
+ setReady(true)
+ }, 1500)
+ setTimeout(
+ () =>
+ (window.location.href = `${
+ process.env.NODE_ENV === 'production'
+ ? storedURL || baseURL
+ : 'http://localhost:3000'
+ }/#/Integrations?`),
+ 3000
) // Redirect to homepage after 3 sec
}, [])
-
- return (
+ )
}
-export default SpotifyLoginRedirect;
+export default SpotifyLoginRedirect
diff --git a/src/pages/Integrations/Spotify/SpotifyScreen/SpotifyScreen.props.tsx b/src/pages/Integrations/Spotify/SpotifyScreen/SpotifyScreen.props.tsx
index 9a044403..236da8ea 100644
--- a/src/pages/Integrations/Spotify/SpotifyScreen/SpotifyScreen.props.tsx
+++ b/src/pages/Integrations/Spotify/SpotifyScreen/SpotifyScreen.props.tsx
@@ -1,33 +1,19 @@
import React from 'react'
-import { Settings } from '@mui/icons-material'
import { TransitionProps } from '@mui/material/transitions'
import { MenuItem, Slide } from '@mui/material'
export interface SpotifyScreenProps {
icon: React.ReactElement
- startIcon: React.ReactElement
- label: string
- type: string
+ startIcon?: React.ReactElement
+ label?: string
+ type?: string
className: string
- // eslint-disable-next-line prettier/prettier
+ // eslint-disable-next-line
color: 'primary' | 'inherit' | 'error' | 'success' | 'warning' | 'info' | 'secondary' | undefined;
variant: 'outlined' | 'text' | 'contained' | undefined
- innerKey: string
+ innerKey?: string
disabled: boolean
- size: 'small' | 'medium' | 'large' | undefined
-}
-
-export const SpotifyScreenDefaultProps = {
- icon: ,
- startIcon: undefined,
- label: '',
- type: 'button',
- className: undefined,
- color: 'primary',
- variant: 'contained',
- innerKey: undefined,
- disabled: false,
- size: 'small'
+ size?: 'small' | 'medium' | 'large' | undefined
}
export const Transition = React.forwardRef(function Transition(
@@ -37,10 +23,6 @@ export const Transition = React.forwardRef(function Transition(
return
})
-Transition.defaultProps = {
- children: loading
-}
-
export const MuiMenuItem = React.forwardRef(
(props: any, ref: React.Ref) => {
return
diff --git a/src/pages/Integrations/Spotify/SpotifyScreen/SpotifyScreen.tsx b/src/pages/Integrations/Spotify/SpotifyScreen/SpotifyScreen.tsx
index 8fe74814..7baa5806 100644
--- a/src/pages/Integrations/Spotify/SpotifyScreen/SpotifyScreen.tsx
+++ b/src/pages/Integrations/Spotify/SpotifyScreen/SpotifyScreen.tsx
@@ -13,7 +13,6 @@ import { Settings, NavigateBefore } from '@mui/icons-material'
import isElectron from 'is-electron'
import {
MuiMenuItem,
- SpotifyScreenDefaultProps,
SpotifyScreenProps,
Transition
} from './SpotifyScreen.props'
@@ -26,14 +25,14 @@ import SpPlaylist from '../../../../components/Integrations/Spotify/Widgets/Spot
import { SpotifyStateContext } from '../../../../components/Integrations/Spotify/SpotifyProvider'
export default function SpotifyScreen({
+ className,
+ innerKey,
icon = ,
startIcon,
label = '',
- type,
- className,
+ type = 'button',
color = 'primary',
variant = 'contained',
- innerKey,
disabled = false,
size = 'small'
}: SpotifyScreenProps) {
@@ -125,5 +124,3 @@ export default function SpotifyScreen({
>
)
}
-
-SpotifyScreen.defaultProps = SpotifyScreenDefaultProps
diff --git a/src/pages/Login/LoginRedirect.tsx b/src/pages/Login/LoginRedirect.tsx
index 022424d9..959f323a 100644
--- a/src/pages/Login/LoginRedirect.tsx
+++ b/src/pages/Login/LoginRedirect.tsx
@@ -51,7 +51,6 @@ const LoginRedirect = () => {
}, 2000)
})
.catch((err) => {
- // eslint-disable-next-line no-console
console.log(err)
setText('An error occurred, please see the developer console.')
})
diff --git a/src/pages/Pages.tsx b/src/pages/Pages.tsx
index eb9e8b02..bed796db 100644
--- a/src/pages/Pages.tsx
+++ b/src/pages/Pages.tsx
@@ -1,4 +1,3 @@
-/* eslint-disable react/jsx-no-useless-fragment */
import {
HashRouter as Router,
BrowserRouter,
@@ -62,7 +61,7 @@ const Routings = ({ handleWs }: any) => {
window.location.reload()
})
if (isElect) {
- useHotkeys(['ctrl+alt+l'], () => {
+ useHotkeys(['ctrl+alt+l'], () => { // eslint-disable-line
window.localStorage.setItem('lock', 'activated')
window.location.reload()
})
@@ -133,7 +132,7 @@ const Routings = ({ handleWs }: any) => {
:
}
/>
diff --git a/src/pages/Scenes/ScenesPlaylist.tsx b/src/pages/Scenes/ScenesPlaylist.tsx
index c393c45d..d410ac2a 100644
--- a/src/pages/Scenes/ScenesPlaylist.tsx
+++ b/src/pages/Scenes/ScenesPlaylist.tsx
@@ -106,7 +106,7 @@ export default function ScenesPlaylist({
headerName: 'Remove',
width: 120,
renderCell: (params: GridRenderCellParams) => {
- const removeScene2PL = useStore((state) => state.removeScene2PL)
+ const removeScene2PL = useStore((state) => state.removeScene2PL) // eslint-disable-line
return (