diff --git a/src/fireedge/src/client/components/Cards/SelectCard/styles.js b/src/fireedge/src/client/components/Cards/SelectCard/styles.js index fd71c00464..411a33bf84 100644 --- a/src/fireedge/src/client/components/Cards/SelectCard/styles.js +++ b/src/fireedge/src/client/components/Cards/SelectCard/styles.js @@ -35,11 +35,13 @@ export default makeStyles(theme => ({ overflow: 'hidden', position: 'relative', '& img': { + top: 0, + left: 0, width: '100%', + height: '100%', + objectFit: 'cover', position: 'absolute', - top: '50%', - left: '50%', - transform: 'translate(-50%, -50%)' + userSelect: 'none' }, transition: theme.transitions.create('filter', { duration: '0.2s' }), filter: ({ isSelected, disableFilterImage }) => { diff --git a/src/fireedge/src/client/components/DebugLog/filters.js b/src/fireedge/src/client/components/DebugLog/filters.js new file mode 100644 index 0000000000..ee6efa9261 --- /dev/null +++ b/src/fireedge/src/client/components/DebugLog/filters.js @@ -0,0 +1,108 @@ +import React, { memo } from 'react' +import PropTypes from 'prop-types' + +import { makeStyles, Paper, Divider } from '@material-ui/core' +import { ToggleButton, ToggleButtonGroup } from '@material-ui/lab' + +import { DEBUG_LEVEL } from 'client/constants' + +const useStyles = makeStyles(theme => ({ + root: { + display: 'flex', + border: `1px solid ${theme.palette.divider}`, + flexWrap: 'wrap', + marginBottom: '0.8em' + }, + grouped: { + margin: theme.spacing(0.5), + border: 'none', + '&:not(:first-child)': { + borderRadius: theme.shape.borderRadius + }, + '&:first-child': { + borderRadius: theme.shape.borderRadius + } + } +})) + +const Filters = memo(({ log, filters, setFilters }) => { + const classes = useStyles() + + const commands = Object.keys(log) + + const handleFilterCommands = (_, filterCommand) => { + setFilters(prev => ({ ...prev, command: filterCommand })) + } + + const handleFilterSeverity = (_, filterCommand) => { + setFilters(prev => ({ ...prev, severity: filterCommand })) + } + + return ( + + {/* SEVERITY FILTER */} + + {Object.values(DEBUG_LEVEL).map(severity => ( + + {severity} + + ))} + + + + + {/* COMMANDS FILTER */} + {commands.length > 1 && ( + + {commands?.map(command => ( + + {command} + + ))} + + )} + + ) +}, (prev, next) => + Object.keys(prev.log).length === Object.keys(next.log).length && + prev.filters.command === next.filters.command && + prev.filters.severity === next.filters.severity +) + +Filters.propTypes = { + filters: PropTypes.shape({ + command: PropTypes.string, + severity: PropTypes.string + }), + log: PropTypes.object.isRequired, + setFilters: PropTypes.func +} + +Filters.defaultProps = { + filters: { + command: undefined, + severity: undefined + }, + log: {}, + setFilters: () => undefined +} + +Filters.displayName = 'Filters' + +export default Filters diff --git a/src/fireedge/src/client/components/DebugLog/index.js b/src/fireedge/src/client/components/DebugLog/index.js index 6f3b3b44ad..ba731d32fc 100644 --- a/src/fireedge/src/client/components/DebugLog/index.js +++ b/src/fireedge/src/client/components/DebugLog/index.js @@ -1,13 +1,24 @@ import React, { useEffect, useState, memo } from 'react' import PropTypes from 'prop-types' -import { makeStyles, Box } from '@material-ui/core' +import { makeStyles } from '@material-ui/core' import AutoScrollBox from 'client/components/AutoScrollBox' -import Message from 'client/components/DebugLog/message' -import { DEBUG_LEVEL } from 'client/constants' +import MessageList from 'client/components/DebugLog/messagelist' +import Filters from 'client/components/DebugLog/filters' +import * as LogUtils from 'client/components/DebugLog/utils' const debugLogStyles = makeStyles(theme => ({ root: { + display: 'flex', + flexFlow: 'column', + height: '100%' + }, + containerScroll: { + width: '100%', + flexGrow: 1, + overflow: 'auto', + borderRadius: 5, + backgroundColor: '#1d1f21', fontSize: '1.1em', wordBreak: 'break-word', '&::-webkit-scrollbar': { @@ -23,62 +34,36 @@ const debugLogStyles = makeStyles(theme => ({ } })) -const DebugLog = memo(({ uuid, socket, logDefault }) => { +const DebugLog = memo(({ uuid, socket, logDefault, title }) => { const classes = debugLogStyles() + const [log, setLog] = useState(logDefault) - useEffect(() => { - uuid && socket.on((socketData = {}) => { - const { id, data, command, commandId } = socketData + const [filters, setFilters] = useState(() => ({ + command: undefined, + severity: undefined + })) - id === uuid && setLog(prev => ({ - ...prev, - [command]: { - [commandId]: [...(prev?.[command]?.[commandId] ?? []), data] - } - })) + useEffect(() => { + uuid && socket?.on((socketData = {}) => { + socketData.id === uuid && + setLog(prevLog => LogUtils.concatNewMessageToLog(prevLog, socketData)) }) - return () => uuid && socket.off() + return () => uuid && socket?.off() }, []) return ( - - - {Object.entries(log)?.map(([command, entries]) => - Object.entries(entries)?.map(([commandId, messages]) => - messages?.map((data, index) => { - const key = `${index}-${command}-${commandId}` +
+ {title} - try { - const { timestamp, severity, message } = JSON.parse(data) - const decryptMessage = atob(message) + - return ( - - ) - } catch { - const severity = data.includes(DEBUG_LEVEL.ERROR) - ? DEBUG_LEVEL.ERROR - : data.includes(DEBUG_LEVEL.INFO) - ? DEBUG_LEVEL.INFO - : data.includes(DEBUG_LEVEL.WARN) - ? DEBUG_LEVEL.WARN - : DEBUG_LEVEL.DEBUG - - return ( - - ) - } - }) - ) - )} - - +
+ + + +
+
) }, (prev, next) => prev.uuid === next.uuid) @@ -88,7 +73,11 @@ DebugLog.propTypes = { on: PropTypes.func.isRequired, off: PropTypes.func.isRequired }).isRequired, - logDefault: PropTypes.object + logDefault: PropTypes.object, + title: PropTypes.oneOfType([ + PropTypes.element, + PropTypes.string + ]) } DebugLog.defaultProps = { @@ -97,9 +86,12 @@ DebugLog.defaultProps = { on: () => undefined, off: () => undefined }, - logDefault: {} + logDefault: {}, + title: null } DebugLog.displayName = 'DebugLog' export default DebugLog + +export { LogUtils } diff --git a/src/fireedge/src/client/components/DebugLog/messagelist.js b/src/fireedge/src/client/components/DebugLog/messagelist.js new file mode 100644 index 0000000000..bc5e8820f7 --- /dev/null +++ b/src/fireedge/src/client/components/DebugLog/messagelist.js @@ -0,0 +1,46 @@ +import * as React from 'react' +import PropTypes from 'prop-types' + +import Message from 'client/components/DebugLog/message' +import { getMessageInfo } from 'client/components/DebugLog/utils' + +const MessageList = ({ log = {}, filters = {} }) => + Object.entries(log)?.map(([command, entries]) => ( + // filter by command + (!filters.command || filters.command.includes(command)) && ( + Object.entries(entries)?.map(([commandId, messages]) => + Array.isArray(messages) && messages?.map((data, index) => { + const { severity, ...messageInfo } = getMessageInfo(data) + + // filter by severity + if (filters.severity && filters.severity !== severity) return null + + const key = `${index}-${command}-${commandId}` + + return ( + + ) + }) + ) + ) + )) + +MessageList.propTypes = { + filters: PropTypes.shape({ + command: PropTypes.string, + severity: PropTypes.string + }).isRequired, + log: PropTypes.object +} + +MessageList.defaultProps = { + filters: { + command: undefined, + severity: undefined + }, + log: undefined +} + +MessageList.displayName = 'MessageList' + +export default MessageList diff --git a/src/fireedge/src/client/components/DebugLog/utils.js b/src/fireedge/src/client/components/DebugLog/utils.js new file mode 100644 index 0000000000..a671e7b3c8 --- /dev/null +++ b/src/fireedge/src/client/components/DebugLog/utils.js @@ -0,0 +1,55 @@ +import { DEBUG_LEVEL } from 'client/constants' + +/** + * Returns severity type if message text includes debug level + * @param {string} data - Message text + * @returns {string} Severity type (debug level) + */ +export const getSeverityFromData = data => + data.includes(DEBUG_LEVEL.ERROR) + ? DEBUG_LEVEL.ERROR + : data.includes(DEBUG_LEVEL.INFO) + ? DEBUG_LEVEL.INFO + : data.includes(DEBUG_LEVEL.WARN) + ? DEBUG_LEVEL.WARN + : DEBUG_LEVEL.DEBUG + +/** + * Returns the message information as json + * @param {string} data - Message information data as string + * @returns {object} Message data + */ +export const getMessageInfo = (data = '') => { + try { + const { message, timestamp, severity } = JSON.parse(data) + const decryptMessage = atob(message) + + return { timestamp, severity, message: decryptMessage } + } catch { + const severity = getSeverityFromData(data) + + return { severity, message: data } + } +} + +/** + * Returns a new log with a new message concatenated + * @param {array} log - Current log data + * @param {object} message - New message to concat + * @param {string} message.command - Message's command: create, configure, etc + * @param {string} message.commandId - Message's command id + * @param {string} message.data - Message's information data + * @returns {array} New log + */ +export const concatNewMessageToLog = (log, message = {}) => { + if (typeof message !== 'object') return log + + const { data, command, commandId } = message + + return { + ...log, + [command]: { + [commandId]: [...(log?.[command]?.[commandId] ?? []), data] + } + } +} diff --git a/src/fireedge/src/client/containers/Provisions/DialogInfo/log.js b/src/fireedge/src/client/containers/Provisions/DialogInfo/log.js index ee1a33a51e..9b4ed1f7e6 100644 --- a/src/fireedge/src/client/containers/Provisions/DialogInfo/log.js +++ b/src/fireedge/src/client/containers/Provisions/DialogInfo/log.js @@ -4,44 +4,39 @@ import PropTypes from 'prop-types' import { LinearProgress } from '@material-ui/core' import { useProvision, useFetch, useSocket } from 'client/hooks' -import DebugLog from 'client/components/DebugLog' +import DebugLog, { LogUtils } from 'client/components/DebugLog' import * as Types from 'client/types/provision' -const Log = React.memo(({ hidden, data: { ID } }) => { +const Log = React.memo(({ hidden, data: { ID: id } }) => { const { getProvision } = useSocket() const { getProvisionLog } = useProvision() - const { data: provisionLog, fetchRequest, loading } = useFetch(getProvisionLog) + + const { + data: { uuid = id, log } = {}, + fetchRequest, + loading + } = useFetch(getProvisionLog) React.useEffect(() => { - !hidden && fetchRequest({ id: ID }) - }, [ID]) + !hidden && fetchRequest({ id }) + }, [id]) React.useEffect(() => { - (!provisionLog && !hidden) && fetchRequest({ id: ID }) + (!log && !hidden) && fetchRequest({ id }) }, [hidden]) - const log = provisionLog?.log?.reduce((res, dataLog) => { - try { - const json = JSON.parse(dataLog) - const { data, command, commandId } = json - - return { - ...res, - [command]: { - [commandId]: [...(res?.[command]?.[commandId] ?? []), data] - } - } - } catch { return res } - }, {}) + const parsedLog = React.useMemo(() => + log + ?.map(entry => { + try { return JSON.parse(entry) } catch { return entry } + }) + ?.reduce(LogUtils.concatNewMessageToLog, {}) + , [loading]) return loading ? ( ) : ( - + ) }, (prev, next) => prev.hidden === next.hidden && prev.data === next.data) diff --git a/src/fireedge/src/client/containers/Provisions/Form/Create/index.js b/src/fireedge/src/client/containers/Provisions/Form/Create/index.js index f268bad0eb..4ec728bed4 100644 --- a/src/fireedge/src/client/containers/Provisions/Form/Create/index.js +++ b/src/fireedge/src/client/containers/Provisions/Form/Create/index.js @@ -8,18 +8,18 @@ import { yupResolver } from '@hookform/resolvers' import FormStepper from 'client/components/FormStepper' import Steps from 'client/containers/Provisions/Form/Create/Steps' -import FormCreateStyles from 'client/containers/Provisions/Form/Create/styles' +import formCreateStyles from 'client/containers/Provisions/Form/Create/styles' import DebugLog from 'client/components/DebugLog' import { useProvision, useSocket, useFetch } from 'client/hooks' import { PATH } from 'client/router/provision' import { set, mapUserInputs } from 'client/utils' -import { Tr, Translate } from 'client/components/HOC' +import { Translate } from 'client/components/HOC' import { T } from 'client/constants' function ProvisionCreateForm () { - const classes = FormCreateStyles() + const classes = formCreateStyles() const history = useHistory() const [uuid, setUuid] = useState(undefined) @@ -71,19 +71,22 @@ function ProvisionCreateForm () { if (uuid) { return ( -
-
- history.push(PATH.PROVISIONS.LIST)} - > - - - - - -
- -
+ + history.push(PATH.PROVISIONS.LIST)} + > + + + + + + + )} + /> ) }