@iobroker/json-config 6.17.6 → 6.17.13

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.
Files changed (173) hide show
  1. package/LICENSE +21 -21
  2. package/build/JsonConfig.d.ts +1 -1
  3. package/build/JsonConfig.js +18 -19
  4. package/build/JsonConfig.js.map +1 -1
  5. package/build/JsonConfigComponent/ChipInput.d.ts +89 -11
  6. package/build/JsonConfigComponent/ChipInput.js +48 -137
  7. package/build/JsonConfigComponent/ChipInput.js.map +1 -1
  8. package/build/JsonConfigComponent/ConfigAccordion.d.ts +7 -14
  9. package/build/JsonConfigComponent/ConfigAccordion.js +10 -21
  10. package/build/JsonConfigComponent/ConfigAccordion.js.map +1 -1
  11. package/build/JsonConfigComponent/ConfigAlive.d.ts +5 -1
  12. package/build/JsonConfigComponent/ConfigAlive.js +0 -1
  13. package/build/JsonConfigComponent/ConfigAlive.js.map +1 -1
  14. package/build/JsonConfigComponent/ConfigAutocomplete.d.ts +5 -29
  15. package/build/JsonConfigComponent/ConfigAutocomplete.js +7 -5
  16. package/build/JsonConfigComponent/ConfigAutocomplete.js.map +1 -1
  17. package/build/JsonConfigComponent/ConfigAutocompleteSendTo.d.ts +5 -14
  18. package/build/JsonConfigComponent/ConfigAutocompleteSendTo.js +3 -3
  19. package/build/JsonConfigComponent/ConfigAutocompleteSendTo.js.map +1 -1
  20. package/build/JsonConfigComponent/ConfigCRON.d.ts +1 -1
  21. package/build/JsonConfigComponent/ConfigCertCollection.d.ts +7 -13
  22. package/build/JsonConfigComponent/ConfigCertCollection.js +8 -18
  23. package/build/JsonConfigComponent/ConfigCertCollection.js.map +1 -1
  24. package/build/JsonConfigComponent/ConfigCertificateSelect.d.ts +7 -13
  25. package/build/JsonConfigComponent/ConfigCertificateSelect.js +5 -18
  26. package/build/JsonConfigComponent/ConfigCertificateSelect.js.map +1 -1
  27. package/build/JsonConfigComponent/ConfigCertificates.d.ts +7 -13
  28. package/build/JsonConfigComponent/ConfigCertificates.js +7 -18
  29. package/build/JsonConfigComponent/ConfigCertificates.js.map +1 -1
  30. package/build/JsonConfigComponent/ConfigCheckbox.d.ts +3 -11
  31. package/build/JsonConfigComponent/ConfigCheckbox.js +2 -2
  32. package/build/JsonConfigComponent/ConfigCheckbox.js.map +1 -1
  33. package/build/JsonConfigComponent/ConfigChip.d.ts +1 -1
  34. package/build/JsonConfigComponent/ConfigColor.d.ts +13 -20
  35. package/build/JsonConfigComponent/ConfigColor.js +9 -23
  36. package/build/JsonConfigComponent/ConfigColor.js.map +1 -1
  37. package/build/JsonConfigComponent/ConfigCoordinates.d.ts +8 -13
  38. package/build/JsonConfigComponent/ConfigCoordinates.js +29 -39
  39. package/build/JsonConfigComponent/ConfigCoordinates.js.map +1 -1
  40. package/build/JsonConfigComponent/ConfigCustom.d.ts +4 -50
  41. package/build/JsonConfigComponent/ConfigCustom.js +0 -1
  42. package/build/JsonConfigComponent/ConfigCustom.js.map +1 -1
  43. package/build/JsonConfigComponent/ConfigDatePicker.d.ts +8 -3
  44. package/build/JsonConfigComponent/ConfigDatePicker.js +21 -13
  45. package/build/JsonConfigComponent/ConfigDatePicker.js.map +1 -1
  46. package/build/JsonConfigComponent/ConfigDeviceManager.d.ts +5 -1
  47. package/build/JsonConfigComponent/ConfigDeviceManager.js +1 -1
  48. package/build/JsonConfigComponent/ConfigDeviceManager.js.map +1 -1
  49. package/build/JsonConfigComponent/ConfigFile.d.ts +1 -1
  50. package/build/JsonConfigComponent/ConfigFunc.d.ts +1 -1
  51. package/build/JsonConfigComponent/ConfigGeneric.d.ts +46 -32
  52. package/build/JsonConfigComponent/ConfigGeneric.js +23 -12
  53. package/build/JsonConfigComponent/ConfigGeneric.js.map +1 -1
  54. package/build/JsonConfigComponent/ConfigIP.d.ts +1 -1
  55. package/build/JsonConfigComponent/ConfigImageSendTo.d.ts +1 -1
  56. package/build/JsonConfigComponent/ConfigInstanceSelect.d.ts +1 -1
  57. package/build/JsonConfigComponent/ConfigInterface.d.ts +1 -1
  58. package/build/JsonConfigComponent/ConfigJsonEditor.d.ts +1 -1
  59. package/build/JsonConfigComponent/ConfigLanguage.d.ts +3 -2
  60. package/build/JsonConfigComponent/ConfigLanguage.js +2 -2
  61. package/build/JsonConfigComponent/ConfigLanguage.js.map +1 -1
  62. package/build/JsonConfigComponent/ConfigNumber.d.ts +3 -13
  63. package/build/JsonConfigComponent/ConfigNumber.js +2 -2
  64. package/build/JsonConfigComponent/ConfigNumber.js.map +1 -1
  65. package/build/JsonConfigComponent/ConfigObjectId.d.ts +1 -1
  66. package/build/JsonConfigComponent/ConfigPanel.d.ts +7 -2
  67. package/build/JsonConfigComponent/ConfigPanel.js +5 -40
  68. package/build/JsonConfigComponent/ConfigPanel.js.map +1 -1
  69. package/build/JsonConfigComponent/ConfigPassword.d.ts +1 -1
  70. package/build/JsonConfigComponent/ConfigPort.d.ts +6 -1
  71. package/build/JsonConfigComponent/ConfigPort.js +2 -3
  72. package/build/JsonConfigComponent/ConfigPort.js.map +1 -1
  73. package/build/JsonConfigComponent/ConfigRoom.d.ts +1 -1
  74. package/build/JsonConfigComponent/ConfigSelect.d.ts +1 -1
  75. package/build/JsonConfigComponent/ConfigSelectSendTo.d.ts +7 -16
  76. package/build/JsonConfigComponent/ConfigSelectSendTo.js +15 -61
  77. package/build/JsonConfigComponent/ConfigSelectSendTo.js.map +1 -1
  78. package/build/JsonConfigComponent/ConfigSendto.d.ts +3 -20
  79. package/build/JsonConfigComponent/ConfigSendto.js +8 -8
  80. package/build/JsonConfigComponent/ConfigSendto.js.map +1 -1
  81. package/build/JsonConfigComponent/ConfigSetState.d.ts +1 -1
  82. package/build/JsonConfigComponent/ConfigSlider.d.ts +1 -1
  83. package/build/JsonConfigComponent/ConfigStaticDivider.d.ts +1 -1
  84. package/build/JsonConfigComponent/ConfigStaticHeader.d.ts +1 -1
  85. package/build/JsonConfigComponent/ConfigStaticImage.d.ts +1 -1
  86. package/build/JsonConfigComponent/ConfigStaticText.d.ts +1 -1
  87. package/build/JsonConfigComponent/ConfigTable.d.ts +4 -25
  88. package/build/JsonConfigComponent/ConfigTable.js +5 -4
  89. package/build/JsonConfigComponent/ConfigTable.js.map +1 -1
  90. package/build/JsonConfigComponent/ConfigTabs.d.ts +8 -33
  91. package/build/JsonConfigComponent/ConfigTabs.js +10 -43
  92. package/build/JsonConfigComponent/ConfigTabs.js.map +1 -1
  93. package/build/JsonConfigComponent/ConfigText.d.ts +7 -13
  94. package/build/JsonConfigComponent/ConfigText.js +13 -18
  95. package/build/JsonConfigComponent/ConfigText.js.map +1 -1
  96. package/build/JsonConfigComponent/ConfigTextSendTo.d.ts +7 -9
  97. package/build/JsonConfigComponent/ConfigTextSendTo.js +11 -21
  98. package/build/JsonConfigComponent/ConfigTextSendTo.js.map +1 -1
  99. package/build/JsonConfigComponent/ConfigTimePicker.d.ts +9 -3
  100. package/build/JsonConfigComponent/ConfigTimePicker.js +28 -18
  101. package/build/JsonConfigComponent/ConfigTimePicker.js.map +1 -1
  102. package/build/JsonConfigComponent/ConfigTopic.d.ts +1 -1
  103. package/build/JsonConfigComponent/ConfigUUID.d.ts +12 -13
  104. package/build/JsonConfigComponent/ConfigUUID.js +1 -6
  105. package/build/JsonConfigComponent/ConfigUUID.js.map +1 -1
  106. package/build/JsonConfigComponent/ConfigUser.d.ts +1 -1
  107. package/build/JsonConfigComponent/index.d.ts +66 -25
  108. package/build/JsonConfigComponent/index.js +48 -61
  109. package/build/JsonConfigComponent/index.js.map +1 -1
  110. package/build/index.d.ts +2 -2
  111. package/build/index.js +2 -2
  112. package/build/index.js.map +1 -1
  113. package/package.json +27 -26
  114. package/src/JsonConfig.tsx +710 -0
  115. package/src/JsonConfigComponent/ChipInput.tsx +752 -0
  116. package/src/JsonConfigComponent/ConfigAccordion.tsx +278 -0
  117. package/src/JsonConfigComponent/ConfigAlive.tsx +74 -0
  118. package/src/JsonConfigComponent/ConfigAutocomplete.tsx +108 -0
  119. package/src/JsonConfigComponent/ConfigAutocompleteSendTo.tsx +183 -0
  120. package/src/JsonConfigComponent/ConfigCRON.jsx +101 -0
  121. package/src/JsonConfigComponent/ConfigCertCollection.tsx +102 -0
  122. package/src/JsonConfigComponent/ConfigCertificateSelect.tsx +92 -0
  123. package/src/JsonConfigComponent/ConfigCertificates.tsx +202 -0
  124. package/src/JsonConfigComponent/ConfigCheckLicense.jsx +662 -0
  125. package/src/JsonConfigComponent/ConfigCheckbox.tsx +67 -0
  126. package/src/JsonConfigComponent/ConfigChip.jsx +81 -0
  127. package/src/JsonConfigComponent/ConfigColor.tsx +86 -0
  128. package/src/JsonConfigComponent/ConfigCoordinates.tsx +234 -0
  129. package/src/JsonConfigComponent/ConfigCustom.tsx +246 -0
  130. package/src/JsonConfigComponent/ConfigDatePicker.tsx +48 -0
  131. package/src/JsonConfigComponent/ConfigDeviceManager.tsx +33 -0
  132. package/src/JsonConfigComponent/ConfigFile.jsx +181 -0
  133. package/src/JsonConfigComponent/ConfigFileSelector.jsx +520 -0
  134. package/src/JsonConfigComponent/ConfigFunc.jsx +90 -0
  135. package/src/JsonConfigComponent/ConfigGeneric.tsx +1027 -0
  136. package/src/JsonConfigComponent/ConfigIP.jsx +96 -0
  137. package/src/JsonConfigComponent/ConfigImageSendTo.jsx +79 -0
  138. package/src/JsonConfigComponent/ConfigImageUpload.jsx +114 -0
  139. package/src/JsonConfigComponent/ConfigInstanceSelect.jsx +172 -0
  140. package/src/JsonConfigComponent/ConfigInterface.jsx +112 -0
  141. package/src/JsonConfigComponent/ConfigJsonEditor.jsx +103 -0
  142. package/src/JsonConfigComponent/ConfigLanguage.tsx +153 -0
  143. package/src/JsonConfigComponent/ConfigLicense.jsx +148 -0
  144. package/src/JsonConfigComponent/ConfigNumber.tsx +207 -0
  145. package/src/JsonConfigComponent/ConfigObjectId.jsx +113 -0
  146. package/src/JsonConfigComponent/ConfigPanel.tsx +360 -0
  147. package/src/JsonConfigComponent/ConfigPassword.jsx +160 -0
  148. package/src/JsonConfigComponent/ConfigPattern.jsx +50 -0
  149. package/src/JsonConfigComponent/ConfigPort.tsx +232 -0
  150. package/src/JsonConfigComponent/ConfigRoom.jsx +90 -0
  151. package/src/JsonConfigComponent/ConfigSelect.jsx +124 -0
  152. package/src/JsonConfigComponent/ConfigSelectSendTo.tsx +251 -0
  153. package/src/JsonConfigComponent/ConfigSendto.tsx +340 -0
  154. package/src/JsonConfigComponent/ConfigSetState.jsx +116 -0
  155. package/src/JsonConfigComponent/ConfigSlider.jsx +97 -0
  156. package/src/JsonConfigComponent/ConfigStaticDivider.jsx +51 -0
  157. package/src/JsonConfigComponent/ConfigStaticHeader.jsx +63 -0
  158. package/src/JsonConfigComponent/ConfigStaticImage.jsx +48 -0
  159. package/src/JsonConfigComponent/ConfigStaticText.jsx +72 -0
  160. package/src/JsonConfigComponent/ConfigTable.tsx +1040 -0
  161. package/src/JsonConfigComponent/ConfigTabs.tsx +150 -0
  162. package/src/JsonConfigComponent/ConfigText.tsx +188 -0
  163. package/src/JsonConfigComponent/ConfigTextSendTo.tsx +102 -0
  164. package/src/JsonConfigComponent/ConfigTimePicker.tsx +63 -0
  165. package/src/JsonConfigComponent/ConfigTopic.jsx +78 -0
  166. package/src/JsonConfigComponent/ConfigUUID.tsx +55 -0
  167. package/src/JsonConfigComponent/ConfigUser.jsx +104 -0
  168. package/src/JsonConfigComponent/index.tsx +435 -0
  169. package/src/JsonConfigComponent/wrapper/Components/CustomModal.jsx +145 -0
  170. package/src/JsonConfigComponent/wrapper/Components/Editor.jsx +65 -0
  171. package/src/Utils.jsx +1683 -0
  172. package/src/index.tsx +14 -0
  173. package/src/types.d.ts +372 -0
