@iobroker/json-config 9.0.3 → 9.0.4
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 +1 -1
- package/build/JsonConfigComponent/ConfigCustom.d.ts +5 -0
- package/build/JsonConfigComponent/ConfigCustom.js +22 -2
- package/build/JsonConfigComponent/ConfigCustom.js.map +1 -1
- package/build/JsonConfigComponent/guiApiGate.d.ts +42 -0
- package/build/JsonConfigComponent/guiApiGate.js +106 -0
- package/build/JsonConfigComponent/guiApiGate.js.map +1 -0
- package/build/JsonConfigComponent/i18n/de.json +3 -0
- package/build/JsonConfigComponent/i18n/en.json +3 -0
- package/build/JsonConfigComponent/i18n/es.json +5 -0
- package/build/JsonConfigComponent/i18n/fr.json +5 -0
- package/build/JsonConfigComponent/i18n/it.json +5 -0
- package/build/JsonConfigComponent/i18n/nl.json +5 -0
- package/build/JsonConfigComponent/i18n/pl.json +5 -0
- package/build/JsonConfigComponent/i18n/pt.json +5 -0
- package/build/JsonConfigComponent/i18n/ru.json +5 -0
- package/build/JsonConfigComponent/i18n/uk.json +5 -0
- package/build/JsonConfigComponent/i18n/zh-cn.json +5 -0
- package/build/JsonConfigComponent/wrapper/Components/Editor.d.ts +0 -1
- package/build/JsonConfigComponent/wrapper/Components/Editor.js +5 -1
- package/build/JsonConfigComponent/wrapper/Components/Editor.js.map +1 -1
- package/build/index.d.ts +1 -11
- package/build/index.js +1 -11
- package/build/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1822,7 +1822,7 @@ The schema is used here: https://github.com/SchemaStore/schemastore/blob/6da29cd
|
|
|
1822
1822
|
### **WORK IN PROGRESS**
|
|
1823
1823
|
-->
|
|
1824
1824
|
## Changelog
|
|
1825
|
-
### 9.0.
|
|
1825
|
+
### 9.0.4 (2026-07-26)
|
|
1826
1826
|
- (@GermanBluefox) Breaking: React 19 + MUI 9 + TS 6
|
|
1827
1827
|
- (@GermanBluefox) Added loading of the new custom components
|
|
1828
1828
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React, { type JSX } from 'react';
|
|
2
2
|
import ConfigGeneric, { type ConfigGenericProps, type ConfigGenericState } from './ConfigGeneric';
|
|
3
|
+
import { type GuiApiVerdict } from './guiApiGate';
|
|
3
4
|
import type { ConfigItemCustom } from '../types';
|
|
4
5
|
interface ConfigCustomProps extends ConfigGenericProps {
|
|
5
6
|
schema: ConfigItemCustom;
|
|
@@ -7,6 +8,8 @@ interface ConfigCustomProps extends ConfigGenericProps {
|
|
|
7
8
|
interface ConfigCustomState extends ConfigGenericState {
|
|
8
9
|
Component: React.FC<ConfigGenericProps> | null;
|
|
9
10
|
error: string;
|
|
11
|
+
/** Set when the component was refused by the GUI API gate, so it was never loaded */
|
|
12
|
+
incompatible: GuiApiVerdict | null;
|
|
10
13
|
}
|
|
11
14
|
export default class ConfigCustom extends ConfigGeneric<ConfigCustomProps, ConfigCustomState> {
|
|
12
15
|
static runningLoads: Record<string, Promise<{
|
|
@@ -14,6 +17,8 @@ export default class ConfigCustom extends ConfigGeneric<ConfigCustomProps, Confi
|
|
|
14
17
|
} | null>>;
|
|
15
18
|
constructor(props: ConfigCustomProps);
|
|
16
19
|
componentDidMount(): Promise<void>;
|
|
20
|
+
/** Explain why a component was not started, and what the user can do about it */
|
|
21
|
+
renderIncompatible(verdict: GuiApiVerdict): JSX.Element;
|
|
17
22
|
render(): JSX.Element;
|
|
18
23
|
}
|
|
19
24
|
export {};
|
|
@@ -3,9 +3,10 @@ import { LinearProgress } from '@mui/material';
|
|
|
3
3
|
import { registerRemotes, loadRemote, init } from '@module-federation/runtime';
|
|
4
4
|
import * as IconsMaterial from '@mui/icons-material';
|
|
5
5
|
import * as AdapterReact from '@iobroker/gui-components';
|
|
6
|
-
import { I18n } from '@iobroker/gui-components';
|
|
6
|
+
import { I18n, InfoBox } from '@iobroker/gui-components';
|
|
7
7
|
import ConfigGeneric from './ConfigGeneric';
|
|
8
8
|
import ConfigCustomErrorBoundary from './ConfigCustomErrorBoundary';
|
|
9
|
+
import { checkGuiApiCompatibility, GUI_API_GENERATION } from './guiApiGate';
|
|
9
10
|
import * as JsonConfig from '../';
|
|
10
11
|
init({
|
|
11
12
|
name: 'iobroker_admin',
|
|
@@ -35,6 +36,7 @@ export default class ConfigCustom extends ConfigGeneric {
|
|
|
35
36
|
Object.assign(this.state, {
|
|
36
37
|
Component: null,
|
|
37
38
|
error: '',
|
|
39
|
+
incompatible: null,
|
|
38
40
|
});
|
|
39
41
|
}
|
|
40
42
|
// load component dynamically
|
|
@@ -64,6 +66,15 @@ export default class ConfigCustom extends ConfigGeneric {
|
|
|
64
66
|
console.error('Invalid format of "name"! Please define "name" as "ConfigCustomBackItUpSet/Components/AdapterExist" in the schema');
|
|
65
67
|
return;
|
|
66
68
|
}
|
|
69
|
+
// Refuse an incompatible component before it is registered: it shares this admin's React and
|
|
70
|
+
// MUI singletons, so one built against another generation would break while rendering.
|
|
71
|
+
const verdict = await checkGuiApiCompatibility(url, this.props.schema.guiApi);
|
|
72
|
+
if (!verdict.compatible) {
|
|
73
|
+
console.warn(`Custom component "${this.props.schema.name}" from "${url}" was not started: it targets ` +
|
|
74
|
+
`GUI API generation ${verdict.declared}, but this admin provides generation ${GUI_API_GENERATION}.`);
|
|
75
|
+
this.setState({ incompatible: verdict });
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
67
78
|
let setPromise = ConfigCustom.runningLoads[`${url}!${fileToLoad}`];
|
|
68
79
|
if (!(setPromise instanceof Promise)) {
|
|
69
80
|
let i18nPromise;
|
|
@@ -143,13 +154,22 @@ export default class ConfigCustom extends ConfigGeneric {
|
|
|
143
154
|
this.setState({ error: `Cannot import from ${this.props.schema.url}: ${error}` });
|
|
144
155
|
}
|
|
145
156
|
}
|
|
157
|
+
/** Explain why a component was not started, and what the user can do about it */
|
|
158
|
+
renderIncompatible(verdict) {
|
|
159
|
+
return (React.createElement(InfoBox, { type: "warning", iconPosition: "top" },
|
|
160
|
+
React.createElement("div", null,
|
|
161
|
+
React.createElement("div", { style: { fontWeight: 'bold' } }, I18n.t('jc_Custom component "%s" was not started', this.props.schema.name)),
|
|
162
|
+
React.createElement("div", null, verdict.tooNew
|
|
163
|
+
? I18n.t('jc_It requires GUI API generation %s, but this admin provides generation %s. Please update the admin.', verdict.declared, GUI_API_GENERATION)
|
|
164
|
+
: I18n.t('jc_It was built for GUI API generation %s, but this admin provides generation %s. Please update the adapter.', verdict.declared, GUI_API_GENERATION)))));
|
|
165
|
+
}
|
|
146
166
|
render() {
|
|
147
167
|
const CustomComponent = this.state.Component;
|
|
148
168
|
const schema = this.props.schema || {};
|
|
149
169
|
const item = CustomComponent ? (React.createElement(ConfigCustomErrorBoundary, { name: schema.name, url: schema.url },
|
|
150
170
|
React.createElement(CustomComponent, { ...this.props,
|
|
151
171
|
// @ts-expect-error BF (2024-12-18) Remove after the 7.4 will be mainstream. All following lines
|
|
152
|
-
socket: this.props.oContext.socket, theme: this.props.oContext.theme, themeType: this.props.oContext.themeType, instance: this.props.oContext.instance, adapterName: this.props.oContext.adapterName, systemConfig: this.props.oContext.systemConfig, forceUpdate: this.props.oContext.forceUpdate }))) : this.state.error ? (React.createElement("div", null, this.state.error)) : (React.createElement(LinearProgress, null));
|
|
172
|
+
socket: this.props.oContext.socket, theme: this.props.oContext.theme, themeType: this.props.oContext.themeType, instance: this.props.oContext.instance, adapterName: this.props.oContext.adapterName, systemConfig: this.props.oContext.systemConfig, forceUpdate: this.props.oContext.forceUpdate }))) : this.state.incompatible ? (this.renderIncompatible(this.state.incompatible)) : this.state.error ? (React.createElement("div", null, this.state.error)) : (React.createElement(LinearProgress, null));
|
|
153
173
|
if (schema.newLine) {
|
|
154
174
|
return (React.createElement(React.Fragment, null,
|
|
155
175
|
React.createElement("div", { style: { flexBasis: '100%', height: 0 } }),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConfigCustom.js","sourceRoot":"src/","sources":["JsonConfigComponent/ConfigCustom.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { type JSX } from 'react';\nimport { LinearProgress } from '@mui/material';\nimport { registerRemotes, loadRemote, init } from '@module-federation/runtime';\n\nimport * as IconsMaterial from '@mui/icons-material';\n\nimport * as AdapterReact from '@iobroker/gui-components';\nimport { I18n } from '@iobroker/gui-components';\n\nimport ConfigGeneric, { type ConfigGenericProps, type ConfigGenericState } from './ConfigGeneric';\nimport ConfigCustomErrorBoundary from './ConfigCustomErrorBoundary';\nimport * as JsonConfig from '../';\nimport type { ConfigItemCustom } from '../types';\n\ninterface ConfigCustomProps extends ConfigGenericProps {\n schema: ConfigItemCustom;\n}\n\ninterface ConfigCustomState extends ConfigGenericState {\n Component: React.FC<ConfigGenericProps> | null;\n error: string;\n}\n\ninit({\n name: 'iobroker_admin',\n shared: {\n '@iobroker/gui-components': {\n lib: () => AdapterReact,\n version: '*',\n },\n '@mui/icons-material': {\n lib: () => IconsMaterial,\n version: '*',\n },\n '@iobroker/json-config': {\n lib: () => JsonConfig,\n version: '*',\n },\n },\n remotes: [],\n});\n\nexport default class ConfigCustom extends ConfigGeneric<ConfigCustomProps, ConfigCustomState> {\n static runningLoads: Record<string, Promise<{ default: Record<string, React.FC<ConfigGenericProps>> } | null>> = {};\n\n constructor(props: ConfigCustomProps) {\n super(props);\n // schema.url - location of Widget\n // schema.name - Component name\n // schema.i18n - i18n\n\n Object.assign(this.state, {\n Component: null,\n error: '',\n });\n }\n\n // load component dynamically\n async componentDidMount(): Promise<void> {\n if (!this.props.schema.url) {\n console.error('URL is empty. Cannot load custom component!');\n this.setState({ error: 'URL is empty. Cannot load custom component!' });\n return;\n }\n\n let url;\n if (this.props.schema.url.startsWith('http:') || this.props.schema.url.startsWith('https:')) {\n url = this.props.schema.url;\n } else if (this.props.schema.url.startsWith('./')) {\n url = `${window.location.protocol}//${window.location.host}${this.props.schema.url.replace(/^\\./, '')}`;\n } else {\n url = `${window.location.protocol}//${window.location.host}/adapter/${this.props.oContext.adapterName}/${this.props.schema.url}`;\n }\n const [uniqueName, fileToLoad, ...componentNameParts] = this.props.schema.name.split('/');\n const componentName = componentNameParts.join('/');\n if (!url) {\n console.error(\n 'Cannot find URL for custom component! Please define \"url\" as \"custom/customComponents.js\" in the schema',\n );\n return;\n }\n if (!uniqueName || !fileToLoad || !componentName) {\n console.error(\n 'Invalid format of \"name\"! Please define \"name\" as \"ConfigCustomBackItUpSet/Components/AdapterExist\" in the schema',\n );\n return;\n }\n let setPromise: Promise<{ default: Record<string, React.FC<ConfigGenericProps>> } | null> | undefined =\n ConfigCustom.runningLoads[`${url}!${fileToLoad}`];\n\n if (!(setPromise instanceof Promise)) {\n let i18nPromise: Promise<void> | undefined;\n if (this.props.schema.i18n === true) {\n // load i18n from files\n const pos = url.lastIndexOf('/');\n let i18nURL: string;\n if (pos !== -1) {\n i18nURL = url.substring(0, pos);\n } else {\n i18nURL = url;\n }\n const lang = I18n.getLanguage();\n const file = `${i18nURL}/i18n/${lang}.json`;\n\n i18nPromise = fetch(file)\n .then(data => data.json())\n .then(json => I18n.extendTranslations(json, lang))\n .catch(error => {\n if (lang !== 'en') {\n // try to load English\n fetch(`${i18nURL}/i18n/en.json`)\n .then(data => data.json())\n .then(json => I18n.extendTranslations(json, lang))\n .catch(err => console.log(`Cannot load i18n \"${file}\": ${err}`));\n return;\n }\n console.log(`Cannot load i18n \"${file}\": ${error}`);\n });\n } else if (this.props.schema.i18n && typeof this.props.schema.i18n === 'object') {\n try {\n I18n.extendTranslations(this.props.schema.i18n);\n } catch (error) {\n console.error(`Cannot import i18n: ${error}`);\n }\n }\n try {\n console.log(url, uniqueName, fileToLoad, componentName);\n\n registerRemotes(\n [\n {\n name: uniqueName,\n entry: url,\n // Components of the current GUI API generation are always built as ES\n // modules, so the former `bundlerType` schema attribute is obsolete.\n type: 'module',\n },\n ],\n // force: true // may be needed to side-load remotes after the fact.\n );\n setPromise = loadRemote(`${uniqueName}/${fileToLoad}`);\n if (i18nPromise instanceof Promise) {\n setPromise = Promise.all([setPromise, i18nPromise]).then(result => result[0]);\n }\n // remember promise\n ConfigCustom.runningLoads[`${url}!${fileToLoad}`] = setPromise;\n } catch (error) {\n console.error(error);\n this.setState({ error: `Cannot import from ${this.props.schema.url}: ${error}` });\n }\n }\n try {\n const component: Record<string, React.FC<ConfigGenericProps>> | undefined = (await setPromise)?.default;\n\n if (!component?.[componentName]) {\n const keys = Object.keys(component || {});\n console.error('URL is empty. Cannot load custom component!');\n this.setState({\n error: `Component ${this.props.schema.name} not found in ${this.props.schema.url}. Found: ${keys.join(', ')}`,\n });\n } else {\n this.setState({ Component: component[componentName] });\n }\n } catch (error) {\n console.error(error);\n this.setState({ error: `Cannot import from ${this.props.schema.url}: ${error}` });\n }\n }\n\n render(): JSX.Element {\n const CustomComponent: React.FC<ConfigGenericProps> | null = this.state.Component;\n const schema = this.props.schema || ({} as ConfigItemCustom);\n\n const item = CustomComponent ? (\n // The custom component is third-party code, so a render error must not take down the\n // whole configuration page with it.\n <ConfigCustomErrorBoundary\n name={schema.name}\n url={schema.url}\n >\n <CustomComponent\n {...this.props}\n // @ts-expect-error BF (2024-12-18) Remove after the 7.4 will be mainstream. All following lines\n socket={this.props.oContext.socket}\n theme={this.props.oContext.theme}\n themeType={this.props.oContext.themeType}\n instance={this.props.oContext.instance}\n adapterName={this.props.oContext.adapterName}\n systemConfig={this.props.oContext.systemConfig}\n forceUpdate={this.props.oContext.forceUpdate}\n />\n </ConfigCustomErrorBoundary>\n ) : this.state.error ? (\n <div>{this.state.error}</div>\n ) : (\n <LinearProgress />\n );\n\n if (schema.newLine) {\n return (\n <>\n <div style={{ flexBasis: '100%', height: 0 }} />\n {item}\n </>\n );\n }\n\n return item;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ConfigCustom.js","sourceRoot":"src/","sources":["JsonConfigComponent/ConfigCustom.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { type JSX } from 'react';\nimport { LinearProgress } from '@mui/material';\nimport { registerRemotes, loadRemote, init } from '@module-federation/runtime';\n\nimport * as IconsMaterial from '@mui/icons-material';\n\nimport * as AdapterReact from '@iobroker/gui-components';\nimport { I18n, InfoBox } from '@iobroker/gui-components';\n\nimport ConfigGeneric, { type ConfigGenericProps, type ConfigGenericState } from './ConfigGeneric';\nimport ConfigCustomErrorBoundary from './ConfigCustomErrorBoundary';\nimport { checkGuiApiCompatibility, GUI_API_GENERATION, type GuiApiVerdict } from './guiApiGate';\nimport * as JsonConfig from '../';\nimport type { ConfigItemCustom } from '../types';\n\ninterface ConfigCustomProps extends ConfigGenericProps {\n schema: ConfigItemCustom;\n}\n\ninterface ConfigCustomState extends ConfigGenericState {\n Component: React.FC<ConfigGenericProps> | null;\n error: string;\n /** Set when the component was refused by the GUI API gate, so it was never loaded */\n incompatible: GuiApiVerdict | null;\n}\n\ninit({\n name: 'iobroker_admin',\n shared: {\n '@iobroker/gui-components': {\n lib: () => AdapterReact,\n version: '*',\n },\n '@mui/icons-material': {\n lib: () => IconsMaterial,\n version: '*',\n },\n '@iobroker/json-config': {\n lib: () => JsonConfig,\n version: '*',\n },\n },\n remotes: [],\n});\n\nexport default class ConfigCustom extends ConfigGeneric<ConfigCustomProps, ConfigCustomState> {\n static runningLoads: Record<string, Promise<{ default: Record<string, React.FC<ConfigGenericProps>> } | null>> = {};\n\n constructor(props: ConfigCustomProps) {\n super(props);\n // schema.url - location of Widget\n // schema.name - Component name\n // schema.i18n - i18n\n\n Object.assign(this.state, {\n Component: null,\n error: '',\n incompatible: null,\n });\n }\n\n // load component dynamically\n async componentDidMount(): Promise<void> {\n if (!this.props.schema.url) {\n console.error('URL is empty. Cannot load custom component!');\n this.setState({ error: 'URL is empty. Cannot load custom component!' });\n return;\n }\n\n let url;\n if (this.props.schema.url.startsWith('http:') || this.props.schema.url.startsWith('https:')) {\n url = this.props.schema.url;\n } else if (this.props.schema.url.startsWith('./')) {\n url = `${window.location.protocol}//${window.location.host}${this.props.schema.url.replace(/^\\./, '')}`;\n } else {\n url = `${window.location.protocol}//${window.location.host}/adapter/${this.props.oContext.adapterName}/${this.props.schema.url}`;\n }\n const [uniqueName, fileToLoad, ...componentNameParts] = this.props.schema.name.split('/');\n const componentName = componentNameParts.join('/');\n if (!url) {\n console.error(\n 'Cannot find URL for custom component! Please define \"url\" as \"custom/customComponents.js\" in the schema',\n );\n return;\n }\n if (!uniqueName || !fileToLoad || !componentName) {\n console.error(\n 'Invalid format of \"name\"! Please define \"name\" as \"ConfigCustomBackItUpSet/Components/AdapterExist\" in the schema',\n );\n return;\n }\n\n // Refuse an incompatible component before it is registered: it shares this admin's React and\n // MUI singletons, so one built against another generation would break while rendering.\n const verdict = await checkGuiApiCompatibility(url, this.props.schema.guiApi);\n if (!verdict.compatible) {\n console.warn(\n `Custom component \"${this.props.schema.name}\" from \"${url}\" was not started: it targets ` +\n `GUI API generation ${verdict.declared}, but this admin provides generation ${GUI_API_GENERATION}.`,\n );\n this.setState({ incompatible: verdict });\n return;\n }\n\n let setPromise: Promise<{ default: Record<string, React.FC<ConfigGenericProps>> } | null> | undefined =\n ConfigCustom.runningLoads[`${url}!${fileToLoad}`];\n\n if (!(setPromise instanceof Promise)) {\n let i18nPromise: Promise<void> | undefined;\n if (this.props.schema.i18n === true) {\n // load i18n from files\n const pos = url.lastIndexOf('/');\n let i18nURL: string;\n if (pos !== -1) {\n i18nURL = url.substring(0, pos);\n } else {\n i18nURL = url;\n }\n const lang = I18n.getLanguage();\n const file = `${i18nURL}/i18n/${lang}.json`;\n\n i18nPromise = fetch(file)\n .then(data => data.json())\n .then(json => I18n.extendTranslations(json, lang))\n .catch(error => {\n if (lang !== 'en') {\n // try to load English\n fetch(`${i18nURL}/i18n/en.json`)\n .then(data => data.json())\n .then(json => I18n.extendTranslations(json, lang))\n .catch(err => console.log(`Cannot load i18n \"${file}\": ${err}`));\n return;\n }\n console.log(`Cannot load i18n \"${file}\": ${error}`);\n });\n } else if (this.props.schema.i18n && typeof this.props.schema.i18n === 'object') {\n try {\n I18n.extendTranslations(this.props.schema.i18n);\n } catch (error) {\n console.error(`Cannot import i18n: ${error}`);\n }\n }\n try {\n console.log(url, uniqueName, fileToLoad, componentName);\n\n registerRemotes(\n [\n {\n name: uniqueName,\n entry: url,\n // Components of the current GUI API generation are always built as ES\n // modules, so the former `bundlerType` schema attribute is obsolete.\n type: 'module',\n },\n ],\n // force: true // may be needed to side-load remotes after the fact.\n );\n setPromise = loadRemote(`${uniqueName}/${fileToLoad}`);\n if (i18nPromise instanceof Promise) {\n setPromise = Promise.all([setPromise, i18nPromise]).then(result => result[0]);\n }\n // remember promise\n ConfigCustom.runningLoads[`${url}!${fileToLoad}`] = setPromise;\n } catch (error) {\n console.error(error);\n this.setState({ error: `Cannot import from ${this.props.schema.url}: ${error}` });\n }\n }\n try {\n const component: Record<string, React.FC<ConfigGenericProps>> | undefined = (await setPromise)?.default;\n\n if (!component?.[componentName]) {\n const keys = Object.keys(component || {});\n console.error('URL is empty. Cannot load custom component!');\n this.setState({\n error: `Component ${this.props.schema.name} not found in ${this.props.schema.url}. Found: ${keys.join(', ')}`,\n });\n } else {\n this.setState({ Component: component[componentName] });\n }\n } catch (error) {\n console.error(error);\n this.setState({ error: `Cannot import from ${this.props.schema.url}: ${error}` });\n }\n }\n\n /** Explain why a component was not started, and what the user can do about it */\n renderIncompatible(verdict: GuiApiVerdict): JSX.Element {\n return (\n <InfoBox\n type=\"warning\"\n iconPosition=\"top\"\n >\n <div>\n <div style={{ fontWeight: 'bold' }}>\n {I18n.t('jc_Custom component \"%s\" was not started', this.props.schema.name)}\n </div>\n <div>\n {verdict.tooNew\n ? I18n.t(\n 'jc_It requires GUI API generation %s, but this admin provides generation %s. Please update the admin.',\n verdict.declared,\n GUI_API_GENERATION,\n )\n : I18n.t(\n 'jc_It was built for GUI API generation %s, but this admin provides generation %s. Please update the adapter.',\n verdict.declared,\n GUI_API_GENERATION,\n )}\n </div>\n </div>\n </InfoBox>\n );\n }\n\n render(): JSX.Element {\n const CustomComponent: React.FC<ConfigGenericProps> | null = this.state.Component;\n const schema = this.props.schema || ({} as ConfigItemCustom);\n\n const item = CustomComponent ? (\n // The custom component is third-party code, so a render error must not take down the\n // whole configuration page with it.\n <ConfigCustomErrorBoundary\n name={schema.name}\n url={schema.url}\n >\n <CustomComponent\n {...this.props}\n // @ts-expect-error BF (2024-12-18) Remove after the 7.4 will be mainstream. All following lines\n socket={this.props.oContext.socket}\n theme={this.props.oContext.theme}\n themeType={this.props.oContext.themeType}\n instance={this.props.oContext.instance}\n adapterName={this.props.oContext.adapterName}\n systemConfig={this.props.oContext.systemConfig}\n forceUpdate={this.props.oContext.forceUpdate}\n />\n </ConfigCustomErrorBoundary>\n ) : this.state.incompatible ? (\n this.renderIncompatible(this.state.incompatible)\n ) : this.state.error ? (\n <div>{this.state.error}</div>\n ) : (\n <LinearProgress />\n );\n\n if (schema.newLine) {\n return (\n <>\n <div style={{ flexBasis: '100%', height: 0 }} />\n {item}\n </>\n );\n }\n\n return item;\n }\n}\n"]}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compatibility gate for custom components loaded via module federation.
|
|
3
|
+
*
|
|
4
|
+
* The admin shares React, MUI and the ioBroker component libraries as federation singletons, so
|
|
5
|
+
* there is exactly one version of each at runtime. A component built against an older generation
|
|
6
|
+
* would be handed APIs it was never compiled against and usually dies while rendering. This module
|
|
7
|
+
* decides *before* the remote is registered whether it may run at all.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Generation of the GUI API this build of `@iobroker/json-config` provides.
|
|
11
|
+
*
|
|
12
|
+
* Generation `2` is `@iobroker/gui-components` (React 19 / MUI 9); generation `1` was the legacy
|
|
13
|
+
* `@iobroker/adapter-react-v5` (React 18 / MUI 6).
|
|
14
|
+
*
|
|
15
|
+
* Bump this only when a change actually breaks components built against the previous generation.
|
|
16
|
+
*/
|
|
17
|
+
export declare const GUI_API_GENERATION = 2;
|
|
18
|
+
export interface GuiApiVerdict {
|
|
19
|
+
/** Whether the component may be loaded */
|
|
20
|
+
compatible: boolean;
|
|
21
|
+
/** Generation the component was built against, as far as it could be determined */
|
|
22
|
+
declared: number;
|
|
23
|
+
/** True if the component needs a *newer* admin, false if it is too old for this one */
|
|
24
|
+
tooNew: boolean;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Decide whether a custom component may be loaded.
|
|
28
|
+
*
|
|
29
|
+
* Precedence:
|
|
30
|
+
* 1. The manifest is authoritative when it names the legacy library - that component cannot run.
|
|
31
|
+
* 2. An explicit `guiApi` in the schema is compared against the generation provided here.
|
|
32
|
+
* 3. A manifest naming the current library counts as compatible.
|
|
33
|
+
* 4. Otherwise the component predates this marker and is treated as generation 1.
|
|
34
|
+
*
|
|
35
|
+
* Note that a manifest can only rule a component *out* by its library name; ruling it *in* means
|
|
36
|
+
* "at least generation 2". Should a generation 3 ever exist, the `guiApi` attribute (step 2) is
|
|
37
|
+
* what distinguishes it, which is why the explicit declaration wins over step 3.
|
|
38
|
+
*
|
|
39
|
+
* @param entryUrl absolute URL of the remote entry, like `https://host/adapter/x/custom/customComponents.js`
|
|
40
|
+
* @param declared value of the `guiApi` attribute from the jsonConfig schema, if the component sets it
|
|
41
|
+
*/
|
|
42
|
+
export declare function checkGuiApiCompatibility(entryUrl: string, declared?: number): Promise<GuiApiVerdict>;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compatibility gate for custom components loaded via module federation.
|
|
3
|
+
*
|
|
4
|
+
* The admin shares React, MUI and the ioBroker component libraries as federation singletons, so
|
|
5
|
+
* there is exactly one version of each at runtime. A component built against an older generation
|
|
6
|
+
* would be handed APIs it was never compiled against and usually dies while rendering. This module
|
|
7
|
+
* decides *before* the remote is registered whether it may run at all.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Generation of the GUI API this build of `@iobroker/json-config` provides.
|
|
11
|
+
*
|
|
12
|
+
* Generation `2` is `@iobroker/gui-components` (React 19 / MUI 9); generation `1` was the legacy
|
|
13
|
+
* `@iobroker/adapter-react-v5` (React 18 / MUI 6).
|
|
14
|
+
*
|
|
15
|
+
* Bump this only when a change actually breaks components built against the previous generation.
|
|
16
|
+
*/
|
|
17
|
+
export const GUI_API_GENERATION = 2;
|
|
18
|
+
/** Component library of the current generation */
|
|
19
|
+
const CURRENT_LIBRARY = '@iobroker/gui-components';
|
|
20
|
+
/** Component library of generation 1 */
|
|
21
|
+
const LEGACY_LIBRARY = '@iobroker/adapter-react-v5';
|
|
22
|
+
/** How long to wait for the manifest before falling back to the declared generation */
|
|
23
|
+
const MANIFEST_TIMEOUT_MS = 5_000;
|
|
24
|
+
/** Manifests are fetched once per remote and reused, keyed by the manifest URL */
|
|
25
|
+
const manifestCache = new Map();
|
|
26
|
+
/**
|
|
27
|
+
* Fetch the module federation manifest that sits next to the remote entry.
|
|
28
|
+
*
|
|
29
|
+
* This is a best-effort lookup: components built before manifests were shipped simply do not have
|
|
30
|
+
* one, which is not an error - the caller then falls back to the declared generation.
|
|
31
|
+
*/
|
|
32
|
+
async function loadManifest(entryUrl) {
|
|
33
|
+
const slash = entryUrl.lastIndexOf('/');
|
|
34
|
+
const manifestUrl = `${slash === -1 ? entryUrl : entryUrl.substring(0, slash)}/mf-manifest.json`;
|
|
35
|
+
let promise = manifestCache.get(manifestUrl);
|
|
36
|
+
if (!promise) {
|
|
37
|
+
promise = (async () => {
|
|
38
|
+
const controller = new AbortController();
|
|
39
|
+
const timer = setTimeout(() => controller.abort(), MANIFEST_TIMEOUT_MS);
|
|
40
|
+
try {
|
|
41
|
+
const response = await fetch(manifestUrl, { signal: controller.signal });
|
|
42
|
+
if (!response.ok) {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
return (await response.json());
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
// No manifest, unreachable or unparsable - treated as "unknown", not as an error
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
finally {
|
|
52
|
+
clearTimeout(timer);
|
|
53
|
+
}
|
|
54
|
+
})();
|
|
55
|
+
manifestCache.set(manifestUrl, promise);
|
|
56
|
+
}
|
|
57
|
+
return promise;
|
|
58
|
+
}
|
|
59
|
+
/** Which component library the remote was built against, or null if the manifest does not say */
|
|
60
|
+
function libraryFromManifest(manifest) {
|
|
61
|
+
const shared = manifest?.shared;
|
|
62
|
+
if (!Array.isArray(shared)) {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
if (shared.some(entry => entry?.name === LEGACY_LIBRARY)) {
|
|
66
|
+
return LEGACY_LIBRARY;
|
|
67
|
+
}
|
|
68
|
+
if (shared.some(entry => entry?.name === CURRENT_LIBRARY)) {
|
|
69
|
+
return CURRENT_LIBRARY;
|
|
70
|
+
}
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Decide whether a custom component may be loaded.
|
|
75
|
+
*
|
|
76
|
+
* Precedence:
|
|
77
|
+
* 1. The manifest is authoritative when it names the legacy library - that component cannot run.
|
|
78
|
+
* 2. An explicit `guiApi` in the schema is compared against the generation provided here.
|
|
79
|
+
* 3. A manifest naming the current library counts as compatible.
|
|
80
|
+
* 4. Otherwise the component predates this marker and is treated as generation 1.
|
|
81
|
+
*
|
|
82
|
+
* Note that a manifest can only rule a component *out* by its library name; ruling it *in* means
|
|
83
|
+
* "at least generation 2". Should a generation 3 ever exist, the `guiApi` attribute (step 2) is
|
|
84
|
+
* what distinguishes it, which is why the explicit declaration wins over step 3.
|
|
85
|
+
*
|
|
86
|
+
* @param entryUrl absolute URL of the remote entry, like `https://host/adapter/x/custom/customComponents.js`
|
|
87
|
+
* @param declared value of the `guiApi` attribute from the jsonConfig schema, if the component sets it
|
|
88
|
+
*/
|
|
89
|
+
export async function checkGuiApiCompatibility(entryUrl, declared) {
|
|
90
|
+
const library = libraryFromManifest(await loadManifest(entryUrl));
|
|
91
|
+
if (library === LEGACY_LIBRARY) {
|
|
92
|
+
return { compatible: false, declared: 1, tooNew: false };
|
|
93
|
+
}
|
|
94
|
+
if (typeof declared === 'number' && Number.isFinite(declared)) {
|
|
95
|
+
return {
|
|
96
|
+
compatible: declared === GUI_API_GENERATION,
|
|
97
|
+
declared,
|
|
98
|
+
tooNew: declared > GUI_API_GENERATION,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
if (library === CURRENT_LIBRARY) {
|
|
102
|
+
return { compatible: true, declared: GUI_API_GENERATION, tooNew: false };
|
|
103
|
+
}
|
|
104
|
+
return { compatible: false, declared: 1, tooNew: false };
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=guiApiGate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guiApiGate.js","sourceRoot":"src/","sources":["JsonConfigComponent/guiApiGate.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Compatibility gate for custom components loaded via module federation.\n *\n * The admin shares React, MUI and the ioBroker component libraries as federation singletons, so\n * there is exactly one version of each at runtime. A component built against an older generation\n * would be handed APIs it was never compiled against and usually dies while rendering. This module\n * decides *before* the remote is registered whether it may run at all.\n */\n\n/**\n * Generation of the GUI API this build of `@iobroker/json-config` provides.\n *\n * Generation `2` is `@iobroker/gui-components` (React 19 / MUI 9); generation `1` was the legacy\n * `@iobroker/adapter-react-v5` (React 18 / MUI 6).\n *\n * Bump this only when a change actually breaks components built against the previous generation.\n */\nexport const GUI_API_GENERATION = 2;\n\n/** Component library of the current generation */\nconst CURRENT_LIBRARY = '@iobroker/gui-components';\n/** Component library of generation 1 */\nconst LEGACY_LIBRARY = '@iobroker/adapter-react-v5';\n\n/** How long to wait for the manifest before falling back to the declared generation */\nconst MANIFEST_TIMEOUT_MS = 5_000;\n\nexport interface GuiApiVerdict {\n /** Whether the component may be loaded */\n compatible: boolean;\n /** Generation the component was built against, as far as it could be determined */\n declared: number;\n /** True if the component needs a *newer* admin, false if it is too old for this one */\n tooNew: boolean;\n}\n\ninterface FederationManifest {\n shared?: { name?: string; version?: string }[];\n}\n\n/** Manifests are fetched once per remote and reused, keyed by the manifest URL */\nconst manifestCache = new Map<string, Promise<FederationManifest | null>>();\n\n/**\n * Fetch the module federation manifest that sits next to the remote entry.\n *\n * This is a best-effort lookup: components built before manifests were shipped simply do not have\n * one, which is not an error - the caller then falls back to the declared generation.\n */\nasync function loadManifest(entryUrl: string): Promise<FederationManifest | null> {\n const slash = entryUrl.lastIndexOf('/');\n const manifestUrl = `${slash === -1 ? entryUrl : entryUrl.substring(0, slash)}/mf-manifest.json`;\n\n let promise = manifestCache.get(manifestUrl);\n if (!promise) {\n promise = (async (): Promise<FederationManifest | null> => {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), MANIFEST_TIMEOUT_MS);\n try {\n const response = await fetch(manifestUrl, { signal: controller.signal });\n if (!response.ok) {\n return null;\n }\n return (await response.json()) as FederationManifest;\n } catch {\n // No manifest, unreachable or unparsable - treated as \"unknown\", not as an error\n return null;\n } finally {\n clearTimeout(timer);\n }\n })();\n manifestCache.set(manifestUrl, promise);\n }\n return promise;\n}\n\n/** Which component library the remote was built against, or null if the manifest does not say */\nfunction libraryFromManifest(manifest: FederationManifest | null): string | null {\n const shared = manifest?.shared;\n if (!Array.isArray(shared)) {\n return null;\n }\n if (shared.some(entry => entry?.name === LEGACY_LIBRARY)) {\n return LEGACY_LIBRARY;\n }\n if (shared.some(entry => entry?.name === CURRENT_LIBRARY)) {\n return CURRENT_LIBRARY;\n }\n return null;\n}\n\n/**\n * Decide whether a custom component may be loaded.\n *\n * Precedence:\n * 1. The manifest is authoritative when it names the legacy library - that component cannot run.\n * 2. An explicit `guiApi` in the schema is compared against the generation provided here.\n * 3. A manifest naming the current library counts as compatible.\n * 4. Otherwise the component predates this marker and is treated as generation 1.\n *\n * Note that a manifest can only rule a component *out* by its library name; ruling it *in* means\n * \"at least generation 2\". Should a generation 3 ever exist, the `guiApi` attribute (step 2) is\n * what distinguishes it, which is why the explicit declaration wins over step 3.\n *\n * @param entryUrl absolute URL of the remote entry, like `https://host/adapter/x/custom/customComponents.js`\n * @param declared value of the `guiApi` attribute from the jsonConfig schema, if the component sets it\n */\nexport async function checkGuiApiCompatibility(entryUrl: string, declared?: number): Promise<GuiApiVerdict> {\n const library = libraryFromManifest(await loadManifest(entryUrl));\n\n if (library === LEGACY_LIBRARY) {\n return { compatible: false, declared: 1, tooNew: false };\n }\n\n if (typeof declared === 'number' && Number.isFinite(declared)) {\n return {\n compatible: declared === GUI_API_GENERATION,\n declared,\n tooNew: declared > GUI_API_GENERATION,\n };\n }\n\n if (library === CURRENT_LIBRARY) {\n return { compatible: true, declared: GUI_API_GENERATION, tooNew: false };\n }\n\n return { compatible: false, declared: 1, tooNew: false };\n}\n"]}
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
"jc_Copy content": "Inhalte kopieren",
|
|
33
33
|
"jc_Create": "Erstellen",
|
|
34
34
|
"jc_Credential type": "Anmeldeinformationstyp",
|
|
35
|
+
"jc_Custom component \"%s\" was not started": "Die benutzerdefinierte Komponente \"%s\" wurde nicht gestartet",
|
|
35
36
|
"jc_Define schedule": "Zeitplan definieren",
|
|
36
37
|
"jc_Delete": "Löschen",
|
|
37
38
|
"jc_Delete current row": "Aktuelle Zeile löschen",
|
|
@@ -64,6 +65,8 @@
|
|
|
64
65
|
"jc_Invalid JSON file.": "Ungültige JSON-Datei.",
|
|
65
66
|
"jc_Invalid JSON format. Expected an array.": "Ungültiges JSON-Format. Array erwartet.",
|
|
66
67
|
"jc_Invalid YAML": "Ungültiges YAML",
|
|
68
|
+
"jc_It requires GUI API generation %s, but this admin provides generation %s. Please update the admin.": "Sie benötigt GUI-API-Generation %s, dieser Admin stellt aber Generation %s bereit. Bitte den Admin aktualisieren.",
|
|
69
|
+
"jc_It was built for GUI API generation %s, but this admin provides generation %s. Please update the adapter.": "Sie wurde für GUI-API-Generation %s erstellt, dieser Admin stellt aber Generation %s bereit. Bitte den Adapter aktualisieren.",
|
|
67
70
|
"jc_It was probably built for an older admin version. Please update the adapter.": "Sie wurde vermutlich für eine ältere Admin-Version erstellt. Bitte den Adapter aktualisieren.",
|
|
68
71
|
"jc_JSON editor": "JSON-Editor",
|
|
69
72
|
"jc_Latitude": "Breite",
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
"jc_Copy content": "Copy content",
|
|
33
33
|
"jc_Create": "Create",
|
|
34
34
|
"jc_Credential type": "Credential type",
|
|
35
|
+
"jc_Custom component \"%s\" was not started": "Custom component \"%s\" was not started",
|
|
35
36
|
"jc_Define schedule": "Define schedule",
|
|
36
37
|
"jc_Delete": "Delete",
|
|
37
38
|
"jc_Delete current row": "Delete current row",
|
|
@@ -64,6 +65,8 @@
|
|
|
64
65
|
"jc_Invalid JSON file.": "Invalid JSON file.",
|
|
65
66
|
"jc_Invalid JSON format. Expected an array.": "Invalid JSON format. Expected an array.",
|
|
66
67
|
"jc_Invalid YAML": "Invalid YAML",
|
|
68
|
+
"jc_It requires GUI API generation %s, but this admin provides generation %s. Please update the admin.": "It requires GUI API generation %s, but this admin provides generation %s. Please update the admin.",
|
|
69
|
+
"jc_It was built for GUI API generation %s, but this admin provides generation %s. Please update the adapter.": "It was built for GUI API generation %s, but this admin provides generation %s. Please update the adapter.",
|
|
67
70
|
"jc_It was probably built for an older admin version. Please update the adapter.": "It was probably built for an older admin version. Please update the adapter.",
|
|
68
71
|
"jc_JSON editor": "JSON editor",
|
|
69
72
|
"jc_Latitude": "Latitude",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"jc_Cannot create credential: %s": "No se puede crear la credencial: %s",
|
|
16
16
|
"jc_Cannot decode license": "No se puede decodificar la licencia",
|
|
17
17
|
"jc_Cannot determine position: System settings are empty and GPS detection is disabled in browser": "No se puede determinar la posición: la configuración del sistema está vacía y la detección de GPS está deshabilitada en el navegador",
|
|
18
|
+
"jc_Cannot display the custom component \"%s\"": "No se puede mostrar el componente personalizado \"%s\"",
|
|
18
19
|
"jc_Cannot read licenses: %s": "No se pueden leer licencias: %s",
|
|
19
20
|
"jc_Cannot retrieve options, as instance is offline": "No se pueden recuperar las opciones, ya que la instancia está fuera de línea",
|
|
20
21
|
"jc_Cannot save configuration because of error in configuration": "No se puede guardar la configuración debido a un error en la configuración.",
|
|
@@ -31,6 +32,7 @@
|
|
|
31
32
|
"jc_Copy content": "Copiar contenido",
|
|
32
33
|
"jc_Create": "Crear",
|
|
33
34
|
"jc_Credential type": "Tipo de credencial",
|
|
35
|
+
"jc_Custom component \"%s\" was not started": "El componente personalizado \"%s\" no se inició.",
|
|
34
36
|
"jc_Define schedule": "Definir horario",
|
|
35
37
|
"jc_Delete": "Eliminar",
|
|
36
38
|
"jc_Delete current row": "Eliminar fila actual",
|
|
@@ -63,6 +65,9 @@
|
|
|
63
65
|
"jc_Invalid JSON file.": "Archivo JSON inválido.",
|
|
64
66
|
"jc_Invalid JSON format. Expected an array.": "Formato JSON inválido. Se esperaba un array.",
|
|
65
67
|
"jc_Invalid YAML": "YAML no válido",
|
|
68
|
+
"jc_It requires GUI API generation %s, but this admin provides generation %s. Please update the admin.": "Requiere la generación de la API de la GUI %s, pero este administrador proporciona la generación %s. Por favor, actualice el administrador.",
|
|
69
|
+
"jc_It was built for GUI API generation %s, but this admin provides generation %s. Please update the adapter.": "Fue diseñado para la generación de API GUI %s, pero este administrador proporciona la generación %s. Por favor, actualice el adaptador.",
|
|
70
|
+
"jc_It was probably built for an older admin version. Please update the adapter.": "Probablemente se diseñó para una versión de administración anterior. Por favor, actualice el adaptador.",
|
|
66
71
|
"jc_JSON editor": "editor JSON",
|
|
67
72
|
"jc_Latitude": "Latitud",
|
|
68
73
|
"jc_License %s": "Licencia %s",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"jc_Cannot create credential: %s": "Impossible de créer les informations d'identification : %s",
|
|
16
16
|
"jc_Cannot decode license": "Impossible de décoder la licence",
|
|
17
17
|
"jc_Cannot determine position: System settings are empty and GPS detection is disabled in browser": "Impossible de déterminer la position : les paramètres système sont vides et la détection GPS est désactivée dans le navigateur",
|
|
18
|
+
"jc_Cannot display the custom component \"%s\"": "Impossible d'afficher le composant personnalisé « %s »",
|
|
18
19
|
"jc_Cannot read licenses: %s": "Impossible de lire les licences : %s",
|
|
19
20
|
"jc_Cannot retrieve options, as instance is offline": "Impossible de récupérer les options, car l'instance est hors ligne",
|
|
20
21
|
"jc_Cannot save configuration because of error in configuration": "Impossible d'enregistrer la configuration en raison d'une erreur de configuration.",
|
|
@@ -31,6 +32,7 @@
|
|
|
31
32
|
"jc_Copy content": "Copier le contenu",
|
|
32
33
|
"jc_Create": "Créer",
|
|
33
34
|
"jc_Credential type": "Type de justificatif d'identité",
|
|
35
|
+
"jc_Custom component \"%s\" was not started": "Le composant personnalisé « %s » n'a pas été démarré.",
|
|
34
36
|
"jc_Define schedule": "Définir le calendrier",
|
|
35
37
|
"jc_Delete": "Supprimer",
|
|
36
38
|
"jc_Delete current row": "Supprimer la ligne actuelle",
|
|
@@ -63,6 +65,9 @@
|
|
|
63
65
|
"jc_Invalid JSON file.": "Fichier JSON invalide.",
|
|
64
66
|
"jc_Invalid JSON format. Expected an array.": "Format JSON invalide. Tableau attendu.",
|
|
65
67
|
"jc_Invalid YAML": "YAML invalide",
|
|
68
|
+
"jc_It requires GUI API generation %s, but this admin provides generation %s. Please update the admin.": "Cela nécessite la génération de l'API GUI %s, mais cet administrateur fournit la génération %s. Veuillez mettre à jour l'administrateur.",
|
|
69
|
+
"jc_It was built for GUI API generation %s, but this admin provides generation %s. Please update the adapter.": "Il a été conçu pour la génération d'API GUI %s, mais cet administrateur fournit la génération %s. Veuillez mettre à jour l'adaptateur.",
|
|
70
|
+
"jc_It was probably built for an older admin version. Please update the adapter.": "Il a probablement été conçu pour une version d'administration plus ancienne. Veuillez mettre à jour l'adaptateur.",
|
|
66
71
|
"jc_JSON editor": "Éditeur JSON",
|
|
67
72
|
"jc_Latitude": "Latitude",
|
|
68
73
|
"jc_License %s": "Licence %s",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"jc_Cannot create credential: %s": "Impossibile creare le credenziali: %s",
|
|
16
16
|
"jc_Cannot decode license": "Impossibile decodificare la licenza",
|
|
17
17
|
"jc_Cannot determine position: System settings are empty and GPS detection is disabled in browser": "Impossibile determinare la posizione: le impostazioni di sistema sono vuote e il rilevamento GPS è disabilitato nel browser",
|
|
18
|
+
"jc_Cannot display the custom component \"%s\"": "Impossibile visualizzare il componente personalizzato \"%s\"",
|
|
18
19
|
"jc_Cannot read licenses: %s": "Impossibile leggere le licenze: %s",
|
|
19
20
|
"jc_Cannot retrieve options, as instance is offline": "Impossibile recuperare le opzioni, poiché l'istanza è offline",
|
|
20
21
|
"jc_Cannot save configuration because of error in configuration": "Impossibile salvare la configurazione a causa di un errore nella configurazione",
|
|
@@ -31,6 +32,7 @@
|
|
|
31
32
|
"jc_Copy content": "Copia contenuto",
|
|
32
33
|
"jc_Create": "Creare",
|
|
33
34
|
"jc_Credential type": "Tipo di credenziale",
|
|
35
|
+
"jc_Custom component \"%s\" was not started": "Il componente personalizzato \"%s\" non è stato avviato",
|
|
34
36
|
"jc_Define schedule": "Definisci programma",
|
|
35
37
|
"jc_Delete": "Elimina",
|
|
36
38
|
"jc_Delete current row": "Elimina la riga corrente",
|
|
@@ -63,6 +65,9 @@
|
|
|
63
65
|
"jc_Invalid JSON file.": "File JSON non valido.",
|
|
64
66
|
"jc_Invalid JSON format. Expected an array.": "Formato JSON non valido. È previsto un array.",
|
|
65
67
|
"jc_Invalid YAML": "YAML non valido",
|
|
68
|
+
"jc_It requires GUI API generation %s, but this admin provides generation %s. Please update the admin.": "Richiede la generazione dell'API GUI %s, ma questo amministratore fornisce la generazione %s. Si prega di aggiornare l'amministratore.",
|
|
69
|
+
"jc_It was built for GUI API generation %s, but this admin provides generation %s. Please update the adapter.": "È stato creato per la generazione dell'API GUI %s, ma questo amministratore fornisce la generazione %s. Si prega di aggiornare l'adattatore.",
|
|
70
|
+
"jc_It was probably built for an older admin version. Please update the adapter.": "Probabilmente è stato creato per una versione di amministrazione precedente. Si prega di aggiornare l'adattatore.",
|
|
66
71
|
"jc_JSON editor": "Editor JSON",
|
|
67
72
|
"jc_Latitude": "Latitudine",
|
|
68
73
|
"jc_License %s": "Licenza %s",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"jc_Cannot create credential: %s": "Kan geen inloggegevens aanmaken: %s",
|
|
16
16
|
"jc_Cannot decode license": "Kan licentie niet decoderen",
|
|
17
17
|
"jc_Cannot determine position: System settings are empty and GPS detection is disabled in browser": "Kan positie niet bepalen: systeeminstellingen zijn leeg en GPS-detectie is uitgeschakeld in browser",
|
|
18
|
+
"jc_Cannot display the custom component \"%s\"": "Kan het aangepaste component \"%s\" niet weergeven.",
|
|
18
19
|
"jc_Cannot read licenses: %s": "Kan licenties niet lezen: %s",
|
|
19
20
|
"jc_Cannot retrieve options, as instance is offline": "Kan opties niet ophalen, omdat instantie offline is",
|
|
20
21
|
"jc_Cannot save configuration because of error in configuration": "Configuratie kan niet worden opgeslagen vanwege een configuratiefout.",
|
|
@@ -31,6 +32,7 @@
|
|
|
31
32
|
"jc_Copy content": "Inhoud kopiëren",
|
|
32
33
|
"jc_Create": "Creëer",
|
|
33
34
|
"jc_Credential type": "Referentietype",
|
|
35
|
+
"jc_Custom component \"%s\" was not started": "Aangepaste component \"%s\" is niet gestart.",
|
|
34
36
|
"jc_Define schedule": "Definieer schema",
|
|
35
37
|
"jc_Delete": "Verwijderen",
|
|
36
38
|
"jc_Delete current row": "Huidige rij verwijderen",
|
|
@@ -63,6 +65,9 @@
|
|
|
63
65
|
"jc_Invalid JSON file.": "Ongeldig JSON-bestand.",
|
|
64
66
|
"jc_Invalid JSON format. Expected an array.": "Ongeldige JSON-indeling. Er werd een array verwacht.",
|
|
65
67
|
"jc_Invalid YAML": "Ongeldige YAML",
|
|
68
|
+
"jc_It requires GUI API generation %s, but this admin provides generation %s. Please update the admin.": "Het vereist GUI API-generatie %s, maar deze beheerder levert generatie %s. Graag de beheerder bijwerken.",
|
|
69
|
+
"jc_It was built for GUI API generation %s, but this admin provides generation %s. Please update the adapter.": "Het is gebouwd voor GUI API-generatie %s, maar deze beheerder levert generatie %s. Update de adapter.",
|
|
70
|
+
"jc_It was probably built for an older admin version. Please update the adapter.": "Het is waarschijnlijk ontwikkeld voor een oudere beheerdersversie. Update de adapter.",
|
|
66
71
|
"jc_JSON editor": "JSON-editor",
|
|
67
72
|
"jc_Latitude": "Breedtegraad",
|
|
68
73
|
"jc_License %s": "Licentie %s",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"jc_Cannot create credential: %s": "Nie można utworzyć poświadczeń: %s",
|
|
16
16
|
"jc_Cannot decode license": "Nie można zdekodować licencji",
|
|
17
17
|
"jc_Cannot determine position: System settings are empty and GPS detection is disabled in browser": "Nie można określić pozycji: ustawienia systemu są puste, a wykrywanie GPS jest wyłączone w przeglądarce",
|
|
18
|
+
"jc_Cannot display the custom component \"%s\"": "Nie można wyświetlić niestandardowego komponentu „%s”",
|
|
18
19
|
"jc_Cannot read licenses: %s": "Nie można odczytać licencji: %s",
|
|
19
20
|
"jc_Cannot retrieve options, as instance is offline": "Nie można pobrać opcji, ponieważ instancja jest w trybie offline",
|
|
20
21
|
"jc_Cannot save configuration because of error in configuration": "Nie można zapisać konfiguracji z powodu błędu w konfiguracji",
|
|
@@ -31,6 +32,7 @@
|
|
|
31
32
|
"jc_Copy content": "Kopiuj zawartość",
|
|
32
33
|
"jc_Create": "Stwórz",
|
|
33
34
|
"jc_Credential type": "Typ poświadczenia",
|
|
35
|
+
"jc_Custom component \"%s\" was not started": "Komponent niestandardowy „%s” nie został uruchomiony",
|
|
34
36
|
"jc_Define schedule": "Zdefiniuj harmonogram",
|
|
35
37
|
"jc_Delete": "Usunąć",
|
|
36
38
|
"jc_Delete current row": "Usuń bieżący wiersz",
|
|
@@ -63,6 +65,9 @@
|
|
|
63
65
|
"jc_Invalid JSON file.": "Nieprawidłowy plik JSON.",
|
|
64
66
|
"jc_Invalid JSON format. Expected an array.": "Nieprawidłowy format JSON. Oczekiwano tablicy.",
|
|
65
67
|
"jc_Invalid YAML": "Nieprawidłowy plik YAML",
|
|
68
|
+
"jc_It requires GUI API generation %s, but this admin provides generation %s. Please update the admin.": "Wymaga generacji interfejsu API GUI %s, ale ten administrator zapewnia generację %s. Zaktualizuj administratora.",
|
|
69
|
+
"jc_It was built for GUI API generation %s, but this admin provides generation %s. Please update the adapter.": "Został stworzony do generowania interfejsu API GUI %s, ale ten administrator zapewnia generowanie %s. Proszę zaktualizować adapter.",
|
|
70
|
+
"jc_It was probably built for an older admin version. Please update the adapter.": "Prawdopodobnie został stworzony dla starszej wersji administratora. Proszę zaktualizować adapter.",
|
|
66
71
|
"jc_JSON editor": "Edytor JSON",
|
|
67
72
|
"jc_Latitude": "Szerokość",
|
|
68
73
|
"jc_License %s": "Licencja %s",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"jc_Cannot create credential: %s": "Não foi possível criar a credencial: %s",
|
|
16
16
|
"jc_Cannot decode license": "Não é possível decodificar a licença",
|
|
17
17
|
"jc_Cannot determine position: System settings are empty and GPS detection is disabled in browser": "Não é possível determinar a posição: as configurações do sistema estão vazias e a detecção de GPS está desativada no navegador",
|
|
18
|
+
"jc_Cannot display the custom component \"%s\"": "Não é possível exibir o componente personalizado \"%s\"",
|
|
18
19
|
"jc_Cannot read licenses: %s": "Não é possível ler licenças: %s",
|
|
19
20
|
"jc_Cannot retrieve options, as instance is offline": "Não é possível recuperar opções, pois a instância está off-line",
|
|
20
21
|
"jc_Cannot save configuration because of error in configuration": "Não foi possível salvar a configuração devido a um erro na configuração.",
|
|
@@ -31,6 +32,7 @@
|
|
|
31
32
|
"jc_Copy content": "Copiar conteúdo",
|
|
32
33
|
"jc_Create": "Crio",
|
|
33
34
|
"jc_Credential type": "Tipo de credencial",
|
|
35
|
+
"jc_Custom component \"%s\" was not started": "O componente personalizado \"%s\" não foi iniciado.",
|
|
34
36
|
"jc_Define schedule": "Definir cronograma",
|
|
35
37
|
"jc_Delete": "Excluir",
|
|
36
38
|
"jc_Delete current row": "Excluir linha atual",
|
|
@@ -63,6 +65,9 @@
|
|
|
63
65
|
"jc_Invalid JSON file.": "Arquivo JSON inválido.",
|
|
64
66
|
"jc_Invalid JSON format. Expected an array.": "Formato JSON inválido. Esperava-se uma matriz.",
|
|
65
67
|
"jc_Invalid YAML": "YAML inválido",
|
|
68
|
+
"jc_It requires GUI API generation %s, but this admin provides generation %s. Please update the admin.": "É necessário gerar %s da API da GUI, mas este painel de administração já fornece a geração %s. Por favor, atualize o painel de administração.",
|
|
69
|
+
"jc_It was built for GUI API generation %s, but this admin provides generation %s. Please update the adapter.": "Foi desenvolvido para geração de API GUI %s, mas este painel de administração fornece geração %s. Por favor, atualize o adaptador.",
|
|
70
|
+
"jc_It was probably built for an older admin version. Please update the adapter.": "Provavelmente foi desenvolvido para uma versão administrativa mais antiga. Por favor, atualize o adaptador.",
|
|
66
71
|
"jc_JSON editor": "Editor JSON",
|
|
67
72
|
"jc_Latitude": "Latitude",
|
|
68
73
|
"jc_License %s": "Licença %s",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"jc_Cannot create credential: %s": "Не удалось создать учетные данные: %s",
|
|
16
16
|
"jc_Cannot decode license": "Не могу декодировать лицензию",
|
|
17
17
|
"jc_Cannot determine position: System settings are empty and GPS detection is disabled in browser": "Невозможно определить местоположение: системные настройки пусты, а обнаружение GPS отключено в браузере.",
|
|
18
|
+
"jc_Cannot display the custom component \"%s\"": "Не удается отобразить пользовательский компонент \"%s\"",
|
|
18
19
|
"jc_Cannot read licenses: %s": "Невозможно прочитать лицензии: %s",
|
|
19
20
|
"jc_Cannot retrieve options, as instance is offline": "Невозможно получить параметры, так как экземпляр находится в автономном режиме.",
|
|
20
21
|
"jc_Cannot save configuration because of error in configuration": "Невозможно сохранить конфигурацию из-за ошибки в конфигурации.",
|
|
@@ -31,6 +32,7 @@
|
|
|
31
32
|
"jc_Copy content": "Копировать содержимое",
|
|
32
33
|
"jc_Create": "Создать",
|
|
33
34
|
"jc_Credential type": "Тип учетных данных",
|
|
35
|
+
"jc_Custom component \"%s\" was not started": "Пользовательский компонент \"%s\" не был запущен.",
|
|
34
36
|
"jc_Define schedule": "Задать расписание",
|
|
35
37
|
"jc_Delete": "Удалить",
|
|
36
38
|
"jc_Delete current row": "Удалить текущую строку",
|
|
@@ -63,6 +65,9 @@
|
|
|
63
65
|
"jc_Invalid JSON file.": "Неверный файл JSON.",
|
|
64
66
|
"jc_Invalid JSON format. Expected an array.": "Недопустимый формат JSON. Ожидается массив.",
|
|
65
67
|
"jc_Invalid YAML": "Недопустимый YAML-файл",
|
|
68
|
+
"jc_It requires GUI API generation %s, but this admin provides generation %s. Please update the admin.": "Для этого требуется генерация API графического интерфейса пользователя %s, но администратор предоставляет генерацию %s. Пожалуйста, обновите администратора.",
|
|
69
|
+
"jc_It was built for GUI API generation %s, but this admin provides generation %s. Please update the adapter.": "Он был создан для генерации API графического интерфейса пользователя %s, но этот администратор предоставляет генерацию %s. Пожалуйста, обновите адаптер.",
|
|
70
|
+
"jc_It was probably built for an older admin version. Please update the adapter.": "Вероятно, он был создан для более старой версии административной панели. Пожалуйста, обновите адаптер.",
|
|
66
71
|
"jc_JSON editor": "Редактор JSON",
|
|
67
72
|
"jc_Latitude": "Широта",
|
|
68
73
|
"jc_License %s": "Лицензия %s",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"jc_Cannot create credential: %s": "Не вдається створити облікові дані: %s",
|
|
16
16
|
"jc_Cannot decode license": "Неможливо розшифрувати ліцензію",
|
|
17
17
|
"jc_Cannot determine position: System settings are empty and GPS detection is disabled in browser": "Неможливо визначити положення: системні налаштування порожні, а визначення GPS вимкнено в браузері",
|
|
18
|
+
"jc_Cannot display the custom component \"%s\"": "Не вдається відобразити користувацький компонент \"%s\"",
|
|
18
19
|
"jc_Cannot read licenses: %s": "Неможливо прочитати ліцензії: %s",
|
|
19
20
|
"jc_Cannot retrieve options, as instance is offline": "Неможливо отримати параметри, оскільки екземпляр офлайн",
|
|
20
21
|
"jc_Cannot save configuration because of error in configuration": "Не вдалося зберегти конфігурацію через помилку в конфігурації",
|
|
@@ -31,6 +32,7 @@
|
|
|
31
32
|
"jc_Copy content": "Скопіюйте вміст",
|
|
32
33
|
"jc_Create": "Створити",
|
|
33
34
|
"jc_Credential type": "Тип облікових даних",
|
|
35
|
+
"jc_Custom component \"%s\" was not started": "Користувацький компонент \"%s\" не запущено",
|
|
34
36
|
"jc_Define schedule": "Визначити розклад",
|
|
35
37
|
"jc_Delete": "Видалити",
|
|
36
38
|
"jc_Delete current row": "Видалити поточний рядок",
|
|
@@ -63,6 +65,9 @@
|
|
|
63
65
|
"jc_Invalid JSON file.": "Недійсний JSON-файл.",
|
|
64
66
|
"jc_Invalid JSON format. Expected an array.": "Недійсний формат JSON. Очікується масив.",
|
|
65
67
|
"jc_Invalid YAML": "Недійсний YAML",
|
|
68
|
+
"jc_It requires GUI API generation %s, but this admin provides generation %s. Please update the admin.": "Потрібна генерація API графічного інтерфейсу %s, але цей адміністратор надає генерацію %s. Будь ласка, оновіть адміністраторську версію.",
|
|
69
|
+
"jc_It was built for GUI API generation %s, but this admin provides generation %s. Please update the adapter.": "Його було створено для покоління GUI API %s, але цей адміністратор надає покоління %s. Будь ласка, оновіть адаптер.",
|
|
70
|
+
"jc_It was probably built for an older admin version. Please update the adapter.": "Ймовірно, його було створено для старішої версії адміністратора. Будь ласка, оновіть адаптер.",
|
|
66
71
|
"jc_JSON editor": "Редактор JSON",
|
|
67
72
|
"jc_Latitude": "Широта",
|
|
68
73
|
"jc_License %s": "Ліцензія %s",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"jc_Cannot create credential: %s": "无法创建凭证:%s",
|
|
16
16
|
"jc_Cannot decode license": "无法解码许可证",
|
|
17
17
|
"jc_Cannot determine position: System settings are empty and GPS detection is disabled in browser": "无法确定位置:系统设置为空且浏览器中禁用了 GPS 检测",
|
|
18
|
+
"jc_Cannot display the custom component \"%s\"": "无法显示自定义组件“%s”",
|
|
18
19
|
"jc_Cannot read licenses: %s": "无法读取许可证:%s",
|
|
19
20
|
"jc_Cannot retrieve options, as instance is offline": "无法检索选项,因为实例处于脱机状态",
|
|
20
21
|
"jc_Cannot save configuration because of error in configuration": "由于配置错误,无法保存配置。",
|
|
@@ -31,6 +32,7 @@
|
|
|
31
32
|
"jc_Copy content": "复制内容",
|
|
32
33
|
"jc_Create": "创建",
|
|
33
34
|
"jc_Credential type": "凭证类型",
|
|
35
|
+
"jc_Custom component \"%s\" was not started": "自定义组件“%s”未启动",
|
|
34
36
|
"jc_Define schedule": "定义时间表",
|
|
35
37
|
"jc_Delete": "删除",
|
|
36
38
|
"jc_Delete current row": "删除当前行",
|
|
@@ -63,6 +65,9 @@
|
|
|
63
65
|
"jc_Invalid JSON file.": "无效的JSON文件。",
|
|
64
66
|
"jc_Invalid JSON format. Expected an array.": "JSON格式无效。应为数组。",
|
|
65
67
|
"jc_Invalid YAML": "无效的 YAML",
|
|
68
|
+
"jc_It requires GUI API generation %s, but this admin provides generation %s. Please update the admin.": "它需要生成 GUI API,但此管理员提供的是生成功能。请更新管理员。",
|
|
69
|
+
"jc_It was built for GUI API generation %s, but this admin provides generation %s. Please update the adapter.": "它原本是为 GUI API 生成 %s 而设计的,但此管理员提供了生成 %s 的功能。请更新适配器。",
|
|
70
|
+
"jc_It was probably built for an older admin version. Please update the adapter.": "这可能是为旧版管理后台构建的。请更新适配器。",
|
|
66
71
|
"jc_JSON editor": "JSON 编辑器",
|
|
67
72
|
"jc_Latitude": "纬度",
|
|
68
73
|
"jc_License %s": "许可证 %s",
|
|
@@ -2,7 +2,6 @@ import { type JSX } from 'react';
|
|
|
2
2
|
import 'ace-builds/src-min-noconflict/mode-json';
|
|
3
3
|
import 'ace-builds/src-min-noconflict/mode-json5';
|
|
4
4
|
import 'ace-builds/src-min-noconflict/mode-yaml';
|
|
5
|
-
import 'ace-builds/src-min-noconflict/worker-json';
|
|
6
5
|
import 'ace-builds/src-min-noconflict/theme-clouds_midnight';
|
|
7
6
|
import 'ace-builds/src-min-noconflict/theme-chrome';
|
|
8
7
|
import 'ace-builds/src-min-noconflict/ext-language_tools';
|
|
@@ -3,7 +3,11 @@ import AceEditor from 'react-ace';
|
|
|
3
3
|
import 'ace-builds/src-min-noconflict/mode-json';
|
|
4
4
|
import 'ace-builds/src-min-noconflict/mode-json5';
|
|
5
5
|
import 'ace-builds/src-min-noconflict/mode-yaml';
|
|
6
|
-
|
|
6
|
+
// The `worker-*` files are web worker scripts: they bail out immediately when loaded in a window
|
|
7
|
+
// (`if (typeof e.window != 'undefined' && e.document) return;`), so importing them here never did
|
|
8
|
+
// anything. As ES modules `this` is `undefined` instead of the global, which made them throw
|
|
9
|
+
// "Cannot read properties of undefined (reading 'window')" and blocked the whole app from starting.
|
|
10
|
+
// Ace loads its workers over `ace.config.setModuleUrl()` when they are actually wanted.
|
|
7
11
|
import 'ace-builds/src-min-noconflict/theme-clouds_midnight';
|
|
8
12
|
import 'ace-builds/src-min-noconflict/theme-chrome';
|
|
9
13
|
import 'ace-builds/src-min-noconflict/ext-language_tools';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Editor.js","sourceRoot":"src/","sources":["JsonConfigComponent/wrapper/Components/Editor.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAExC,OAAO,SAAS,MAAM,WAAW,CAAC;AAClC,OAAO,yCAAyC,CAAC;AACjD,OAAO,0CAA0C,CAAC;AAClD,OAAO,yCAAyC,CAAC;AACjD,
|
|
1
|
+
{"version":3,"file":"Editor.js","sourceRoot":"src/","sources":["JsonConfigComponent/wrapper/Components/Editor.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAExC,OAAO,SAAS,MAAM,WAAW,CAAC;AAClC,OAAO,yCAAyC,CAAC;AACjD,OAAO,0CAA0C,CAAC;AAClD,OAAO,yCAAyC,CAAC;AACjD,iGAAiG;AACjG,kGAAkG;AAClG,6FAA6F;AAC7F,oGAAoG;AACpG,wFAAwF;AACxF,OAAO,qDAAqD,CAAC;AAC7D,OAAO,4CAA4C,CAAC;AACpD,OAAO,kDAAkD,CAAC;AAE1D,MAAM,MAAM,GAAwC;IAChD,SAAS,EAAE;QACP,MAAM,EAAE,eAAe;QACvB,SAAS,EAAE,GAAG;KACjB;IACD,WAAW,EAAE;QACT,MAAM,EAAE,qBAAqB;QAC7B,SAAS,EAAE,GAAG;KACjB;CACJ,CAAC;AAcF,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,KAAkB;IAC7C,OAAO,CACH,oBAAC,SAAS,IACN,KAAK,EAAE,KAAK,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,EACvG,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,MAAM,EAC1B,KAAK,EAAC,MAAM,EACZ,MAAM,EAAC,MAAM,EACb,eAAe,EAAE,KAAK,CAAC,aAAa,EACpC,UAAU,EAAE,KAAK,CAAC,aAAa,EAC/B,mBAAmB,EAAE,KAAK,CAAC,aAAa,EACxC,YAAY,EAAE,KAAK,CAAC,YAAY,EAChC,KAAK,EAAE,KAAK,CAAC,SAAS,KAAK,MAAM,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,QAAQ,EAChE,KAAK,EAAE,KAAK,CAAC,KAAK,EAClB,QAAQ,EAAE,CAAC,KAAK,CAAC,QAAQ,EACzB,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,EAChD,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,mBAAmB,EACvC,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,EAAE,EAC9B,UAAU,EAAE;YACR,yBAAyB,EAAE,IAAI;YAC/B,wBAAwB,EAAE,IAAI;YAC9B,cAAc,EAAE,IAAI;YAEpB,eAAe,EAAE,KAAK,CAAC,aAAa;YACpC,OAAO,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS;SAC/C,EACD,WAAW,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,GACxC,CACL,CAAC;AACN,CAAC","sourcesContent":["import React, { type JSX } from 'react';\n\nimport AceEditor from 'react-ace';\nimport 'ace-builds/src-min-noconflict/mode-json';\nimport 'ace-builds/src-min-noconflict/mode-json5';\nimport 'ace-builds/src-min-noconflict/mode-yaml';\n// The `worker-*` files are web worker scripts: they bail out immediately when loaded in a window\n// (`if (typeof e.window != 'undefined' && e.document) return;`), so importing them here never did\n// anything. As ES modules `this` is `undefined` instead of the global, which made them throw\n// \"Cannot read properties of undefined (reading 'window')\" and blocked the whole app from starting.\n// Ace loads its workers over `ace.config.setModuleUrl()` when they are actually wanted.\nimport 'ace-builds/src-min-noconflict/theme-clouds_midnight';\nimport 'ace-builds/src-min-noconflict/theme-chrome';\nimport 'ace-builds/src-min-noconflict/ext-language_tools';\n\nconst styles: Record<string, React.CSSProperties> = {\n jsonError: {\n border: '1px solid red',\n minHeight: 200,\n },\n jsonNoError: {\n border: '1px solid #00000000',\n minHeight: 200,\n },\n};\n\ninterface EditorProps {\n fontSize?: number;\n value?: string;\n defaultValue?: string;\n mode?: 'json' | 'css' | 'html' | 'json5' | 'yaml';\n name: string;\n onChange?: (newValue: string) => void;\n themeType: string;\n editValueMode?: boolean; // flag that indicates the \"value edit mode\"\n error?: boolean;\n}\n\nexport default function Editor(props: EditorProps): JSX.Element {\n return (\n <AceEditor\n style={props.error === true ? styles.jsonError : props.error === false ? styles.jsonNoError : undefined}\n mode={props.mode || 'json'}\n width=\"100%\"\n height=\"100%\"\n showPrintMargin={props.editValueMode}\n showGutter={props.editValueMode}\n highlightActiveLine={props.editValueMode}\n defaultValue={props.defaultValue}\n theme={props.themeType === 'dark' ? 'clouds_midnight' : 'chrome'}\n value={props.value}\n readOnly={!props.onChange}\n onChange={newValue => props.onChange?.(newValue)}\n name={props.name || 'UNIQUE_ID_OF_DIV1'}\n fontSize={props.fontSize || 14}\n setOptions={{\n enableBasicAutocompletion: true,\n enableLiveAutocompletion: true,\n enableSnippets: true,\n\n showLineNumbers: props.editValueMode,\n tabSize: props.editValueMode ? 2 : undefined,\n }}\n editorProps={{ $blockScrolling: true }}\n />\n );\n}\n"]}
|
package/build/index.d.ts
CHANGED
|
@@ -4,15 +4,5 @@ import ConfigPanel from './JsonConfigComponent/ConfigPanel';
|
|
|
4
4
|
import ConfigGeneric from './JsonConfigComponent/ConfigGeneric';
|
|
5
5
|
export type { DeviceManagerPropsProps, ConfigGenericProps, ConfigGenericState, } from './JsonConfigComponent/ConfigGeneric';
|
|
6
6
|
export type { ConfigItemType, ConfigItemConfirmData, ConfigItem, ConfigItemAlive, ConfigItemSelectOption, ConfigItemPanel, ConfigItemPattern, ConfigItemChip, ConfigItemComponent, ConfigItemTabs, ConfigItemText, ConfigItemColor, ConfigItemCheckbox, ConfigItemNumber, ConfigItemQrCode, ConfigItemQrCodeSendTo, ConfigItemPassword, ConfigItemObjectId, ConfigItemSlider, ConfigItemTopic, ConfigItemIP, ConfigItemUser, ConfigItemStaticDivider, ConfigItemStaticHeader, ConfigItemStaticImage, ConfigItemStaticText, ConfigItemRoom, ConfigItemFunc, ConfigItemSelect, ConfigItemAutocomplete, ConfigItemSetState, ConfigItemAutocompleteSendTo, ConfigItemAccordion, ConfigItemDivider, ConfigItemHeader, ConfigItemCoordinates, ConfigItemCustom, ConfigItemDatePicker, ConfigItemDeviceManager, ConfigItemLanguage, ConfigItemPort, ConfigItemImageSendTo, ConfigItemSendTo, ConfigItemState, ConfigItemTextSendTo, ConfigItemSelectSendTo, ConfigItemTable, ConfigItemTimePicker, ConfigItemCertCollection, ConfigItemCRON, ConfigItemCertificateSelect, ConfigItemCredentialSelect, ConfigItemLicense, ConfigItemCertificates, ConfigItemCheckLicense, ConfigItemUUID, ConfigItemJsonEditor, ConfigItemYamlEditor, ConfigItemInterface, ConfigItemImageUpload, ConfigItemInstanceSelect, ConfigItemFile, ConfigItemFileSelector, ConfigItemAny, BackEndCommandType, BackEndCommandGeneric, BackEndCommandNoOperation, BackEndCommandRefresh, BackEndCommandOpenLink, BackEndCommandMessage, BackEndCommand, } from './types';
|
|
7
|
-
|
|
8
|
-
* Generation of the GUI API this build of `@iobroker/json-config` provides.
|
|
9
|
-
*
|
|
10
|
-
* A custom component declares the generation it was built against via `guiApi` in its jsonConfig
|
|
11
|
-
* schema. Generation `2` is `@iobroker/gui-components` (React 19 / MUI 9); everything below was
|
|
12
|
-
* built against the legacy `@iobroker/adapter-react-v5` (React 18 / MUI 6) and cannot run here,
|
|
13
|
-
* because the shared React/MUI singletons it expects are no longer provided.
|
|
14
|
-
*
|
|
15
|
-
* Bump this only when a change actually breaks components built against the previous generation.
|
|
16
|
-
*/
|
|
17
|
-
export declare const GUI_API_GENERATION = 2;
|
|
7
|
+
export { GUI_API_GENERATION, checkGuiApiCompatibility, type GuiApiVerdict } from './JsonConfigComponent/guiApiGate';
|
|
18
8
|
export { JsonConfig, JsonConfigComponent, ConfigPanel, ConfigGeneric };
|
package/build/index.js
CHANGED
|
@@ -2,16 +2,6 @@ import JsonConfig from './JsonConfig';
|
|
|
2
2
|
import JsonConfigComponent from './JsonConfigComponent';
|
|
3
3
|
import ConfigPanel from './JsonConfigComponent/ConfigPanel';
|
|
4
4
|
import ConfigGeneric from './JsonConfigComponent/ConfigGeneric';
|
|
5
|
-
|
|
6
|
-
* Generation of the GUI API this build of `@iobroker/json-config` provides.
|
|
7
|
-
*
|
|
8
|
-
* A custom component declares the generation it was built against via `guiApi` in its jsonConfig
|
|
9
|
-
* schema. Generation `2` is `@iobroker/gui-components` (React 19 / MUI 9); everything below was
|
|
10
|
-
* built against the legacy `@iobroker/adapter-react-v5` (React 18 / MUI 6) and cannot run here,
|
|
11
|
-
* because the shared React/MUI singletons it expects are no longer provided.
|
|
12
|
-
*
|
|
13
|
-
* Bump this only when a change actually breaks components built against the previous generation.
|
|
14
|
-
*/
|
|
15
|
-
export const GUI_API_GENERATION = 2;
|
|
5
|
+
export { GUI_API_GENERATION, checkGuiApiCompatibility } from './JsonConfigComponent/guiApiGate';
|
|
16
6
|
export { JsonConfig, JsonConfigComponent, ConfigPanel, ConfigGeneric };
|
|
17
7
|
//# sourceMappingURL=index.js.map
|
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"src/","sources":["index.tsx"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,cAAc,CAAC;AACtC,OAAO,mBAAmB,MAAM,uBAAuB,CAAC;AACxD,OAAO,WAAW,MAAM,mCAAmC,CAAC;AAC5D,OAAO,aAAa,MAAM,qCAAqC,CAAC;AAkFhE
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"src/","sources":["index.tsx"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,cAAc,CAAC;AACtC,OAAO,mBAAmB,MAAM,uBAAuB,CAAC;AACxD,OAAO,WAAW,MAAM,mCAAmC,CAAC;AAC5D,OAAO,aAAa,MAAM,qCAAqC,CAAC;AAkFhE,OAAO,EAAE,kBAAkB,EAAE,wBAAwB,EAAsB,MAAM,kCAAkC,CAAC;AAEpH,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,WAAW,EAAE,aAAa,EAAE,CAAC","sourcesContent":["import JsonConfig from './JsonConfig';\nimport JsonConfigComponent from './JsonConfigComponent';\nimport ConfigPanel from './JsonConfigComponent/ConfigPanel';\nimport ConfigGeneric from './JsonConfigComponent/ConfigGeneric';\n\nexport type {\n DeviceManagerPropsProps,\n ConfigGenericProps,\n ConfigGenericState,\n} from './JsonConfigComponent/ConfigGeneric';\n\nexport type {\n ConfigItemType,\n ConfigItemConfirmData,\n ConfigItem,\n ConfigItemAlive,\n ConfigItemSelectOption,\n ConfigItemPanel,\n ConfigItemPattern,\n ConfigItemChip,\n ConfigItemComponent,\n ConfigItemTabs,\n ConfigItemText,\n ConfigItemColor,\n ConfigItemCheckbox,\n ConfigItemNumber,\n ConfigItemQrCode,\n ConfigItemQrCodeSendTo,\n ConfigItemPassword,\n ConfigItemObjectId,\n ConfigItemSlider,\n ConfigItemTopic,\n ConfigItemIP,\n ConfigItemUser,\n ConfigItemStaticDivider,\n ConfigItemStaticHeader,\n ConfigItemStaticImage,\n ConfigItemStaticText,\n ConfigItemRoom,\n ConfigItemFunc,\n ConfigItemSelect,\n ConfigItemAutocomplete,\n ConfigItemSetState,\n ConfigItemAutocompleteSendTo,\n ConfigItemAccordion,\n ConfigItemDivider,\n ConfigItemHeader,\n ConfigItemCoordinates,\n ConfigItemCustom,\n ConfigItemDatePicker,\n ConfigItemDeviceManager,\n ConfigItemLanguage,\n ConfigItemPort,\n ConfigItemImageSendTo,\n ConfigItemSendTo,\n ConfigItemState,\n ConfigItemTextSendTo,\n ConfigItemSelectSendTo,\n ConfigItemTable,\n ConfigItemTimePicker,\n ConfigItemCertCollection,\n ConfigItemCRON,\n ConfigItemCertificateSelect,\n ConfigItemCredentialSelect,\n ConfigItemLicense,\n ConfigItemCertificates,\n ConfigItemCheckLicense,\n ConfigItemUUID,\n ConfigItemJsonEditor,\n ConfigItemYamlEditor,\n ConfigItemInterface,\n ConfigItemImageUpload,\n ConfigItemInstanceSelect,\n ConfigItemFile,\n ConfigItemFileSelector,\n ConfigItemAny,\n BackEndCommandType,\n BackEndCommandGeneric,\n BackEndCommandNoOperation,\n BackEndCommandRefresh,\n BackEndCommandOpenLink,\n BackEndCommandMessage,\n BackEndCommand,\n} from './types';\n\nexport { GUI_API_GENERATION, checkGuiApiCompatibility, type GuiApiVerdict } from './JsonConfigComponent/guiApiGate';\n\nexport { JsonConfig, JsonConfigComponent, ConfigPanel, ConfigGeneric };\n"]}
|