From 9c8f31e1b81c62701cc54c6d039706ec52fae852 Mon Sep 17 00:00:00 2001 From: GermanBluefox Date: Fri, 9 Jul 2021 19:41:39 +0200 Subject: [PATCH] ### __WORK IN PROGRESS__ * (bluefox) Corrected some GUI errors --- README.md | 3 + admin/i18n/de/translations.json | 7 +- admin/i18n/en/translations.json | 7 +- admin/i18n/es/translations.json | 7 +- admin/i18n/fr/translations.json | 7 +- admin/i18n/it/translations.json | 7 +- admin/i18n/nl/translations.json | 7 +- admin/i18n/pl/translations.json | 7 +- admin/i18n/pt/translations.json | 7 +- admin/i18n/ru/translations.json | 7 +- admin/i18n/zh-cn/translations.json | 7 +- src-rx/package.json | 4 +- src-rx/src/App.js | 3 +- src-rx/src/TODO.md | 1 + src-rx/src/components/Adapters/AdapterRow.js | 12 +++- src-rx/src/components/Enums/EnumsMain.js | 2 +- .../src/components/Instances/InstanceRow.js | 32 +++++++-- .../JsonConfigComponent/ConfigGeneric.js | 16 +++++ src-rx/src/components/Object/ObjectChart.js | 9 ++- src-rx/src/components/Users/GroupBlock.js | 2 +- src-rx/src/components/Users/UsersList.js | 71 ++++++++++++------- src-rx/src/dialogs/AdapterUpdateDialog.js | 14 +++- src-rx/src/dialogs/DiscoveryDialog.js | 2 +- src-rx/src/dialogs/LicenseDialog.js | 3 +- .../dialogs/SlowConnectionWarningDialog.js | 14 ++-- src-rx/src/helpers/MobileDialog.js | 2 +- src-rx/src/tabs/Logs.js | 24 +++++-- 27 files changed, 221 insertions(+), 63 deletions(-) diff --git a/README.md b/README.md index 334180089..2196d67a0 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,9 @@ The icons may not be reused in other projects without the proper flaticon licens --> ## Changelog +### __WORK IN PROGRESS__ +* (bluefox) Corrected some GUI errors + ### 5.1.9 (2021-06-09) * (bluefox) Corrected some GUI errors diff --git a/admin/i18n/de/translations.json b/admin/i18n/de/translations.json index 361958926..599e1f828 100644 --- a/admin/i18n/de/translations.json +++ b/admin/i18n/de/translations.json @@ -70,5 +70,10 @@ "sec": "Sek", "Use background image": "Hintergrundbild verwenden", "Upload image": "Bild hochladen", - "Undo": "Rückgängig machen" + "Undo": "Rückgängig machen", + "End date": "Enddatum", + "End time": "Endzeit", + "Insert entry": "Eintrag einfügen", + "No data in history for selected period": "Keine Daten im Verlauf für den ausgewählten Zeitraum", + "1 minute": "1 Minute" } \ No newline at end of file diff --git a/admin/i18n/en/translations.json b/admin/i18n/en/translations.json index 0c1620ae7..0331a33f9 100644 --- a/admin/i18n/en/translations.json +++ b/admin/i18n/en/translations.json @@ -70,5 +70,10 @@ "sec": "sec", "Use background image": "Use background image", "Upload image": "Upload image", - "Undo": "Undo" + "Undo": "Undo", + "End date": "End date", + "End time": "End time", + "Insert entry": "Insert entry", + "No data in history for selected period": "No data in history for selected period", + "1 minute": "1 minute" } \ No newline at end of file diff --git a/admin/i18n/es/translations.json b/admin/i18n/es/translations.json index 18f47fdeb..9ddb02249 100644 --- a/admin/i18n/es/translations.json +++ b/admin/i18n/es/translations.json @@ -70,5 +70,10 @@ "sec": "segundo", "Use background image": "Usar imagen de fondo", "Upload image": "Cargar imagen", - "Undo": "Deshacer" + "Undo": "Deshacer", + "End date": "Fecha final", + "End time": "Hora de finalización", + "Insert entry": "Insertar entrada", + "No data in history for selected period": "No hay datos en el historial para el período seleccionado", + "1 minute": "1 minuto" } \ No newline at end of file diff --git a/admin/i18n/fr/translations.json b/admin/i18n/fr/translations.json index bbc9220ff..670ebf40e 100644 --- a/admin/i18n/fr/translations.json +++ b/admin/i18n/fr/translations.json @@ -70,5 +70,10 @@ "sec": "seconde", "Use background image": "Utiliser l'image d'arrière-plan", "Upload image": "Télécharger une image", - "Undo": "annuler" + "Undo": "annuler", + "End date": "Date de fin", + "End time": "Heure de fin", + "Insert entry": "Insérer une entrée", + "No data in history for selected period": "Aucune donnée dans l'historique pour la période sélectionnée", + "1 minute": "1 minute" } \ No newline at end of file diff --git a/admin/i18n/it/translations.json b/admin/i18n/it/translations.json index 3bd42a058..ef18e64e3 100644 --- a/admin/i18n/it/translations.json +++ b/admin/i18n/it/translations.json @@ -70,5 +70,10 @@ "sec": "secondo", "Use background image": "Usa immagine di sfondo", "Upload image": "Carica immagine", - "Undo": "Disfare" + "Undo": "Disfare", + "End date": "Data di fine", + "End time": "Tempo scaduto", + "Insert entry": "Inserisci voce", + "No data in history for selected period": "Nessun dato nella cronologia per il periodo selezionato", + "1 minute": "1 minuto" } \ No newline at end of file diff --git a/admin/i18n/nl/translations.json b/admin/i18n/nl/translations.json index 41b1440de..1ee5778d8 100644 --- a/admin/i18n/nl/translations.json +++ b/admin/i18n/nl/translations.json @@ -70,5 +70,10 @@ "sec": "sec", "Use background image": "Achtergrondafbeelding gebruiken", "Upload image": "Afbeelding uploaden", - "Undo": "ongedaan maken" + "Undo": "ongedaan maken", + "End date": "Einddatum", + "End time": "Eindtijd", + "Insert entry": "Invoer invoegen", + "No data in history for selected period": "Geen gegevens in geschiedenis voor geselecteerde periode", + "1 minute": "1 minuut" } \ No newline at end of file diff --git a/admin/i18n/pl/translations.json b/admin/i18n/pl/translations.json index 00468bbca..4aa4eaa89 100644 --- a/admin/i18n/pl/translations.json +++ b/admin/i18n/pl/translations.json @@ -70,5 +70,10 @@ "sec": "sek", "Use background image": "Użyj obrazu tła", "Upload image": "Załaduj obrazek", - "Undo": "Cofnij" + "Undo": "Cofnij", + "End date": "Data końcowa", + "End time": "Koniec czasu", + "Insert entry": "Wstaw wpis", + "No data in history for selected period": "Brak danych w historii dla wybranego okresu", + "1 minute": "1 minuta" } \ No newline at end of file diff --git a/admin/i18n/pt/translations.json b/admin/i18n/pt/translations.json index b436b5e93..ccf8c7f57 100644 --- a/admin/i18n/pt/translations.json +++ b/admin/i18n/pt/translations.json @@ -70,5 +70,10 @@ "sec": "s", "Use background image": "Use imagem de fundo", "Upload image": "Enviar Imagem", - "Undo": "Desfazer" + "Undo": "Desfazer", + "End date": "Data final", + "End time": "Fim do tempo", + "Insert entry": "Inserir entrada", + "No data in history for selected period": "Nenhum dado no histórico para o período selecionado", + "1 minute": "1 minuto" } \ No newline at end of file diff --git a/admin/i18n/ru/translations.json b/admin/i18n/ru/translations.json index 784ef6ccb..49d4bac47 100644 --- a/admin/i18n/ru/translations.json +++ b/admin/i18n/ru/translations.json @@ -70,5 +70,10 @@ "sec": "сек", "Use background image": "Использовать фоновое изображение", "Upload image": "Загрузить изображение", - "Undo": "Отменить" + "Undo": "Отменить", + "End date": "До", + "End time": "Время до", + "Insert entry": "Вставить запись", + "No data in history for selected period": "Нет данных в истории за выбранный период", + "1 minute": "1 минута" } \ No newline at end of file diff --git a/admin/i18n/zh-cn/translations.json b/admin/i18n/zh-cn/translations.json index da02735a2..3ea9cd58b 100644 --- a/admin/i18n/zh-cn/translations.json +++ b/admin/i18n/zh-cn/translations.json @@ -70,5 +70,10 @@ "sec": "秒", "Use background image": "使用背景图片", "Upload image": "上传图片", - "Undo": "撤消" + "Undo": "撤消", + "End date": "结束日期", + "End time": "时间结束", + "Insert entry": "插入条目", + "No data in history for selected period": "所选期间的历史记录中没有数据", + "1 minute": "1分钟" } \ No newline at end of file diff --git a/src-rx/package.json b/src-rx/package.json index cf4bd2296..fad68264e 100644 --- a/src-rx/package.json +++ b/src-rx/package.json @@ -10,7 +10,7 @@ "@date-io/core": "^1.3.13", "@date-io/date-fns": "^1.3.13", "@fnando/sparkline": "^0.3.10", - "@iobroker/adapter-react": "^1.6.29", + "@iobroker/adapter-react": "^1.6.30", "@material-ui/core": "^4.11.4", "@material-ui/data-grid": "^4.0.0-alpha.30", "@material-ui/icons": "^4.11.2", @@ -67,4 +67,4 @@ "not dead", "not op_mini all" ] -} \ No newline at end of file +} diff --git a/src-rx/src/App.js b/src-rx/src/App.js index 3981c62fe..759d77183 100644 --- a/src-rx/src/App.js +++ b/src-rx/src/App.js @@ -194,7 +194,7 @@ const styles = theme => ({ animation: '0.2s linear infinite alternate $myEffect2', }, performed: { - color: '#388e3c', + color: theme.palette.type === 'light' ? '#3bfd44' : '#388e3c', animation: '0.2s linear infinite alternate $myEffect2', }, wrapperButtons: { @@ -1280,7 +1280,6 @@ class App extends Router { } showAlert(message, type) { - if (type !== 'error' && type !== 'warning' && type !== 'info' && type !== 'success') { type = 'info'; } diff --git a/src-rx/src/TODO.md b/src-rx/src/TODO.md index 2ff732659..552aed357 100644 --- a/src-rx/src/TODO.md +++ b/src-rx/src/TODO.md @@ -17,6 +17,7 @@ Marked with "!" must be in release candidate ## Adapters - Install command: during installation the close button in upper right corner is not disabled - Show icons for autocomplete in github dialog +- Make close button black and not red ## Wizard - Replace map with leaflet diff --git a/src-rx/src/components/Adapters/AdapterRow.js b/src-rx/src/components/Adapters/AdapterRow.js index 0e569d236..e6bae84a7 100644 --- a/src-rx/src/components/Adapters/AdapterRow.js +++ b/src-rx/src/components/Adapters/AdapterRow.js @@ -137,7 +137,12 @@ const styles = theme => ({ filter: 'invert(0%) sepia(90%) saturate(1267%) hue-rotate(-260deg) brightness(99%) contrast(97%)' }, rating: { - cursor: 'pointer' + cursor: 'pointer', + height: 18 + }, + nameCell: { + paddingTop: '0 !important', + paddingBottom: '0 !important', } }); @@ -253,7 +258,8 @@ class AdapterRow extends Component { /> {/* {name} */} -
{name}
+ +
{name}
{!versionDate ?
onSetRating() : undefined} className={clsx(classes.rating, onSetRating && classes.ratingSet)} @@ -270,7 +276,7 @@ class AdapterRow extends Component { - {!descHidden && {this.props.description}} + {!descHidden && {this.props.description}}
{connectionType === 'cloud' ? diff --git a/src-rx/src/components/Enums/EnumsMain.js b/src-rx/src/components/Enums/EnumsMain.js index c677c8b02..b28a931d1 100644 --- a/src-rx/src/components/Enums/EnumsMain.js +++ b/src-rx/src/components/Enums/EnumsMain.js @@ -459,7 +459,7 @@ class EnumsList extends Component { ids.sort(sort(container.children, this.getName)); } - let name = this.getName(container.data.common?.name); + let name = this.getName(container.data?.common?.name); let idText = container.id; if (this.state.search) { const search = this.state.search; diff --git a/src-rx/src/components/Instances/InstanceRow.js b/src-rx/src/components/Instances/InstanceRow.js index 80fd25352..04087c174 100644 --- a/src-rx/src/components/Instances/InstanceRow.js +++ b/src-rx/src/components/Instances/InstanceRow.js @@ -584,6 +584,24 @@ const styles = theme => ({ opacity: '.3 !important', background: 'repeating-linear-gradient(135deg, #333, #333 10px, #888 10px, #888 20px)', } + }, + desktopRow: { + minHeight: 0 + }, + desktopIcon: { + height: 32, + width: 32, + marginTop: 4 + }, + desktopRowContent: { + marginTop: 2, + marginBottom: 2, + }, + desktopButton: { + paddingRight: 12, + paddingTop: 4, + paddingBottom: 4, + paddingLeft: 4, } }); @@ -665,6 +683,7 @@ const InstanceRow = ({ const [hostValue, setHostValue] = useState(host); const [visibleEdit, handlerEdit] = useState(false); + const desktop = window.innerWidth > 1000; let showModal = false; let title; @@ -874,14 +893,19 @@ const InstanceRow = ({ }}> {linksDialog} }> + expandIcon={}> {customModal} {stopAdminDialog} {(openDialogCron || openDialogSchedule) &&
{instance.id}
diff --git a/src-rx/src/components/JsonConfigComponent/ConfigGeneric.js b/src-rx/src/components/JsonConfigComponent/ConfigGeneric.js index 3522917a9..0023d5e2a 100644 --- a/src-rx/src/components/JsonConfigComponent/ConfigGeneric.js +++ b/src-rx/src/components/JsonConfigComponent/ConfigGeneric.js @@ -28,6 +28,8 @@ class ConfigGeneric extends Component { confirmData: null, }; + this.isError = {}; + if (this.props.custom) { this.defaultValue = this.props.schema.defaultFunc ? this.executeCustom(this.props.schema.defaultFunc, this.props.schema.default, this.props.data, this.props.instanceObj) : this.props.schema.default; } else { @@ -332,6 +334,12 @@ class ConfigGeneric extends Component { } onError(attr, error) { + if (!error) { + delete this.isError[attr]; + } else { + this.isError[attr] = error; + } + this.props.onError && this.props.onError(attr, error); } @@ -389,6 +397,14 @@ class ConfigGeneric extends Component { const schema = this.props.schema; if (hidden) { + // Remove all errors if element is hidden + if (Object.keys(this.isError)) { + setTimeout(isError => + Object.keys(isError).forEach(attr => this.props.onError(attr)), + 100, JSON.parse(JSON.stringify(this.isError))); + this.isError = {}; + } + if (schema.hideOnlyControl) { const item = ({ maxHeight: '100%', maxWidth: '100%', overflow: 'hidden', + width: '100%' }, chart: { width: '100%', @@ -179,7 +181,7 @@ class ObjectChart extends Component { this.state = { loaded: false, - historyInstance: '', + historyInstance: this.props.historyInstance || '', historyInstances: null, defaultHistory: '', chartHeight: 300, @@ -315,6 +317,11 @@ class ObjectChart extends Component { getHistoryInstances() { const list = []; const ids = []; + + if (this.props.historyInstance) { + return Promise.resolve(list); + } + this.props.customsInstances.forEach(instance => { const instObj = this.props.objects['system.adapter.' + instance]; if (instObj && instObj.common && instObj.common.getHistory) { diff --git a/src-rx/src/components/Users/GroupBlock.js b/src-rx/src/components/Users/GroupBlock.js index dbd6c450b..bf5c2bd0b 100644 --- a/src-rx/src/components/Users/GroupBlock.js +++ b/src-rx/src/components/Users/GroupBlock.js @@ -109,7 +109,7 @@ function GroupBlock(props) { key={i} variant="outlined" className={props.classes.userGroupMember} - style={{ color: _textColor, borderColor: _textColor + '80', background: user.common?.color || 'inherit' }} + style={{ color: _textColor, borderColor: _textColor + '40', background: user.common?.color || 'inherit' }} > {user.common.icon ? {this.props.t('Groups')}
{ - this.state.groups.map(group => ) + this.state.groups + .sort((a, b) => { + const _a = (this.getName(a?.common?.name) || a._id).toLowerCase(); + const _b = (this.getName(b?.common?.name) || b._id).toLowerCase(); + if (_a > _b) { + return 1; + } else if (_a < _b) { + return -1; + } else { + return 0; + } + }).map(group => ) }
600 && this.props.classes.childGridContWide)}> @@ -522,19 +533,31 @@ class UsersList extends Component {
{ - this.state.users.map(user => ) + this.state.users + .sort((a, b) => { + const _a = (this.getName(a?.common?.name) || a._id).toLowerCase(); + const _b = (this.getName(b?.common?.name) || b._id).toLowerCase(); + if (_a > _b) { + return 1; + } else if (_a < _b) { + return -1; + } else { + return 0; + } + }) + .map(user => ) }
diff --git a/src-rx/src/dialogs/AdapterUpdateDialog.js b/src-rx/src/dialogs/AdapterUpdateDialog.js index 573c4d1b4..935cef23d 100644 --- a/src-rx/src/dialogs/AdapterUpdateDialog.js +++ b/src-rx/src/dialogs/AdapterUpdateDialog.js @@ -1,4 +1,5 @@ import React, { Component } from 'react'; +import semver from 'semver'; import { withStyles } from '@material-ui/core/styles'; @@ -14,9 +15,10 @@ import { IconButton } from '@material-ui/core'; import { Typography } from '@material-ui/core'; import CloseIcon from '@material-ui/icons/Close'; +import CheckIcon from '@material-ui/icons/Check'; import State from '../components/State'; -import CheckIcon from "@material-ui/icons/Check"; +import {MOBILE_WIDTH} from '../helpers/MobileDialog'; const styles = theme => { return ({ @@ -60,6 +62,7 @@ class AdapterUpdateDialog extends Component { super(props); this.t = props.t; + this.mobile = window.innerWidth < MOBILE_WIDTH; } getDependencies() { @@ -93,6 +96,11 @@ class AdapterUpdateDialog extends Component { ) .filter(line => !!line); + if (this.props.adapterObject?.version && entry.version && + semver.gt(entry.version, this.props.adapterObject?.version)) { + return; + } + result.push( @@ -172,7 +180,7 @@ class AdapterUpdateDialog extends Component { color="primary" startIcon={} > - {this.props.textUpdate ? this.props.textUpdate : this.t('Update')} + {this.mobile ? null : (this.props.textUpdate ? this.props.textUpdate : this.t('Update'))} ; diff --git a/src-rx/src/dialogs/DiscoveryDialog.js b/src-rx/src/dialogs/DiscoveryDialog.js index 0aa37be5a..17da2c3ef 100644 --- a/src-rx/src/dialogs/DiscoveryDialog.js +++ b/src-rx/src/dialogs/DiscoveryDialog.js @@ -732,7 +732,7 @@ const DiscoveryDialog = ({ themeType, themeName, socket, dateFormat, currentHost
diff --git a/src-rx/src/dialogs/LicenseDialog.js b/src-rx/src/dialogs/LicenseDialog.js index 56fc603a9..4109da74d 100644 --- a/src-rx/src/dialogs/LicenseDialog.js +++ b/src-rx/src/dialogs/LicenseDialog.js @@ -33,7 +33,8 @@ const useStyles = makeStyles((theme) => ({ pre: { overflow: 'auto', whiteSpace: 'pre-wrap', - margin: 0 + margin: 0, + padding: 10, } })); const LicenseDialog = ({ url, cb }) => { diff --git a/src-rx/src/dialogs/SlowConnectionWarningDialog.js b/src-rx/src/dialogs/SlowConnectionWarningDialog.js index f0ad9f848..60cec477b 100644 --- a/src-rx/src/dialogs/SlowConnectionWarningDialog.js +++ b/src-rx/src/dialogs/SlowConnectionWarningDialog.js @@ -10,8 +10,10 @@ import DialogContentText from '@material-ui/core/DialogContentText'; import { Button, TextField } from '@material-ui/core'; import CloseIcon from '@material-ui/icons/Close'; -import {TimeIcon} from "@material-ui/pickers/_shared/icons/TimeIcon"; -import CheckIcon from "@material-ui/icons/Check"; +import {TimeIcon} from '@material-ui/pickers/_shared/icons/TimeIcon'; +import CheckIcon from '@material-ui/icons/Check'; + +import {MOBILE_WIDTH} from '../helpers/MobileDialog'; const styles = theme => ({ buttonLabel: { @@ -29,6 +31,8 @@ class SlowConnectionWarningDialog extends Component { this.state = { readTimeoutSec: Math.round((this.props.readTimeoutMs || SlowConnectionWarningDialog.getReadTimeoutMs()) / 1000), }; + + this.mobile = window.innerWidth < MOBILE_WIDTH; } static getReadTimeoutMs() { @@ -74,7 +78,7 @@ class SlowConnectionWarningDialog extends Component { }} startIcon={} > - {this.props.t('Set timeout to 1 minute')} + {this.mobile ? this.props.t('1 minute') : this.props.t('Set timeout to 1 minute')} ; diff --git a/src-rx/src/helpers/MobileDialog.js b/src-rx/src/helpers/MobileDialog.js index 0f7e43d66..9a0992679 100644 --- a/src-rx/src/helpers/MobileDialog.js +++ b/src-rx/src/helpers/MobileDialog.js @@ -1,6 +1,6 @@ import {Component} from 'react'; -const MOBILE_WIDTH = 800; +export const MOBILE_WIDTH = 800; class MobileDialog extends Component { static isMobile() { diff --git a/src-rx/src/tabs/Logs.js b/src-rx/src/tabs/Logs.js index a0017cbde..34e3a4524 100644 --- a/src-rx/src/tabs/Logs.js +++ b/src-rx/src/tabs/Logs.js @@ -39,6 +39,7 @@ import SaveAltIcon from '@material-ui/icons/SaveAlt'; import ErrorIcon from '@material-ui/icons/ErrorOutline'; import WarningIcon from '@material-ui/icons/Warning'; import CheckIcon from '@material-ui/icons/Check'; +import {FaPalette as ColorsIcon} from 'react-icons/fa'; import amber from '@material-ui/core/colors/amber'; import grey from '@material-ui/core/colors/grey'; @@ -298,9 +299,9 @@ class Logs extends Component { super(props); this.state = { - source: '1', - severity: 'debug', - message: '', + source: window.localStorage.getItem('Log.source') || '1', + severity: window.localStorage.getItem('Log.severity') || 'debug', + message: window.localStorage.getItem('Log.message') || '', logDeleteDialog: false, logDownloadDialog: null, logFiles: [], @@ -312,6 +313,7 @@ class Logs extends Component { pause: 0, pauseCount: 0, pid: JSON.parse(window.localStorage.getItem('Logs.pid')) || false, + colors: window.localStorage.getItem('Logs.colors') === 'true', adapters: {}, sources: {}, currentHost: this.props.currentHost, @@ -551,14 +553,17 @@ class Logs extends Component { } handleMessageChange(event) { + window.localStorage.setItem('Log.message', event.target.value); this.setState({ message: event.target.value }); } handleSourceChange(event) { + window.localStorage.setItem('Log.source', event.target.value); this.setState({ source: event.target.value }); } handleSeverityChange(event) { + window.localStorage.setItem('Log.severity', event.target.value); this.setState({ severity: event.target.value }); } @@ -695,7 +700,7 @@ class Logs extends Component { rows.push( this.lastRowRender && classes.updatedRow)} - style={{backgroundColor: this.state.sources[row.from]?.color || undefined}} + style={this.state.colors ? {backgroundColor: this.state.sources[row.from]?.color || undefined} : {}} key={key} hover > @@ -820,6 +825,17 @@ class Logs extends Component {
{this.props.t('PID')}
+ + { + window.localStorage.setItem('Logs.colors', this.state.colors ? 'false' : 'true'); + this.setState({colors: !this.state.colors}); + }} + color={!this.state.colors ? 'default' : 'primary'} + > + + +