Skip to content

Commit

Permalink
fixed issue with jsonConfig sendTo with native option when returnin… (#…
Browse files Browse the repository at this point in the history
…2202)

…g multiple properties

- closes #2196
  • Loading branch information
foxriver76 authored Nov 2, 2023
1 parent 9df631a commit e18fe6d
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 37 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ The icons may not be reused in other projects without the proper flaticon licens
-->
## Changelog
### **WORK IN PROGRESS**
* (foxriver76) fixed issue with jsonConfig `sendTo` with `native` option when returning multiple properties
* (foxriver76) fixed crash case when schema cannot be read
* (klein0r) Fixed noDelete attribute of JSON config accordion

Expand Down
2 changes: 1 addition & 1 deletion src/src/components/JsonConfigComponent/ConfigGeneric.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ export default class ConfigGeneric<Props extends ConfigGenericProps, State exten
}

// eslint-disable-next-line react/no-unused-class-component-methods
getIcon(iconSettings: string | undefined | null): React.JSX.Element | null {
getIcon(iconSettings?: string | null): React.JSX.Element | null {
iconSettings = iconSettings || this.props.schema.icon;
let icon = null;
if (iconSettings === 'auth') {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '@mui/styles';

import { Button, CircularProgress } from '@mui/material';
Expand All @@ -10,12 +9,13 @@ import {
Info as IconInfo,
} from '@mui/icons-material';

import { AdminConnection } from '@iobroker/adapter-react-v5';
import I18n from './wrapper/i18n';
import DialogError from './wrapper/Dialogs/Error';
import DialogMessage from './wrapper/Dialogs/Message';
import DialogConfirm from './wrapper/Dialogs/Confirm';

import ConfigGeneric from './ConfigGeneric';
import ConfigGeneric, { ConfigGenericProps, ConfigGenericState } from './ConfigGeneric';

const styles = () => ({
fullWidth: {
Expand All @@ -28,23 +28,23 @@ const styles = () => ({
},
});

function ip2int(ip) {
function ip2int(ip: string) {
// eslint-disable-next-line no-bitwise
return ip.split('.').reduce((ipInt, octet) => (ipInt << 8) + parseInt(octet, 10), 0) >>> 0;
}

// copied from iobroker.admin/src-rx/src/Utils.js
function findNetworkAddressOfHost(obj, localIp) {
function findNetworkAddressOfHost(obj: Record<string, any>, localIp: string) {
const networkInterfaces = obj?.native?.hardware?.networkInterfaces;
if (!networkInterfaces) {
return null;
}

let hostIp;
let hostIp: string | undefined;

// check ipv4 addresses
Object.keys(networkInterfaces).forEach(inter =>
networkInterfaces[inter].forEach(ip => {
networkInterfaces[inter].forEach((ip: Record<string, any>) => {
if (ip.internal) {
return;
}
Expand All @@ -71,7 +71,7 @@ function findNetworkAddressOfHost(obj, localIp) {
// check ipv6 addresses
if (!hostIp) {
Object.keys(networkInterfaces).forEach(inter =>
networkInterfaces[inter].forEach(ip => {
networkInterfaces[inter].forEach((ip: Record<string, any>) => {
if (ip.internal) {
return;
} if (localIp.includes(':') && ip.family !== 'IPv6') {
Expand All @@ -95,7 +95,7 @@ function findNetworkAddressOfHost(obj, localIp) {

if (!hostIp) {
Object.keys(networkInterfaces).forEach(inter => {
networkInterfaces[inter].forEach(ip => {
networkInterfaces[inter].forEach((ip: Record<string, any>) => {
if (ip.internal) {
return;
} if (localIp.includes(':') && ip.family !== 'IPv6') {
Expand All @@ -114,7 +114,7 @@ function findNetworkAddressOfHost(obj, localIp) {

if (!hostIp) {
Object.keys(networkInterfaces).forEach(inter => {
networkInterfaces[inter].forEach(ip => {
networkInterfaces[inter].forEach((ip: Record<string, any>) => {
if (ip.internal) {
return;
}
Expand All @@ -126,7 +126,29 @@ function findNetworkAddressOfHost(obj, localIp) {
return hostIp;
}

class ConfigSendto extends ConfigGeneric {
interface ConfigSendToProps extends ConfigGenericProps {
socket: AdminConnection;
themeType: string;
themeName: string;
style: Record<string, any>;
className: string;
data: Record<string, any>;
schema: Record<string, any>;
adapterName: string;
instance:number;
commandRunning: boolean;
onCommandRunning: (running: boolean) => void;
classes: Record<string, any>;
}

interface ConfigSendToState extends ConfigGenericState {
_error: string;
_message: string;
hostname: string;
running?: boolean;
}

class ConfigSendto extends ConfigGeneric<ConfigSendToProps, ConfigSendToState> {
async componentDidMount() {
super.componentDidMount();

Expand All @@ -150,14 +172,15 @@ class ConfigSendto extends ConfigGeneric {

renderErrorDialog() {
if (this.state._error) {
// @ts-expect-error classes should be optional in adapter-react
return <DialogError text={this.state._error} classes={undefined} onClose={() => this.setState({ _error: '' })} />;
}
return null;
}

renderMessageDialog() {
if (this.state._message) {
return <DialogMessage text={this.state._message} classes={undefined} onClose={() => this.setState({ _message: '' })} />;
return <DialogMessage text={this.state._message} onClose={() => this.setState({ _message: '' })} />;
}
return null;
}
Expand Down Expand Up @@ -191,7 +214,7 @@ class ConfigSendto extends ConfigGeneric {
_originIp,
};
}
let timeout;
let timeout: ReturnType<typeof setTimeout> | undefined;
if (this.props.schema.timeout) {
timeout = setTimeout(() => {
this.props.onCommandRunning(false);
Expand All @@ -204,16 +227,16 @@ class ConfigSendto extends ConfigGeneric {
this.props.schema.command || 'send',
data,
)
.then(response => {
.then(async (response: Record<string, any>) => {
if (timeout) {
clearTimeout(timeout);
timeout = null;
timeout = undefined;
}
if (response?.error) {
if (this.props.schema.error && this.props.schema.error[response.error]) {
let error = this.getText(this.props.schema.error[response.error]);
if (response.args) {
response.args.forEach(arg => error = error.replace('%s', arg));
response.args.forEach((arg: string) => error = error.replace('%s', arg));
}
this.setState({ _error: error });
} else {
Expand All @@ -227,15 +250,17 @@ class ConfigSendto extends ConfigGeneric {
} else if (response?.result && this.props.schema.result && this.props.schema.result[response.result]) {
let text = this.getText(this.props.schema.result[response.result]);
if (response.args) {
response.args.forEach(arg => text = text.replace('%s', arg));
response.args.forEach((arg: string) => text = text.replace('%s', arg));
}
window.alert(text);
}

if (response?.native && this.props.schema.useNative) {
const attrs = Object.keys(response.native);
attrs.forEach(attr =>
this.onChange(attr, response.native[attr]));
for (const attr of attrs) {
await this.onChange(attr, response.native[attr]);
}

setTimeout(() => this.props.forceUpdate(attrs, this.props.data), 300);
} else if (response?.result) {
window.alert(typeof response.result === 'object' ? JSON.stringify(response.result) : response.result);
Expand All @@ -244,11 +269,12 @@ class ConfigSendto extends ConfigGeneric {
}

if (response?.saveConfig) {
// @ts-expect-error 4 values intended?
this.props.onChange(null, null, null, true);
}
}
})
.catch(e => {
.catch((e: any) => {
if (this.props.schema.error && this.props.schema.error[e.toString()]) {
this.setState({ _error: this.getText(this.props.schema.error[e.toString()]) });
} else {
Expand Down Expand Up @@ -287,7 +313,7 @@ class ConfigSendto extends ConfigGeneric {
/>;
}

renderItem(error, disabled /* , defaultValue */) {
renderItem(error: Error | undefined, disabled: boolean /* , defaultValue */) {
const icon = this.getIcon();

return <div className={this.props.classes.fullWidth}>
Expand Down Expand Up @@ -315,20 +341,4 @@ class ConfigSendto extends ConfigGeneric {
}
}

ConfigSendto.propTypes = {
socket: PropTypes.object.isRequired,
themeType: PropTypes.string,
themeName: PropTypes.string,
style: PropTypes.object,
className: PropTypes.string,
data: PropTypes.object.isRequired,
schema: PropTypes.object,
onError: PropTypes.func,
onChange: PropTypes.func,
adapterName: PropTypes.string,
instance: PropTypes.number,
commandRunning: PropTypes.bool,
onCommandRunning: PropTypes.func,
};

export default withStyles(styles)(ConfigSendto);

0 comments on commit e18fe6d

Please sign in to comment.