@@ -0,0 +1,153 @@
1
+ import React from 'react';
2
+ import { withStyles } from '@mui/styles';
3
+
4
+ import {
5
+ InputLabel,
6
+ MenuItem,
7
+ FormHelperText,
8
+ FormControl,
9
+ Select,
10
+ } from '@mui/material';
11
+
12
+ import { I18n } from '@iobroker/adapter-react-v5';
13
+
14
+ import type { ConfigItemLanguage } from '#JC/types';
15
+ import ConfigGeneric, { type ConfigGenericProps, type ConfigGenericState } from './ConfigGeneric';
16
+
17
+ const styles: Record<string, any> = {
18
+ fullWidth: {
19
+ width: '100%',
20
+ },
21
+ };
22
+
23
+ const LANGUAGES = [
24
+ {
25
+ value: 'en',
26
+ label: 'English',
27
+ },
28
+ {
29
+ value: 'de',
30
+ label: 'Deutsch',
31
+ },
32
+ {
33
+ value: 'ru',
34
+ label: 'русский',
35
+ },
36
+ {
37
+ value: 'pt',
38
+ label: 'Portugues',
39
+ },
40
+ {
41
+ value: 'nl',
42
+ label: 'Nederlands',
43
+ },
44
+ {
45
+ value: 'fr',
46
+ label: 'français',
47
+ },
48
+ {
49
+ value: 'it',
50
+ label: 'Italiano',
51
+ },
52
+ {
53
+ value: 'es',
54
+ label: 'Espanol',
55
+ },
56
+ {
57
+ value: 'pl',
58
+ label: 'Polski',
59
+ },
60
+ {
61
+ value: 'uk',
62
+ label: 'Український',
63
+ },
64
+ {
65
+ value: 'zh-ch',
66
+ label: '简体中文',
67
+ },
68
+ ] as const;
69
+
70
+ interface LanguageSelectOption {
71
+ /** Value to save */
72
+ value: string;
73
+ /** Label to show */
74
+ label: string;
75
+ }
76
+
77
+ interface ConfigLanguageProps extends ConfigGenericProps {
78
+ schema: ConfigItemLanguage;
79
+ }
80
+
81
+ interface ConfigLanguageState extends ConfigGenericState {
82
+ selectOptions: LanguageSelectOption[];
83
+ }
84
+
85
+ class ConfigLanguage extends ConfigGeneric<ConfigLanguageProps, ConfigLanguageState> {
86
+ componentDidMount() {
87
+ super.componentDidMount();
88
+ const value = ConfigGeneric.getValue(this.props.data, this.props.attr);
89
+ const languages: LanguageSelectOption[] = [...LANGUAGES];
90
+ if (this.props.schema.system) {
91
+ languages.unshift({ value: '', label: I18n.t('ra_System language') });
92
+ } else {
93
+ languages.unshift({ value: '', label: I18n.t('ra_none') });
94
+ }
95
+
96
+ this.setState({ value: this.props.schema.system ? (value || '') : (value || I18n.getLanguage()), selectOptions: languages });
97
+ }
98
+
99
+ renderItem(error: unknown, disabled: boolean): React.JSX.Element | null {
100
+ if (!this.state.selectOptions) {
101
+ return null;
102
+ }
103
+
104
+ const item = this.state.selectOptions?.find(it => it.value === this.state.value || (!it.value && !this.state.value));
105
+
106
+ return <FormControl className={this.props.classes.fullWidth} variant="standard">
107
+ {this.props.schema.label ? <InputLabel>{this.getText(this.props.schema.label)}</InputLabel> : null}
108
+ <Select
109
+ variant="standard"
110
+ error={!!error}
111
+ disabled={disabled}
112
+ value={this.state.value || '_'}
113
+ renderValue={() => this.getText(item?.label, this.props.schema.noTranslation)}
114
+ onChange={e => {
115
+ let { value } = e.target;
116
+ if (value === '_') {
117
+ value = '';
118
+ }
119
+
120
+ this.setState({ value }, () => {
121
+ this.onChange(this.props.attr, value);
122
+ if (this.props.schema.changeGuiLanguage) {
123
+ if (value) {
124
+ if (value === I18n.getLanguage()) {
125
+ return;
126
+ }
127
+ I18n.setLanguage(value);
128
+ this.props.changeLanguage && this.props.changeLanguage();
129
+ } else {
130
+ this.props.socket.getSystemConfig()
131
+ .then((systemConfig: ioBroker.SystemConfigObject) => {
132
+ if (systemConfig.common.language === I18n.getLanguage()) {
133
+ return;
134
+ }
135
+ if (systemConfig.common.language) {
136
+ I18n.setLanguage(systemConfig.common.language);
137
+ this.props.changeLanguage && this.props.changeLanguage();
138
+ }
139
+ });
140
+ }
141
+ }
142
+ });
143
+ }}
144
+ >
145
+ {this.state.selectOptions?.map(it =>
146
+ <MenuItem key={it.value} value={it.value}>{it.label}</MenuItem>)}
147
+ </Select>
148
+ {this.props.schema.help ? <FormHelperText>{this.renderHelp(this.props.schema.help, this.props.schema.helpLink, this.props.schema.noTranslation)}</FormHelperText> : null}
149
+ </FormControl>;
150
+ }
151
+ }
152
+
153
+ export default withStyles(styles)(ConfigLanguage);
@@ -0,0 +1,148 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+
4
+ import {
5
+ Button,
6
+ Dialog,
7
+ DialogActions,
8
+ DialogContent,
9
+ DialogTitle,
10
+ LinearProgress,
11
+ FormControlLabel,
12
+ Checkbox,
13
+ } from '@mui/material';
14
+
15
+ import { Check, Close } from '@mui/icons-material';
16
+
17
+ import { I18n } from '@iobroker/adapter-react-v5';
18
+
19
+ import ConfigGeneric from './ConfigGeneric';
20
+
21
+ class ConfigLicense extends ConfigGeneric {
22
+ constructor(props) {
23
+ super(props);
24
+ this.scrollRef = React.createRef();
25
+ this.noPlaceRequired = true;
26
+ }
27
+
28
+ scrolledDown() {
29
+ if (!this.scrollRef.current) {
30
+ return false;
31
+ }
32
+ return this.scrollRef.current.offsetHeight + this.scrollRef.current.scrollTop >= this.scrollRef.current.scrollHeight;
33
+ }
34
+
35
+ componentDidMount() {
36
+ super.componentDidMount();
37
+ if (!ConfigGeneric.getValue(this.props.data, this.props.attr)) {
38
+ if (this.props.schema.licenseUrl) {
39
+ this.setState({ showLicenseDialog: true, loading: true, scrolledDown: false });
40
+ fetch(this.props.schema.licenseUrl)
41
+ .then(res => res.text())
42
+ .then(text => this.setState({ license: text, loading: false }))
43
+ .catch(e => this.setState({
44
+ license: e.toString(), loading: false, error: true, scrolledDown: false,
45
+ }));
46
+ } else {
47
+ this.setState({ showLicenseDialog: true, scrolledDown: false });
48
+ }
49
+ setTimeout(() => {
50
+ // install scroll handler
51
+ if (this.scrollRef.current) {
52
+ const scrolledDown = this.scrolledDown();
53
+ if (!scrolledDown) {
54
+ this.scrollRef.current.addEventListener('scroll', () => {
55
+ if (!this.state.scrolledDown && this.scrolledDown()) {
56
+ this.setState({ scrolledDown: true });
57
+ }
58
+ });
59
+ } else {
60
+ this.setState({ scrolledDown: true });
61
+ }
62
+ }
63
+ }, 1000);
64
+ }
65
+ }
66
+
67
+ renderItem(/* error, disabled, defaultValue */) {
68
+ if (!this.state.showLicenseDialog) {
69
+ return null;
70
+ }
71
+
72
+ return <Dialog
73
+ maxWidth="lg"
74
+ open={!0}
75
+ onClose={(e, reason) => {
76
+ if (reason !== 'escapeKeyDown' && reason !== 'backdropClick') {
77
+ this.setState({ showLicenseDialog: false });
78
+ }
79
+ }}
80
+ >
81
+ <DialogTitle>{this.props.schema.title ? I18n.t(this.props.schema.title) : I18n.t('ra_License agreement')}</DialogTitle>
82
+ <DialogContent>
83
+ {this.props.schema.licenseUrl ? <>
84
+ {this.state.loading ? <LinearProgress /> : null}
85
+ <pre
86
+ ref={this.scrollRef}
87
+ style={{
88
+ width: '100%', height: '100%', overflowY: 'auto', fontSize: 14,
89
+ }}
90
+ >
91
+ {this.state.license}
92
+ </pre>
93
+ </> : null}
94
+ {!this.props.schema.licenseUrl && this.props.schema.texts ? <div
95
+ ref={this.scrollRef}
96
+ style={{
97
+ width: '100%', height: '100%', overflowY: 'auto', fontSize: 14,
98
+ }}
99
+ >
100
+ {this.props.schema.texts.map(text => (this.props.schema.noTranslation ? <p>{text}</p> : <p>{I18n.t(text)}</p>))}
101
+ </div> : null}
102
+ </DialogContent>
103
+ <DialogActions>
104
+ {this.props.schema.checkBox ? <FormControlLabel
105
+ control={<Checkbox checked={!!this.state.licenseChecked} onClick={() => this.setState({ licenseChecked: !this.state.licenseChecked })} />}
106
+ label={I18n.t(this.props.schema.checkBox)}
107
+ /> : null}
108
+ <Button
109
+ disabled={this.state.loading || this.state.error || (this.props.schema.checkBox && !this.state.licenseChecked) || !this.state.scrolledDown}
110
+ onClick={() => {
111
+ this.setState({ showLicenseDialog: null });
112
+ this.onChange(this.props.attr, true);
113
+ }}
114
+ color="primary"
115
+ variant="contained"
116
+ startIcon={<Check />}
117
+ >
118
+ {this.props.schema.agreeText ? I18n.t(this.props.schema.agreeText) : I18n.t('ra_Accept license')}
119
+ </Button>
120
+ <Button
121
+ onClick={() => {
122
+ this.setState({ showLicenseDialog: false });
123
+ setTimeout(() => this.setState({ showLicenseDialog: true }), 2000);
124
+ }}
125
+ color="grey"
126
+ variant="contained"
127
+ startIcon={<Close />}
128
+ >
129
+ {I18n.t('ra_Close')}
130
+ </Button>
131
+ </DialogActions>
132
+ </Dialog>;
133
+ }
134
+ }
135
+
136
+ ConfigLicense.propTypes = {
137
+ socket: PropTypes.object.isRequired,
138
+ themeType: PropTypes.string,
139
+ themeName: PropTypes.string,
140
+ style: PropTypes.object,
141
+ className: PropTypes.string,
142
+ data: PropTypes.object.isRequired,
143
+ schema: PropTypes.object,
144
+ onError: PropTypes.func,
145
+ onChange: PropTypes.func,
146
+ };
147
+
148
+ export default ConfigLicense;
@@ -0,0 +1,207 @@
1
+ import React from 'react';
2
+ import { withStyles } from '@mui/styles';
3
+
4
+ import { Autocomplete, TextField, FormControl } from '@mui/material';
5
+
6
+ import { I18n } from '@iobroker/adapter-react-v5';
7
+
8
+ import type { ConfigItemNumber } from '#JC/types';
9
+ import ConfigGeneric, { type ConfigGenericProps, type ConfigGenericState } from './ConfigGeneric';
10
+
11
+ const styles: Record<string, any> = {
12
+ indeterminate: {
13
+ opacity: 0.5,
14
+ },
15
+ control: {
16
+ flexDirection: 'row',
17
+ width: '100%',
18
+ },
19
+ };
20
+
21
+ interface ConfigNumberProps extends ConfigGenericProps {
22
+ schema: ConfigItemNumber;
23
+ }
24
+
25
+ interface ConfigNumberState extends ConfigGenericState {
26
+ _value: string;
27
+ oldValue: string | null;
28
+ }
29
+
30
+ class ConfigNumber extends ConfigGeneric<ConfigNumberProps, ConfigNumberState> {
31
+ private updateTimeout?: ReturnType<typeof setTimeout>;
32
+
33
+ componentDidMount() {
34
+ super.componentDidMount();
35
+ let _value = ConfigGeneric.getValue(this.props.data, this.props.attr);
36
+
37
+ if (_value === null || _value === undefined) {
38
+ _value = '';
39
+ }
40
+
41
+ if (Array.isArray(_value) && this.props.multiEdit) {
42
+ _value = ConfigGeneric.DIFFERENT_VALUE;
43
+ this.setState({ _value, oldValue: _value });
44
+ return;
45
+ }
46
+
47
+ this.setState({ _value: _value.toString(), oldValue: _value.toString() });
48
+ }
49
+
50
+ static getDerivedStateFromProps(props: ConfigNumberProps, state: ConfigNumberState) {
51
+ if (
52
+ (props.schema.min !== undefined && props.schema.min < 0) ||
53
+ (props.schema.max !== undefined && props.schema.max < 0)
54
+ ) {
55
+ return null;
56
+ }
57
+ const _value = ConfigGeneric.getValue(props.data, props.attr);
58
+
59
+ if (props.multiEdit && state._value === ConfigGeneric.DIFFERENT_VALUE) {
60
+ return ConfigGeneric.DIFFERENT_VALUE;
61
+ }
62
+
63
+ if (
64
+ _value === null ||
65
+ _value === undefined ||
66
+ state.oldValue === null ||
67
+ state.oldValue === undefined ||
68
+ (_value.toString() !== parseFloat(state._value).toString() &&
69
+ _value.toString() !== state.oldValue.toString())
70
+ ) {
71
+ return { _value };
72
+ }
73
+
74
+ return null;
75
+ }
76
+
77
+ checkValue(value: string): string | null {
78
+ if (value === null || value === undefined) {
79
+ return null;
80
+ }
81
+ value = value.toString().trim();
82
+ const f = value === '' ? 0 : parseFloat(value);
83
+
84
+ if (value !== '' && Number.isNaN(f)) {
85
+ return 'ra_Not a number';
86
+ }
87
+
88
+ // eslint-disable-next-line no-restricted-properties
89
+ if (value !== '' && window.isFinite(f)) {
90
+ if (this.props.schema.min !== undefined && f < this.props.schema.min) {
91
+ return 'ra_Too small';
92
+ }
93
+ if (this.props.schema.max !== undefined && f > this.props.schema.max) {
94
+ return 'ra_Too big';
95
+ }
96
+ if (value === '' || value === '-' || Number.isNaN(f)) {
97
+ return 'ra_Not a number';
98
+ }
99
+
100
+ return null;
101
+ }
102
+
103
+ return 'ra_Not a number';
104
+ }
105
+
106
+ renderItem(error: unknown, disabled: boolean) {
107
+ const isIndeterminate = Array.isArray(this.state._value) || this.state._value === ConfigGeneric.DIFFERENT_VALUE;
108
+
109
+ if (this.state.oldValue !== null && this.state.oldValue !== undefined) {
110
+ this.updateTimeout && clearTimeout(this.updateTimeout);
111
+ this.updateTimeout = setTimeout(() => {
112
+ this.updateTimeout = undefined;
113
+ this.setState({ oldValue: null });
114
+ }, 30);
115
+ } else if (this.updateTimeout) {
116
+ clearTimeout(this.updateTimeout);
117
+ this.updateTimeout = undefined;
118
+ }
119
+
120
+ if (isIndeterminate) {
121
+ const autoCompleteOptions = ConfigGeneric.getValue(this.props.data, this.props.attr);
122
+ const arr = [...autoCompleteOptions].map(item => ({ label: item.toString(), value: item }));
123
+
124
+ arr.unshift({ label: I18n.t(ConfigGeneric.DIFFERENT_LABEL), value: ConfigGeneric.DIFFERENT_VALUE });
125
+
126
+ return <Autocomplete
127
+ className={this.props.classes.indeterminate}
128
+ fullWidth
129
+ freeSolo
130
+ value={arr[0]}
131
+ // @ts-expect-error needs investigation if this really has no effect
132
+ getOptionSelected={(option, value) => option.label === value.label}
133
+ onChange={(_, value: typeof arr[number]) => {
134
+ this.onChange(this.props.attr, value?.value, () => {
135
+ this.setState({ _value: value?.value, oldValue: this.state._value });
136
+ });
137
+ }}
138
+ options={arr}
139
+ getOptionLabel={(option: typeof arr[number]) => option.label}
140
+ renderInput={params => (
141
+ <TextField
142
+ {...params}
143
+ label={this.getText(this.props.schema.label)}
144
+ variant="standard"
145
+ inputProps={{ ...params.inputProps, readOnly: this.props.schema.readOnly || false }}
146
+ error={!!error}
147
+ placeholder={this.getText(this.props.schema.placeholder)}
148
+ helperText={this.renderHelp(
149
+ this.props.schema.help,
150
+ this.props.schema.helpLink,
151
+ this.props.schema.noTranslation,
152
+ )}
153
+ disabled={!!disabled}
154
+ />
155
+ )}
156
+ />;
157
+ }
158
+ if (!error && this.state._value !== null && this.state._value !== undefined && this.state._value) {
159
+ error = this.checkValue(this.state._value);
160
+ if (error) {
161
+ error = I18n.t(error as string);
162
+ }
163
+ }
164
+
165
+ return <FormControl variant="standard" className={this.props.classes.control}>
166
+ <TextField
167
+ variant="standard"
168
+ type="number"
169
+ fullWidth
170
+ inputProps={{
171
+ min: this.props.schema.min,
172
+ max: this.props.schema.max,
173
+ step: this.props.schema.step,
174
+ readOnly: this.props.schema.readOnly || false,
175
+ }}
176
+ value={this.state._value === null || this.state._value === undefined ? '' : this.state._value}
177
+ error={!!error}
178
+ disabled={!!disabled}
179
+ onChange={e => {
180
+ const _value = e.target.value; // value is always a string and it is validly formatted
181
+ const _error = this.checkValue(_value);
182
+ if (_error) {
183
+ this.onError(this.props.attr, I18n.t(_error));
184
+ } else {
185
+ this.onError(this.props.attr); // clear error
186
+ }
187
+
188
+ this.setState({ _value, oldValue: this.state._value }, () =>
189
+ this.onChange(this.props.attr, parseFloat(_value)));
190
+ }}
191
+ placeholder={this.getText(this.props.schema.placeholder)}
192
+ label={this.getText(this.props.schema.label)}
193
+ helperText={
194
+ error && typeof error === 'string'
195
+ ? error
196
+ : this.renderHelp(
197
+ this.props.schema.help,
198
+ this.props.schema.helpLink,
199
+ this.props.schema.noTranslation,
200
+ )
201
+ }
202
+ />
203
+ </FormControl>;
204
+ }
205
+ }
206
+
207
+ export default withStyles(styles)(ConfigNumber);
@@ -0,0 +1,113 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { withStyles } from '@mui/styles';
4
+
5
+ import {
6
+ InputLabel,
7
+ FormControl,
8
+ Button,
9
+ TextField,
10
+ } from '@mui/material';
11
+
12
+ import { SelectID as DialogSelectID } from '@iobroker/adapter-react-v5';
13
+
14
+ import ConfigGeneric from './ConfigGeneric';
15
+
16
+ const styles = () => ({
17
+ fullWidth: {
18
+ width: '100%',
19
+ },
20
+ flex: {
21
+ display: 'flex',
22
+ },
23
+ button: {
24
+ height: 48,
25
+ marginLeft: 4,
26
+ minWidth: 48,
27
+ },
28
+ });
29
+
30
+ class ConfigObjectId extends ConfigGeneric {
31
+ async componentDidMount() {
32
+ super.componentDidMount();
33
+ const { data, attr } = this.props;
34
+ const value = ConfigGeneric.getValue(data, attr) || '';
35
+ this.setState({ value, initialized: true });
36
+ }
37
+
38
+ renderItem(error, disabled /* , defaultValue */) {
39
+ if (!this.state.initialized) {
40
+ return null;
41
+ }
42
+ const {
43
+ classes, schema, socket, attr,
44
+ } = this.props;
45
+ const { value, showSelectId } = this.state;
46
+
47
+ return <FormControl className={classes.fullWidth} variant="standard">
48
+ {schema.label ? <InputLabel shrink>{this.getText(schema.label)}</InputLabel> : null}
49
+ <div className={classes.flex}>
50
+ <TextField
51
+ variant="standard"
52
+ fullWidth
53
+ value={value}
54
+ error={!!error}
55
+ disabled={disabled}
56
+ placeholder={this.getText(schema.placeholder)}
57
+ label={this.getText(schema.label)}
58
+ helperText={this.renderHelp(schema.help, schema.helpLink, schema.noTranslation)}
59
+ onChange={e => {
60
+ const value_ = e.target.value;
61
+ this.setState({ value: value_ }, () =>
62
+ this.onChange(attr, value_));
63
+ }}
64
+ />
65
+ <Button
66
+ color="grey"
67
+ className={this.props.classes.button}
68
+ size="small"
69
+ variant="outlined"
70
+ onClick={() => this.setState({ showSelectId: true })}
71
+ >
72
+ ...
73
+ </Button>
74
+ </div>
75
+ {showSelectId ? <DialogSelectID
76
+ imagePrefix={this.props.imagePrefix === undefined ? '../..' : this.props.imagePrefix}
77
+ dateFormat={this.props.dateFormat}
78
+ isFloatComma={this.props.isFloatComma}
79
+ dialogName={`admin.${this.props.adapterName}`}
80
+ filterFunc={schema.filterFunc}
81
+ themeType={this.props.themeType}
82
+ types={schema.types ? (Array.isArray(schema.types) ? schema.types : [schema.types]) : undefined}
83
+ customFilter={schema.customFilter}
84
+ filters={schema.filters}
85
+ socket={socket}
86
+ statesOnly={schema.all === undefined ? true : schema.all}
87
+ selected={value}
88
+ root={schema.root}
89
+ onClose={() => this.setState({ showSelectId: false })}
90
+ onOk={value_ =>
91
+ this.setState({ showSelectId: false, value: value_ }, () =>
92
+ this.onChange(attr, value_))}
93
+ /> : null}
94
+ </FormControl>;
95
+ }
96
+ }
97
+
98
+ ConfigObjectId.propTypes = {
99
+ socket: PropTypes.object.isRequired,
100
+ themeType: PropTypes.string,
101
+ themeName: PropTypes.string,
102
+ style: PropTypes.object,
103
+ className: PropTypes.string,
104
+ data: PropTypes.object.isRequired,
105
+ schema: PropTypes.object,
106
+ onError: PropTypes.func,
107
+ onChange: PropTypes.func,
108
+ dateFormat: PropTypes.string,
109
+ isFloatComma: PropTypes.bool,
110
+ imagePrefix: PropTypes.string,
111
+ };
112
+
113
+ export default withStyles(styles)(ConfigObjectId);