@iobroker/gui-components 10.3.16 → 10.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -1
- package/build/Components/AnimatedIcons/IconCopyToClipboard.d.ts +25 -0
- package/build/Components/AnimatedIcons/IconCopyToClipboard.js +84 -0
- package/build/Components/AnimatedIcons/IconCopyToClipboard.js.map +1 -0
- package/build/Components/AnimatedIcons/IconFilter.d.ts +23 -0
- package/build/Components/AnimatedIcons/IconFilter.js +26 -0
- package/build/Components/AnimatedIcons/IconFilter.js.map +1 -0
- package/build/Components/AnimatedIcons/IconFolder.d.ts +6 -0
- package/build/Components/AnimatedIcons/IconFolder.js +2 -1
- package/build/Components/AnimatedIcons/IconFolder.js.map +1 -1
- package/build/Components/AnimatedIcons/IconThemeMode.d.ts +22 -0
- package/build/Components/AnimatedIcons/IconThemeMode.js +32 -0
- package/build/Components/AnimatedIcons/IconThemeMode.js.map +1 -0
- package/build/Components/AnimatedIcons/IconUpload.d.ts +24 -0
- package/build/Components/AnimatedIcons/IconUpload.js +37 -0
- package/build/Components/AnimatedIcons/IconUpload.js.map +1 -0
- package/build/Components/AnimatedIcons/common.d.ts +2 -0
- package/build/Components/AnimatedIcons/common.js +64 -5
- package/build/Components/AnimatedIcons/common.js.map +1 -1
- package/build/Components/ColorPicker.js +4 -3
- package/build/Components/ColorPicker.js.map +1 -1
- package/build/Components/FileBrowser.d.ts +6 -0
- package/build/Components/FileBrowser.js +54 -12
- package/build/Components/FileBrowser.js.map +1 -1
- package/build/Components/FileViewer.js +3 -2
- package/build/Components/FileViewer.js.map +1 -1
- package/build/Components/ObjectBrowser/ObjectBrowserClass.d.ts +6 -0
- package/build/Components/ObjectBrowser/ObjectBrowserClass.js +66 -6
- package/build/Components/ObjectBrowser/ObjectBrowserClass.js.map +1 -1
- package/build/Components/ObjectBrowser/contextMenu.js +3 -2
- package/build/Components/ObjectBrowser/contextMenu.js.map +1 -1
- package/build/Components/ObjectBrowser/renderLeaf.js +55 -76
- package/build/Components/ObjectBrowser/renderLeaf.js.map +1 -1
- package/build/Components/ObjectBrowser/rowAnimation.d.ts +25 -1
- package/build/Components/ObjectBrowser/rowAnimation.js +46 -19
- package/build/Components/ObjectBrowser/rowAnimation.js.map +1 -1
- package/build/Components/ObjectBrowser/skeleton.d.ts +15 -0
- package/build/Components/ObjectBrowser/skeleton.js +106 -0
- package/build/Components/ObjectBrowser/skeleton.js.map +1 -0
- package/build/Components/ObjectBrowser/styles.js +16 -11
- package/build/Components/ObjectBrowser/styles.js.map +1 -1
- package/build/Components/ObjectBrowser/toolbar.js +18 -14
- package/build/Components/ObjectBrowser/toolbar.js.map +1 -1
- package/build/Components/ObjectBrowser/utils.d.ts +2 -0
- package/build/Components/ObjectBrowser/utils.js +2 -0
- package/build/Components/ObjectBrowser/utils.js.map +1 -1
- package/build/Components/ToggleThemeMenu.js +11 -8
- package/build/Components/ToggleThemeMenu.js.map +1 -1
- package/build/Components/TreeTable.d.ts +16 -0
- package/build/Components/TreeTable.js +106 -18
- package/build/Components/TreeTable.js.map +1 -1
- package/build/Dialogs/ComplexCron.js +3 -2
- package/build/Dialogs/ComplexCron.js.map +1 -1
- package/build/Dialogs/Error.js +3 -2
- package/build/Dialogs/Error.js.map +1 -1
- package/build/index.d.ts +4 -0
- package/build/index.js +4 -0
- package/build/index.js.map +1 -1
- package/package.json +5 -5
|
@@ -3,11 +3,12 @@
|
|
|
3
3
|
import React, { Component } from 'react';
|
|
4
4
|
import { TextField, Button, Dialog, DialogActions, DialogContent, DialogTitle, IconButton } from '@mui/material';
|
|
5
5
|
// Icons
|
|
6
|
-
import { Close as CloseIcon, Save as SaveIcon, Brightness6 as Brightness5Icon
|
|
6
|
+
import { Close as CloseIcon, Save as SaveIcon, Brightness6 as Brightness5Icon } from '@mui/icons-material';
|
|
7
7
|
import { IconNoIcon } from '../icons/IconNoIcon';
|
|
8
8
|
import { withWidth } from './withWidth';
|
|
9
9
|
import { Utils } from './Utils';
|
|
10
10
|
import { Icon } from './Icon';
|
|
11
|
+
import { IconCopyToClipboard } from './AnimatedIcons/IconCopyToClipboard';
|
|
11
12
|
const styles = {
|
|
12
13
|
dialog: {
|
|
13
14
|
height: '100%',
|
|
@@ -235,7 +236,7 @@ export class FileViewerClass extends Component {
|
|
|
235
236
|
e.stopPropagation();
|
|
236
237
|
e.preventDefault();
|
|
237
238
|
Utils.copyToClipboard(this.state.text || this.state.code || '');
|
|
238
|
-
}, startIcon: React.createElement(
|
|
239
|
+
}, startIcon: React.createElement(IconCopyToClipboard, null) }, this.props.t('Copy content'))) : null,
|
|
239
240
|
this.state.editing ? (React.createElement(Button, { color: "grey", disabled: this.state.editingValue === this.state.code ||
|
|
240
241
|
this.state.editingValue === this.state.text, variant: "contained", onClick: () => this.onSave(), startIcon: React.createElement(SaveIcon, null) }, this.props.t('Save'))) : null,
|
|
241
242
|
React.createElement(Button, { variant: "contained", onClick: () => this.props.onClose(), color: "primary", startIcon: React.createElement(CloseIcon, null) }, this.props.t('Close')))));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileViewer.js","sourceRoot":"./src/","sources":["Components/FileViewer.tsx"],"names":[],"mappings":"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","sourcesContent":["// File viewer in adapter-react does not support write\n// import { Buffer } from 'buffer';\nimport React, { Component, type JSX } from 'react';\n\nimport { TextField, Button, Dialog, DialogActions, DialogContent, DialogTitle, IconButton } from '@mui/material';\n\n// Icons\nimport {\n Close as CloseIcon,\n Save as SaveIcon,\n Brightness6 as Brightness5Icon,\n ContentCopy as CopyIcon,\n} from '@mui/icons-material';\n\nimport type { Connection } from '@iobroker/socket-client';\n\nimport { IconNoIcon } from '../icons/IconNoIcon';\nimport { withWidth } from './withWidth';\nimport { Utils } from './Utils';\nimport type { ThemeType, Translate } from '../types';\nimport { Icon } from './Icon';\n\nconst styles: Record<string, React.CSSProperties> = {\n dialog: {\n height: '100%',\n },\n paper: {\n height: 'calc(100% - 64px)',\n },\n content: {\n textAlign: 'center',\n },\n textarea: {\n width: '100%',\n height: '100%',\n },\n img: {\n width: 'auto',\n height: 'calc(100% - 5px)',\n objectFit: 'contain',\n },\n dialogTitle: {\n justifyContent: 'space-between',\n display: 'flex',\n },\n};\n\nexport const EXTENSIONS = {\n images: ['png', 'jpg', 'svg', 'jpeg', 'bmp', 'gif', 'apng', 'avif', 'webp', 'ico'],\n code: ['js', 'json', 'json5', 'md'],\n txt: ['log', 'txt', 'html', 'css', 'xml', 'ics', 'csv'],\n audio: ['mp3', 'wav', 'ogg', 'acc'],\n video: ['mp4', 'mov', 'avi'],\n};\n\nfunction bufferToBase64(buffer: Buffer, isFull?: boolean): string {\n let binary = '';\n const bytes = new Uint8Array((buffer as unknown as { data: number[]; type: 'Buffer' })?.data || buffer);\n const len = bytes.byteLength;\n for (let i = 0; i < len && (isFull || i < 50); i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return window.btoa(binary);\n}\n\nexport interface FileViewerProps {\n /** Translation function */\n t: Translate;\n /** Callback when the viewer is closed. */\n onClose: () => void;\n /** The URL (file path) to the file to be displayed. */\n href: string;\n formatEditFile?: string;\n socket: Connection;\n setStateBackgroundImage: () => void;\n themeType: ThemeType;\n getStyleBackgroundImage: () => React.CSSProperties | null;\n /** Flag is the js-controller support subscribe on file */\n supportSubscribes?: boolean;\n}\n\nexport interface FileViewerState {\n text: string | null;\n code: string | null;\n ext: string | null;\n editing: boolean;\n editingValue: string | null;\n copyPossible: boolean;\n forceUpdate: number;\n changed: boolean;\n imgError: boolean;\n}\n\nexport class FileViewerClass extends Component<FileViewerProps, FileViewerState> {\n private timeout: ReturnType<typeof setTimeout> | null = null;\n\n constructor(props: FileViewerProps) {\n super(props);\n const ext = Utils.getFileExtension(props.href);\n\n this.state = {\n text: null,\n code: null,\n ext,\n // File viewer in adapter-react does not support write\n editing: /* !!this.props.formatEditFile || */ false,\n editingValue: null,\n copyPossible: !!ext && (EXTENSIONS.code.includes(ext) || EXTENSIONS.txt.includes(ext)),\n forceUpdate: Date.now(),\n changed: false,\n imgError: false,\n };\n }\n\n readFile(): void {\n if (this.props.href) {\n const parts = this.props.href.split('/');\n parts.splice(0, 2);\n const adapter = parts[0];\n const name = parts.splice(1).join('/');\n\n this.props.socket\n .readFile(adapter, name)\n .then((data: { file: string | Buffer; mimeType: string }) => {\n let fileData: string | Buffer = '';\n if (data.file !== undefined) {\n fileData = (data as { file: string; mimeType: string }).file;\n }\n\n const newState: Partial<FileViewerState> = {\n copyPossible: this.state.copyPossible,\n ext: this.state.ext,\n };\n // try to detect valid extension\n if ((fileData as unknown as { data: Buffer; type: string }).type === 'Buffer') {\n if (name.toLowerCase().endsWith('.json5')) {\n newState.ext = 'json5';\n newState.copyPossible = true;\n try {\n fileData = atob(bufferToBase64(fileData as unknown as Buffer, true));\n } catch {\n console.error('Cannot convert base64 to string');\n fileData = '';\n }\n } else {\n const ext = Utils.detectMimeType(bufferToBase64(fileData as unknown as Buffer));\n if (ext) {\n newState.ext = ext;\n newState.copyPossible = EXTENSIONS.code.includes(ext) || EXTENSIONS.txt.includes(ext);\n }\n }\n }\n\n if (newState.copyPossible) {\n if (newState.ext && EXTENSIONS.txt.includes(newState.ext)) {\n newState.text = fileData;\n newState.editingValue = fileData;\n } else if (newState.ext && EXTENSIONS.code.includes(newState.ext)) {\n newState.code = fileData;\n newState.editingValue = fileData;\n }\n }\n\n this.setState(newState as FileViewerState);\n })\n .catch(e => window.alert(`Cannot read file: ${e}`));\n }\n }\n\n componentDidMount(): void {\n this.readFile();\n\n const parts = this.props.href.split('/');\n parts.splice(0, 2);\n const adapter = parts[0];\n const name = parts.splice(1).join('/');\n\n if (this.props.supportSubscribes) {\n this.props.socket\n .subscribeFiles(adapter, name, this.onFileChanged)\n .catch(e => window.alert(`Cannot subscribe on file: ${e}`));\n }\n }\n\n componentWillUnmount(): void {\n if (this.timeout) {\n clearTimeout(this.timeout);\n this.timeout = null;\n }\n const parts = this.props.href.split('/');\n parts.splice(0, 2);\n const adapter = parts[0];\n const name = parts.splice(1).join('/');\n if (this.props.supportSubscribes) {\n this.props.socket.unsubscribeFiles(adapter, name, this.onFileChanged);\n }\n }\n\n onFileChanged = (_id: string, _fileName: string, size: number | null): void => {\n if (!this.state.changed) {\n if (this.timeout) {\n clearTimeout(this.timeout);\n }\n this.timeout = setTimeout(() => {\n this.timeout = null;\n if (size === null) {\n window.alert('Show file was deleted!');\n } else if (this.state.text !== null || this.state.code !== null) {\n this.readFile();\n } else {\n this.setState({ forceUpdate: Date.now() });\n }\n }, 300);\n }\n };\n\n getEditorOrViewer(): JSX.Element {\n return (\n <TextField\n variant=\"standard\"\n style={styles.textarea}\n multiline\n value={this.state.editingValue || this.state.code || this.state.text}\n // onChange={newValue => this.setState({ editingValue: newValue, changed: true })}\n slotProps={{\n htmlInput: {\n readOnly: !this.state.editing,\n },\n }}\n />\n );\n }\n\n getContent(): React.JSX.Element | null {\n if (this.state.ext && EXTENSIONS.images.includes(this.state.ext)) {\n if (this.state.imgError) {\n return <IconNoIcon style={{ ...styles.img, ...this.props.getStyleBackgroundImage() }} />;\n }\n return (\n <Icon\n onError={e => {\n (e.target as HTMLImageElement).onerror = null;\n this.setState({ imgError: true });\n }}\n style={{ ...styles.img, ...this.props.getStyleBackgroundImage() }}\n src={`${this.props.href}?ts=${this.state.forceUpdate}`}\n alt={this.props.href}\n />\n );\n }\n if (this.state.ext && EXTENSIONS.audio.includes(this.state.ext)) {\n return (\n <div\n style={{\n width: '100%',\n height: '100%',\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n }}\n >\n <audio\n style={{ width: '100%' }}\n src={this.props.href}\n controls\n ></audio>\n </div>\n );\n }\n if (this.state.ext && EXTENSIONS.video.includes(this.state.ext)) {\n return (\n <div\n style={{\n width: '100%',\n height: '100%',\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n }}\n >\n <video\n style={{ width: '100%', height: '100%' }}\n controls\n >\n <source\n src={this.props.href}\n type={`video/${this.state.ext}`}\n />\n </video>\n </div>\n );\n }\n if (this.state.code !== null || this.state.text !== null || this.state.editing) {\n // File viewer in adapter-react does not support write\n // return <Editor\n // mode={this.getEditFile(this.props.formatEditFile)}\n // themeType={this.props.themeType}\n // value={this.state.editingValue || this.state.code || this.state.text}\n // onChange={this.state.editing ? newValue => this.setState({ editingValue: newValue, changed: true }) : undefined}\n // />;\n return this.getEditorOrViewer();\n }\n return null;\n }\n\n // eslint-disable-next-line class-methods-use-this\n onSave(): void {\n // Do nothing as the file viewer in adapter-react does not support writing\n }\n\n render(): JSX.Element {\n return (\n <Dialog\n sx={{\n '&.MuiDialog-scrollPaper': styles.dialog,\n '& .MuiDialog-paper': styles.paper,\n }}\n scroll=\"paper\"\n open={!!this.props.href}\n onClose={() => this.props.onClose()}\n fullWidth\n maxWidth=\"xl\"\n aria-labelledby=\"ar_dialog_file_view_title\"\n >\n <div style={styles.dialogTitle}>\n <DialogTitle id=\"ar_dialog_file_view_title\">{`${this.props.t(this.state.editing ? 'Edit' : 'View')}: ${this.props.href}`}</DialogTitle>\n {this.state.ext && EXTENSIONS.images.includes(this.state.ext) && (\n <div>\n <IconButton\n size=\"large\"\n color=\"inherit\"\n onClick={this.props.setStateBackgroundImage}\n >\n <Brightness5Icon />\n </IconButton>\n </div>\n )}\n </div>\n <DialogContent style={styles.content}>{this.getContent()}</DialogContent>\n <DialogActions>\n {this.state.copyPossible ? (\n <Button\n color=\"grey\"\n onClick={e => {\n e.stopPropagation();\n e.preventDefault();\n Utils.copyToClipboard(this.state.text || this.state.code || '');\n }}\n startIcon={<CopyIcon />}\n >\n {this.props.t('Copy content')}\n </Button>\n ) : null}\n {this.state.editing ? (\n <Button\n color=\"grey\"\n disabled={\n this.state.editingValue === this.state.code ||\n this.state.editingValue === this.state.text\n }\n variant=\"contained\"\n onClick={() => this.onSave()}\n startIcon={<SaveIcon />}\n >\n {this.props.t('Save')}\n </Button>\n ) : null}\n <Button\n variant=\"contained\"\n onClick={() => this.props.onClose()}\n color=\"primary\"\n startIcon={<CloseIcon />}\n >\n {this.props.t('Close')}\n </Button>\n </DialogActions>\n </Dialog>\n );\n }\n}\nexport const FileViewer = withWidth()(FileViewerClass);\n"]}
|
|
1
|
+
{"version":3,"file":"FileViewer.js","sourceRoot":"./src/","sources":["Components/FileViewer.tsx"],"names":[],"mappings":"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","sourcesContent":["// File viewer in adapter-react does not support write\n// import { Buffer } from 'buffer';\nimport React, { Component, type JSX } from 'react';\n\nimport { TextField, Button, Dialog, DialogActions, DialogContent, DialogTitle, IconButton } from '@mui/material';\n\n// Icons\nimport { Close as CloseIcon, Save as SaveIcon, Brightness6 as Brightness5Icon } from '@mui/icons-material';\n\nimport type { Connection } from '@iobroker/socket-client';\n\nimport { IconNoIcon } from '../icons/IconNoIcon';\nimport { withWidth } from './withWidth';\nimport { Utils } from './Utils';\nimport type { ThemeType, Translate } from '../types';\nimport { Icon } from './Icon';\nimport { IconCopyToClipboard } from './AnimatedIcons/IconCopyToClipboard';\n\nconst styles: Record<string, React.CSSProperties> = {\n dialog: {\n height: '100%',\n },\n paper: {\n height: 'calc(100% - 64px)',\n },\n content: {\n textAlign: 'center',\n },\n textarea: {\n width: '100%',\n height: '100%',\n },\n img: {\n width: 'auto',\n height: 'calc(100% - 5px)',\n objectFit: 'contain',\n },\n dialogTitle: {\n justifyContent: 'space-between',\n display: 'flex',\n },\n};\n\nexport const EXTENSIONS = {\n images: ['png', 'jpg', 'svg', 'jpeg', 'bmp', 'gif', 'apng', 'avif', 'webp', 'ico'],\n code: ['js', 'json', 'json5', 'md'],\n txt: ['log', 'txt', 'html', 'css', 'xml', 'ics', 'csv'],\n audio: ['mp3', 'wav', 'ogg', 'acc'],\n video: ['mp4', 'mov', 'avi'],\n};\n\nfunction bufferToBase64(buffer: Buffer, isFull?: boolean): string {\n let binary = '';\n const bytes = new Uint8Array((buffer as unknown as { data: number[]; type: 'Buffer' })?.data || buffer);\n const len = bytes.byteLength;\n for (let i = 0; i < len && (isFull || i < 50); i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return window.btoa(binary);\n}\n\nexport interface FileViewerProps {\n /** Translation function */\n t: Translate;\n /** Callback when the viewer is closed. */\n onClose: () => void;\n /** The URL (file path) to the file to be displayed. */\n href: string;\n formatEditFile?: string;\n socket: Connection;\n setStateBackgroundImage: () => void;\n themeType: ThemeType;\n getStyleBackgroundImage: () => React.CSSProperties | null;\n /** Flag is the js-controller support subscribe on file */\n supportSubscribes?: boolean;\n}\n\nexport interface FileViewerState {\n text: string | null;\n code: string | null;\n ext: string | null;\n editing: boolean;\n editingValue: string | null;\n copyPossible: boolean;\n forceUpdate: number;\n changed: boolean;\n imgError: boolean;\n}\n\nexport class FileViewerClass extends Component<FileViewerProps, FileViewerState> {\n private timeout: ReturnType<typeof setTimeout> | null = null;\n\n constructor(props: FileViewerProps) {\n super(props);\n const ext = Utils.getFileExtension(props.href);\n\n this.state = {\n text: null,\n code: null,\n ext,\n // File viewer in adapter-react does not support write\n editing: /* !!this.props.formatEditFile || */ false,\n editingValue: null,\n copyPossible: !!ext && (EXTENSIONS.code.includes(ext) || EXTENSIONS.txt.includes(ext)),\n forceUpdate: Date.now(),\n changed: false,\n imgError: false,\n };\n }\n\n readFile(): void {\n if (this.props.href) {\n const parts = this.props.href.split('/');\n parts.splice(0, 2);\n const adapter = parts[0];\n const name = parts.splice(1).join('/');\n\n this.props.socket\n .readFile(adapter, name)\n .then((data: { file: string | Buffer; mimeType: string }) => {\n let fileData: string | Buffer = '';\n if (data.file !== undefined) {\n fileData = (data as { file: string; mimeType: string }).file;\n }\n\n const newState: Partial<FileViewerState> = {\n copyPossible: this.state.copyPossible,\n ext: this.state.ext,\n };\n // try to detect valid extension\n if ((fileData as unknown as { data: Buffer; type: string }).type === 'Buffer') {\n if (name.toLowerCase().endsWith('.json5')) {\n newState.ext = 'json5';\n newState.copyPossible = true;\n try {\n fileData = atob(bufferToBase64(fileData as unknown as Buffer, true));\n } catch {\n console.error('Cannot convert base64 to string');\n fileData = '';\n }\n } else {\n const ext = Utils.detectMimeType(bufferToBase64(fileData as unknown as Buffer));\n if (ext) {\n newState.ext = ext;\n newState.copyPossible = EXTENSIONS.code.includes(ext) || EXTENSIONS.txt.includes(ext);\n }\n }\n }\n\n if (newState.copyPossible) {\n if (newState.ext && EXTENSIONS.txt.includes(newState.ext)) {\n newState.text = fileData;\n newState.editingValue = fileData;\n } else if (newState.ext && EXTENSIONS.code.includes(newState.ext)) {\n newState.code = fileData;\n newState.editingValue = fileData;\n }\n }\n\n this.setState(newState as FileViewerState);\n })\n .catch(e => window.alert(`Cannot read file: ${e}`));\n }\n }\n\n componentDidMount(): void {\n this.readFile();\n\n const parts = this.props.href.split('/');\n parts.splice(0, 2);\n const adapter = parts[0];\n const name = parts.splice(1).join('/');\n\n if (this.props.supportSubscribes) {\n this.props.socket\n .subscribeFiles(adapter, name, this.onFileChanged)\n .catch(e => window.alert(`Cannot subscribe on file: ${e}`));\n }\n }\n\n componentWillUnmount(): void {\n if (this.timeout) {\n clearTimeout(this.timeout);\n this.timeout = null;\n }\n const parts = this.props.href.split('/');\n parts.splice(0, 2);\n const adapter = parts[0];\n const name = parts.splice(1).join('/');\n if (this.props.supportSubscribes) {\n this.props.socket.unsubscribeFiles(adapter, name, this.onFileChanged);\n }\n }\n\n onFileChanged = (_id: string, _fileName: string, size: number | null): void => {\n if (!this.state.changed) {\n if (this.timeout) {\n clearTimeout(this.timeout);\n }\n this.timeout = setTimeout(() => {\n this.timeout = null;\n if (size === null) {\n window.alert('Show file was deleted!');\n } else if (this.state.text !== null || this.state.code !== null) {\n this.readFile();\n } else {\n this.setState({ forceUpdate: Date.now() });\n }\n }, 300);\n }\n };\n\n getEditorOrViewer(): JSX.Element {\n return (\n <TextField\n variant=\"standard\"\n style={styles.textarea}\n multiline\n value={this.state.editingValue || this.state.code || this.state.text}\n // onChange={newValue => this.setState({ editingValue: newValue, changed: true })}\n slotProps={{\n htmlInput: {\n readOnly: !this.state.editing,\n },\n }}\n />\n );\n }\n\n getContent(): React.JSX.Element | null {\n if (this.state.ext && EXTENSIONS.images.includes(this.state.ext)) {\n if (this.state.imgError) {\n return <IconNoIcon style={{ ...styles.img, ...this.props.getStyleBackgroundImage() }} />;\n }\n return (\n <Icon\n onError={e => {\n (e.target as HTMLImageElement).onerror = null;\n this.setState({ imgError: true });\n }}\n style={{ ...styles.img, ...this.props.getStyleBackgroundImage() }}\n src={`${this.props.href}?ts=${this.state.forceUpdate}`}\n alt={this.props.href}\n />\n );\n }\n if (this.state.ext && EXTENSIONS.audio.includes(this.state.ext)) {\n return (\n <div\n style={{\n width: '100%',\n height: '100%',\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n }}\n >\n <audio\n style={{ width: '100%' }}\n src={this.props.href}\n controls\n ></audio>\n </div>\n );\n }\n if (this.state.ext && EXTENSIONS.video.includes(this.state.ext)) {\n return (\n <div\n style={{\n width: '100%',\n height: '100%',\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n }}\n >\n <video\n style={{ width: '100%', height: '100%' }}\n controls\n >\n <source\n src={this.props.href}\n type={`video/${this.state.ext}`}\n />\n </video>\n </div>\n );\n }\n if (this.state.code !== null || this.state.text !== null || this.state.editing) {\n // File viewer in adapter-react does not support write\n // return <Editor\n // mode={this.getEditFile(this.props.formatEditFile)}\n // themeType={this.props.themeType}\n // value={this.state.editingValue || this.state.code || this.state.text}\n // onChange={this.state.editing ? newValue => this.setState({ editingValue: newValue, changed: true }) : undefined}\n // />;\n return this.getEditorOrViewer();\n }\n return null;\n }\n\n // eslint-disable-next-line class-methods-use-this\n onSave(): void {\n // Do nothing as the file viewer in adapter-react does not support writing\n }\n\n render(): JSX.Element {\n return (\n <Dialog\n sx={{\n '&.MuiDialog-scrollPaper': styles.dialog,\n '& .MuiDialog-paper': styles.paper,\n }}\n scroll=\"paper\"\n open={!!this.props.href}\n onClose={() => this.props.onClose()}\n fullWidth\n maxWidth=\"xl\"\n aria-labelledby=\"ar_dialog_file_view_title\"\n >\n <div style={styles.dialogTitle}>\n <DialogTitle id=\"ar_dialog_file_view_title\">{`${this.props.t(this.state.editing ? 'Edit' : 'View')}: ${this.props.href}`}</DialogTitle>\n {this.state.ext && EXTENSIONS.images.includes(this.state.ext) && (\n <div>\n <IconButton\n size=\"large\"\n color=\"inherit\"\n onClick={this.props.setStateBackgroundImage}\n >\n <Brightness5Icon />\n </IconButton>\n </div>\n )}\n </div>\n <DialogContent style={styles.content}>{this.getContent()}</DialogContent>\n <DialogActions>\n {this.state.copyPossible ? (\n <Button\n color=\"grey\"\n onClick={e => {\n e.stopPropagation();\n e.preventDefault();\n Utils.copyToClipboard(this.state.text || this.state.code || '');\n }}\n startIcon={<IconCopyToClipboard />}\n >\n {this.props.t('Copy content')}\n </Button>\n ) : null}\n {this.state.editing ? (\n <Button\n color=\"grey\"\n disabled={\n this.state.editingValue === this.state.code ||\n this.state.editingValue === this.state.text\n }\n variant=\"contained\"\n onClick={() => this.onSave()}\n startIcon={<SaveIcon />}\n >\n {this.props.t('Save')}\n </Button>\n ) : null}\n <Button\n variant=\"contained\"\n onClick={() => this.props.onClose()}\n color=\"primary\"\n startIcon={<CloseIcon />}\n >\n {this.props.t('Close')}\n </Button>\n </DialogActions>\n </Dialog>\n );\n }\n}\nexport const FileViewer = withWidth()(FileViewerClass);\n"]}
|
|
@@ -106,6 +106,11 @@ export declare class ObjectBrowserClass extends Component<ObjectBrowserProps, Ob
|
|
|
106
106
|
ts: number;
|
|
107
107
|
shown?: number;
|
|
108
108
|
}>;
|
|
109
|
+
/** id -> last confirmation of a command: the state was written with ack=false and then got ack=true */
|
|
110
|
+
readonly valueAcks: Record<string, {
|
|
111
|
+
ts: number;
|
|
112
|
+
shown?: number;
|
|
113
|
+
}>;
|
|
109
114
|
/** The running animations of an unfolded or folding node (see `rowAnimation.ts`) */
|
|
110
115
|
private rowAnimations;
|
|
111
116
|
/** The node whose children slide under its row at the moment; they are removed when that ends */
|
|
@@ -322,6 +327,7 @@ export declare class ObjectBrowserClass extends Component<ObjectBrowserProps, Ob
|
|
|
322
327
|
unsubscribe(id: string): void;
|
|
323
328
|
pauseSubscribe(isPause: boolean): void;
|
|
324
329
|
clearFilter(): void;
|
|
330
|
+
/** True if no filter is set */
|
|
325
331
|
isFilterEmpty(): boolean;
|
|
326
332
|
onExpandAll(root?: TreeItem, expanded?: string[]): void;
|
|
327
333
|
onCollapseAll(): void;
|
|
@@ -10,14 +10,14 @@
|
|
|
10
10
|
*/
|
|
11
11
|
/* eslint-disable react/no-unused-class-component-methods -- the members are used by the sibling modules of this directory */
|
|
12
12
|
import React, { Component, createRef } from 'react';
|
|
13
|
-
import { Box
|
|
13
|
+
import { Box } from '@mui/material';
|
|
14
14
|
// own
|
|
15
15
|
import { Connection } from '../../Connection';
|
|
16
16
|
import { Utils } from '../Utils'; // @iobroker/gui-components/Components/Utils
|
|
17
17
|
import { TabContainer } from '../TabContainer';
|
|
18
18
|
import { TabContent } from '../TabContent';
|
|
19
19
|
import { TabHeader } from '../TabHeader';
|
|
20
|
-
import { ROW_HEIGHT, TREND_DURATION, applyFilter, buildTree, findNode, formatValue, generateFile, getName, colVar, widthFromContainer, growVar, getSelectIdIconFromObjects, setCustomValue, } from './utils';
|
|
20
|
+
import { ROW_HEIGHT, TREND_DURATION, ACK_DURATION, applyFilter, buildTree, findNode, formatValue, generateFile, getName, colVar, widthFromContainer, growVar, getSelectIdIconFromObjects, setCustomValue, } from './utils';
|
|
21
21
|
import { HistoryChart } from './HistoryChart';
|
|
22
22
|
import { styles } from './styles';
|
|
23
23
|
import * as dialogs from './dialogs';
|
|
@@ -25,6 +25,7 @@ import * as toolbar from './toolbar';
|
|
|
25
25
|
import * as leaf from './renderLeaf';
|
|
26
26
|
import * as contextMenu from './contextMenu';
|
|
27
27
|
import * as rowAnimation from './rowAnimation';
|
|
28
|
+
import { renderSkeleton } from './skeleton';
|
|
28
29
|
import { DEFAULT_DATE_FORMAT, DEFAULT_FILTER, ITEM_LEVEL, MIN_COLUMN_WIDTHS, SCREEN_WIDTHS, } from './constants';
|
|
29
30
|
export { getSelectIdIconFromObjects };
|
|
30
31
|
let objectsAlreadyLoaded = false;
|
|
@@ -129,6 +130,8 @@ export class ObjectBrowserClass extends Component {
|
|
|
129
130
|
* `shown` is the time the row showed it first, so a row that is rendered again continues the animation.
|
|
130
131
|
*/
|
|
131
132
|
valueTrends = {};
|
|
133
|
+
/** id -> last confirmation of a command: the state was written with ack=false and then got ack=true */
|
|
134
|
+
valueAcks = {};
|
|
132
135
|
/** The running animations of an unfolded or folding node (see `rowAnimation.ts`) */
|
|
133
136
|
rowAnimations = [];
|
|
134
137
|
/** The node whose children slide under its row at the moment; they are removed when that ends */
|
|
@@ -213,6 +216,17 @@ export class ObjectBrowserClass extends Component {
|
|
|
213
216
|
catch {
|
|
214
217
|
expanded = [];
|
|
215
218
|
}
|
|
219
|
+
// the way down to the root is open: above it, there is nothing to choose
|
|
220
|
+
if (props.root) {
|
|
221
|
+
const parts = props.root.split('.');
|
|
222
|
+
for (let i = 1; i <= parts.length; i++) {
|
|
223
|
+
const id = parts.slice(0, i).join('.');
|
|
224
|
+
if (!expanded.includes(id)) {
|
|
225
|
+
expanded.push(id);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
expanded.sort();
|
|
229
|
+
}
|
|
216
230
|
let filter;
|
|
217
231
|
const filterStr = props.defaultFilters
|
|
218
232
|
? ''
|
|
@@ -501,8 +515,15 @@ export class ObjectBrowserClass extends Component {
|
|
|
501
515
|
props.types[i] === 'enum') {
|
|
502
516
|
continue;
|
|
503
517
|
}
|
|
504
|
-
|
|
505
|
-
|
|
518
|
+
// Only below the root, if there is one. Else from ' ': with an empty start key the view brings
|
|
519
|
+
// the objects under `system.` only.
|
|
520
|
+
const moreObjects = await props.socket.getObjectViewSystem(props.types[i], props.root || ' ', props.root ? `${props.root}.\u9999` : '\u9999');
|
|
521
|
+
// The views `config`, `user` and `group` are keyed by the name of the object, not by its ID
|
|
522
|
+
for (const obj of Object.values(moreObjects)) {
|
|
523
|
+
if (obj?._id) {
|
|
524
|
+
objects[obj._id] = obj;
|
|
525
|
+
}
|
|
526
|
+
}
|
|
506
527
|
}
|
|
507
528
|
}
|
|
508
529
|
this.systemConfig ||=
|
|
@@ -1088,6 +1109,10 @@ export class ObjectBrowserClass extends Component {
|
|
|
1088
1109
|
else if (typeof oldVal === 'boolean' && typeof newVal === 'boolean' && oldVal !== newVal) {
|
|
1089
1110
|
this.valueTrends[id] = { dir: 'toggle', ts: Date.now() };
|
|
1090
1111
|
}
|
|
1112
|
+
// the placeholder of a state that is not loaded yet has no `ack`, so only a real command counts
|
|
1113
|
+
if (oldState?.ack === false && state?.ack === true) {
|
|
1114
|
+
this.valueAcks[id] = { ts: Date.now() };
|
|
1115
|
+
}
|
|
1091
1116
|
if (state) {
|
|
1092
1117
|
this.states[id] = state;
|
|
1093
1118
|
}
|
|
@@ -1369,8 +1394,9 @@ export class ObjectBrowserClass extends Component {
|
|
|
1369
1394
|
});
|
|
1370
1395
|
}
|
|
1371
1396
|
}
|
|
1397
|
+
/** True if no filter is set */
|
|
1372
1398
|
isFilterEmpty() {
|
|
1373
|
-
return (!!this.state.filter.id ||
|
|
1399
|
+
return !(!!this.state.filter.id ||
|
|
1374
1400
|
!!this.state.filter.name ||
|
|
1375
1401
|
!!this.state.filter.room?.length ||
|
|
1376
1402
|
!!this.state.filter.func?.length ||
|
|
@@ -2848,7 +2874,7 @@ export class ObjectBrowserClass extends Component {
|
|
|
2848
2874
|
this.doFilter(true);
|
|
2849
2875
|
}
|
|
2850
2876
|
if (!this.state.loaded) {
|
|
2851
|
-
return
|
|
2877
|
+
return renderSkeleton(this);
|
|
2852
2878
|
}
|
|
2853
2879
|
// the container was resized into another width class => other columns are visible, and the
|
|
2854
2880
|
// stored widths have to be written into the defaults of the new class.
|
|
@@ -2951,7 +2977,41 @@ export class ObjectBrowserClass extends Component {
|
|
|
2951
2977
|
0% { transform: perspective(60px) rotateX(90deg); opacity: 0.3; }
|
|
2952
2978
|
100% { transform: none; opacity: 1; }
|
|
2953
2979
|
}
|
|
2980
|
+
.iob-ob-ack {
|
|
2981
|
+
display: inline-flex;
|
|
2982
|
+
align-self: center;
|
|
2983
|
+
flex-shrink: 0;
|
|
2984
|
+
width: 0.9em;
|
|
2985
|
+
height: 0.9em;
|
|
2986
|
+
margin-left: 4px;
|
|
2987
|
+
color: ${this.props.themeType === 'dark' ? '#66bb6a' : '#2e7d32'};
|
|
2988
|
+
animation: iob-ob-ack ${ACK_DURATION}ms ease-out forwards;
|
|
2989
|
+
}
|
|
2990
|
+
.iob-ob-ack svg {
|
|
2991
|
+
width: 100%;
|
|
2992
|
+
height: 100%;
|
|
2993
|
+
fill: none;
|
|
2994
|
+
stroke: currentColor;
|
|
2995
|
+
stroke-width: 3;
|
|
2996
|
+
stroke-linecap: round;
|
|
2997
|
+
stroke-linejoin: round;
|
|
2998
|
+
}
|
|
2999
|
+
.iob-ob-ack path {
|
|
3000
|
+
stroke-dasharray: 1 1;
|
|
3001
|
+
stroke-dashoffset: 1;
|
|
3002
|
+
animation: iob-ob-ack-draw 0.35s cubic-bezier(0.65, 0, 0.35, 1) forwards;
|
|
3003
|
+
/* a row that is mounted again continues the drawing too, see continueTrendAnimation */
|
|
3004
|
+
animation-delay: inherit;
|
|
3005
|
+
}
|
|
3006
|
+
@keyframes iob-ob-ack {
|
|
3007
|
+
0%, 75% { opacity: 1; }
|
|
3008
|
+
100% { opacity: 0; }
|
|
3009
|
+
}
|
|
3010
|
+
@keyframes iob-ob-ack-draw {
|
|
3011
|
+
to { stroke-dashoffset: 0; }
|
|
3012
|
+
}
|
|
2954
3013
|
@media (prefers-reduced-motion: reduce) {
|
|
3014
|
+
.iob-ob-ack path { animation: none; stroke-dashoffset: 0; }
|
|
2955
3015
|
.iob-ob-trend { animation-name: iob-ob-trend-fade; }
|
|
2956
3016
|
.newValueBrowser-dark.iob-ob-flip { animation: newValueAnimation-dark 2s ease-in-out; }
|
|
2957
3017
|
.newValueBrowser-light.iob-ob-flip { animation: newValueAnimation-light 2s ease-in-out; }
|