+ {icon}
+ {text}
+
+ }
+ />
+ );
+ }
+
+ return (
+ this.onClick()}
+ />
+ );
+ }
+
+ renderRadio(isOn: boolean, style: CSSProperties): React.JSX.Element {
+ const on = this.state.rxData.text_true !== undefined ? this.state.rxData.text_true : this.state.rxData.on_text; // back compatibility with radio on/off
+ const off =
+ this.state.rxData.text_false !== undefined ? this.state.rxData.text_false : this.state.rxData.off_text; // back compatibility with radio on/off
+ const onIcon = this.renderIcon(true);
+ const offIcon = this.renderIcon(false);
+
+ let variant = this.state.rxData.variant === undefined ? 'contained' : this.state.rxData.variant;
+ if (variant === 'standard') {
+ variant = 'text';
+ }
+
+ const buttonStyle =
+ this.state.rxData.orientation === 'vertical'
+ ? { height: '50%' }
+ : this.state.rxData.notEqualLength
+ ? undefined
+ : { width: '50%' };
+
+ return (
+
+
+
+
+ );
+ }
+
+ componentDidUpdate(/* prevProps, prevState */): void {
+ if (!this.refService.current) {
+ return;
+ }
+ if (
+ this.state.rxData.type === 'image' ||
+ this.state.rxData.type === 'html' ||
+ (this.state.rxData.type === 'button' && this.state.rxData.jquery_style)
+ ) {
+ if (this.state.rxData.type === 'button') {
+ const el = this.refService.current.getElementsByClassName('vis-widget-body');
+ if (el?.length && !(this.refService.current as any)._jQueryDone) {
+ (this.refService.current as any)._jQueryDone = true;
+ (window.jQuery as any)(el[0]).button();
+ const textEl = el[0].getElementsByClassName('ui-button-text');
+ if (textEl?.length) {
+ (textEl[0] as any).style.display = 'flex';
+ (textEl[0] as any).style.alignItems = 'center';
+ }
+ }
+ }
+
+ if (
+ this.refService.current.clientWidth !== this.state.width ||
+ this.refService.current.clientHeight !== this.state.height
+ ) {
+ this.setState({
+ width: this.refService.current.clientWidth,
+ height: this.refService.current.clientHeight,
+ });
+ }
+ }
+ }
+
+ renderWidgetBody(props: RxRenderWidgetProps): React.JSX.Element {
+ super.renderWidgetBody(props);
+ const isOn = this.isOn();
+
+ const buttonStyle: CSSProperties = {};
+ // apply style from the element
+ Object.keys(this.state.rxStyle).forEach(attr => {
+ const value = this.state.rxStyle[attr as keyof typeof this.state.rxStyle];
+ if (value !== null && value !== undefined && VisRxWidget.POSSIBLE_MUI_STYLES.includes(attr)) {
+ attr = attr.replace(/(-\w)/g, text => text[1].toUpperCase());
+ (buttonStyle as any)[attr] = value;
+ }
+ });
+
+ let type = this.state.rxData.type;
+ if (!type && this.props.tpl === 'tplJquiRadio') {
+ type = 'radio';
+ }
+ if (buttonStyle.borderWidth) {
+ buttonStyle.borderWidth = VisBaseWidget.correctStylePxValue(buttonStyle.borderWidth);
+ }
+ if (buttonStyle.fontSize) {
+ buttonStyle.fontSize = VisBaseWidget.correctStylePxValue(buttonStyle.fontSize);
+ }
+
+ // extra no rxData here, as it is not possible to set it with bindings
+ buttonStyle.width = '100%';
+ buttonStyle.height = '100%';
+ buttonStyle.minWidth = 'unset';
+ let content;
+ const bodyStyle: CSSProperties = { textAlign: 'center' };
+ if (type === 'radio') {
+ content = this.renderRadio(isOn, buttonStyle);
+ } else if (type === 'html' || (type === 'button' && this.state.rxData.jquery_style)) {
+ bodyStyle.display = 'flex';
+ bodyStyle.flexDirection = this.state.height > this.state.width ? 'column' : 'row';
+ bodyStyle.alignItems = 'center';
+ bodyStyle.justifyContent = 'center';
+ bodyStyle.cursor = !this.state.rxData.readOnly ? 'pointer' : undefined;
+
+ content = this.renderHtml(isOn);
+ } else if (type === 'switch') {
+ content = this.renderSwitch(isOn, buttonStyle);
+ } else if (type === 'checkbox') {
+ content = this.renderCheckbox(isOn, buttonStyle);
+ } else if (type === 'image') {
+ bodyStyle.cursor = !this.state.rxData.readOnly ? 'pointer' : undefined;
+ content = this.renderIcon(isOn, !!buttonStyle);
+ } else if (type === 'round-button') {
+ content = this.renderFab(isOn, buttonStyle);
+ } else if (!this.state.rxData.jquery_style) {
+ content = this.renderButton(isOn, buttonStyle);
+ }
+
+ const result = (
+ this.onClick() : undefined}
+ >
+ {content}
+
+ );
+ if (isOn && this.state.rxData.alt_true) {
+ return (
+
+ {result}
+
+ );
+ }
+ if (!isOn && this.state.rxData.alt_false) {
+ return (
+
+ {result}
+
+ );
+ }
+ return result;
+ }
+}
+
+export default JQuiBinaryState;
diff --git a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiButton.tsx b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiButton.tsx
index 7ad86157..decadfac 100644
--- a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiButton.tsx
+++ b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiButton.tsx
@@ -1,1042 +1,1042 @@
-/**
- * ioBroker.vis-2
- * https://github.com/ioBroker/ioBroker.vis-2
- *
- * Copyright (c) 2023-2024 Denis Haev https://github.com/GermanBluefox,
- * Creative Common Attribution-NonCommercial (CC BY-NC)
- *
- * http://creativecommons.org/licenses/by-nc/4.0/
- *
- * Short content:
- * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
- * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
- * (Free for non-commercial use).
- */
-
-import type { CSSProperties } from 'react';
-import React from 'react';
-
-import {
- Button,
- Dialog,
- DialogContent,
- DialogTitle,
- IconButton,
- Popper,
- Paper,
- TextField,
- DialogActions,
-} from '@mui/material';
-
-import { Close, Check } from '@mui/icons-material';
-
-import { I18n, Icon, Utils, IconCopy } from '@iobroker/adapter-react-v5';
-
-import VisBaseWidget from '@/Vis/visBaseWidget';
-import type {
- RxRenderWidgetProps,
- RxWidgetInfo,
- RxWidgetInfoAttributesField,
- RxWidgetInfoWriteable,
- Writeable,
- VisBaseWidgetProps,
- VisWidgetCommand,
-} from '@iobroker/types-vis-2';
-import { isVarFinite } from '../../../Utils/utils';
-import VisRxWidget, { type VisRxWidgetState } from '../../visRxWidget';
-
-// eslint-disable-next-line no-use-before-define
-export type JQuiButtonDataProps = {
- buttontext: string;
- html: string;
- Password: string;
- nav_view: string;
- buttontext_view: boolean;
- sub_view: string;
- href: string;
- url: string;
- target: string;
- no_style: boolean;
- jquery_style: boolean;
- padding: number;
- variant: string;
- color: string;
- html_prepend: string;
- html_append: string;
- visResizable: boolean;
- src: string;
- icon: string;
- invert_icon: boolean;
- imageHeight: number;
- html_dialog: string;
- contains_view: string;
- title: string;
- modal: boolean;
- dialog_width: string;
- dialog_height: string;
- dialog_class: string;
- persistent: boolean;
- preload: boolean;
- closeOnClick: boolean;
- hideCloseButton: boolean;
- dialogBackgroundColor: string;
- dialogTitleColor: string;
- overflowX: string;
- overflowY: string;
- setId: string;
- setValue: string;
- dialogName: string;
- externalDialog: boolean;
- autoclose: number | string | boolean;
- text: string;
-};
-
-export interface JQuiButtonState extends VisRxWidgetState {
- width: number;
- height: number;
- dialogVisible: boolean;
- showPassword: boolean;
- password: string;
- passwordError: boolean;
-}
-
-class JQuiButton<
- P extends JQuiButtonDataProps = JQuiButtonDataProps,
- S extends JQuiButtonState = JQuiButtonState,
-> extends VisRxWidget {
- refButton: React.RefObject;
-
- refDialog: React.RefObject;
-
- hideTimeout: ReturnType;
-
- setObjectType: string;
-
- constructor(props: VisBaseWidgetProps) {
- super(props);
- (this.state as JQuiButtonState).width = 0;
- (this.state as JQuiButtonState).height = 0;
- (this.state as JQuiButtonState).dialogVisible = false;
- (this.state as JQuiButtonState).showPassword = false;
- (this.state as JQuiButtonState).password = '';
- this.refButton = React.createRef();
- this.refDialog = React.createRef();
- }
-
- static getWidgetInfo(): RxWidgetInfo {
- return {
- id: 'tplJquiButtonLink',
- visSet: 'jqui',
- visName: 'Button Link',
- visSetLabel: 'jqui_set_label',
- visWidgetLabel: 'jqui_button_link',
- visPrev: 'widgets/jqui/img/Prev_ButtonLink.png',
- visOrder: 1,
- visAttrs: [
- {
- name: 'common',
- fields: [
- {
- name: 'buttontext',
- type: 'text',
- default: 'URL',
- hidden: (data: any) =>
- !!data.html || !!(data.buttontext_view && data.nav_view) || !!data.externalDialog,
- },
- {
- name: 'html',
- type: 'html',
- default: '',
- tooltip: 'jqui_html_tooltip',
- disabled: (data: any) =>
- !!data.buttontext || !!data.icon || !!data.src || !!data.externalDialog,
- },
- {
- name: 'Password',
- type: 'password',
- label: 'password',
- tooltip: 'jqui_password_tooltip',
- disabled: (data: any) =>
- !data.nav_view && !data.url && !data.href && !data.html_dialog && !data.contains_view,
- },
- ],
- },
- {
- name: 'view',
- label: 'jqui_view_group',
- hidden: (data: any) => !!data.url || !!data.href || !!data.html_dialog || !!data.contains_view,
- fields: [
- {
- name: 'nav_view',
- label: 'jqui_nav_view',
- type: 'views',
- },
- {
- name: 'buttontext_view',
- label: 'jqui_buttontext_view',
- type: 'checkbox',
- hidden: (data: any) => !data.nav_view,
- },
- {
- name: 'sub_view',
- label: 'basic_sub_view',
- type: 'text',
- tooltip: 'sub_view_tooltip',
- hidden: (data: any) => !data.nav_view,
- },
- ],
- },
- {
- name: 'URL',
- label: 'jqui_url_group',
- hidden: (data: any) => !!data.html_dialog || !!data.contains_view || !!data.nav_view,
- fields: [
- {
- name: 'href',
- label: 'jqui_url_in_browser',
- type: 'url',
- hidden: (data: any) => !!data.url,
- tooltip: 'jqui_href_tooltip',
- },
- {
- name: 'url',
- label: 'jqui_url_in_background',
- type: 'url',
- hidden: (data: any) => !!data.href,
- tooltip: 'jqui_url_tooltip',
- },
- {
- name: 'target',
- type: 'auto',
- options: ['_blank', '_self', '_parent', '_top'],
- hidden: (data: any) => !!data.url || !data.href,
- },
- ],
- },
- {
- name: 'style',
- label: 'Style',
- hidden: (data: any) => !!data.externalDialog,
- fields: [
- { name: 'no_style', type: 'checkbox', hidden: (data: any) => data.jquery_style },
- {
- name: 'jquery_style',
- label: 'jqui_jquery_style',
- type: 'checkbox',
- hidden: (data: any) => data.no_style,
- },
- {
- name: 'padding',
- type: 'slider',
- min: 0,
- max: 100,
- default: 5,
- // hidden: (data: any) => !data.no_style && !data.jquery_style,
- },
- {
- name: 'variant',
- label: 'jqui_variant',
- type: 'select',
- noTranslation: true,
- options: ['contained', 'outlined', 'standard'],
- default: 'contained',
- hidden: (data: any) => data.jquery_style || data.no_style,
- },
- {
- name: 'color',
- label: 'jqui_button_color',
- type: 'select',
- noTranslation: true,
- options: ['', 'primary', 'secondary'],
- default: '',
- hidden: (data: any) => data.jquery_style || data.no_style,
- },
- { name: 'html_prepend', type: 'html' },
- { name: 'html_append', type: 'html' },
- {
- name: 'visResizable', // reserved name for resizable
- label: 'visResizable',
- type: 'checkbox',
- default: false,
- desiredSize: false, // If sizes should be deleted or set to specific value. `false` - delete sizes, or {width: 100, height: 100}
- },
- ],
- },
- {
- name: 'icon',
- hidden: (data: any) => !!data.externalDialog || data.jquery_style,
- fields: [
- {
- name: 'src',
- label: 'jqui_image',
- type: 'image',
- hidden: (data: any) => data.icon,
- },
- {
- name: 'icon',
- label: 'jqui_icon',
- type: 'icon64',
- hidden: (data: any) => data.src,
- },
- {
- name: 'invert_icon',
- type: 'checkbox',
- hidden: (data: any) => !data.icon && !data.src,
- },
- {
- name: 'imageHeight',
- type: 'slider',
- min: 0,
- max: 200,
- default: 100,
- hidden: (data: any) => !data.src,
- },
- ],
- },
- {
- name: 'dialog',
- hidden: (data: any) => !!data.url || !!data.href || !!data.nav_view,
- fields: [
- {
- name: 'html_dialog',
- type: 'html',
- hidden: (data: any) => !!data.contains_view,
- },
- {
- name: 'contains_view',
- type: 'views',
- hidden: (data: any) => !!data.html_dialog,
- },
- {
- name: 'title',
- type: 'text',
- hidden: (data: any) => !data.html_dialog && !data.contains_view,
- },
- {
- name: 'autoclose',
- type: 'slider',
- min: 0,
- max: 30000,
- step: 100,
- hidden: (data: any) => !data.html_dialog && !data.contains_view,
- },
- {
- name: 'modal',
- type: 'checkbox',
- default: true,
- hidden: (data: any) => !data.html_dialog && !data.contains_view,
- },
- {
- name: 'dialog_width',
- type: 'text',
- hidden: (data: any) => !data.html_dialog && !data.contains_view,
- },
- {
- name: 'dialog_height',
- type: 'text',
- hidden: (data: any) => !data.html_dialog && !data.contains_view,
- },
- {
- name: 'dialog_class',
- label: 'CSS Class',
- type: 'text',
- hidden: (data: any) => !data.html_dialog && !data.contains_view,
- },
- {
- name: 'persistent',
- type: 'checkbox',
- hidden: (data: any) => !data.html_dialog && !data.contains_view,
- },
- {
- name: 'preload',
- type: 'checkbox',
- hidden: (data: any) => !data.html_dialog && !data.contains_view,
- },
- {
- name: 'closeOnClick',
- type: 'checkbox',
- hidden: (data: any) => !data.html_dialog && !data.contains_view,
- },
- {
- name: 'hideCloseButton',
- label: 'jqui_hide_close_button',
- type: 'checkbox',
- hidden: (data: any) => !data.html_dialog && !data.contains_view && !!data.closeOnClick,
- },
- {
- name: 'dialogBackgroundColor',
- label: 'Background color',
- type: 'color',
- hidden: (data: any) => !data.html_dialog && !data.contains_view,
- },
- {
- name: 'dialogTitleColor',
- type: 'color',
- label: 'Text color',
- hidden: (data: any) => !data.html_dialog && !data.contains_view,
- },
- /*
- {
- name: 'dialog_top',
- type: 'text',
- hidden: (data: any) => !data.html_dialog && !data.contains_view,
- },
- {
- name: 'dialog_left',
- type: 'text',
- hidden: (data: any) => !data.html_dialog && !data.contains_view,
- },
- */
- {
- name: 'overflowX',
- type: 'select',
- noTranslation: true,
- options: ['', 'auto', 'hidden', 'visible', 'scroll', 'initial', 'inherit'],
- hidden: (data: any) => !data.html_dialog && !data.contains_view,
- },
- {
- name: 'overflowY',
- type: 'select',
- noTranslation: true,
- options: ['', 'auto', 'hidden', 'visible', 'scroll', 'initial', 'inherit'],
- hidden: (data: any) => !data.html_dialog && !data.contains_view,
- },
- {
- name: 'setId',
- type: 'id',
- tooltip: 'jqui_dialog_set_id_tooltip',
- hidden: (data: any) => !data.html_dialog && !data.contains_view,
- },
- {
- name: 'setValue',
- type: 'text',
- hidden: (data: any) => !data.setId || (!data.html_dialog && !data.contains_view),
- },
- {
- name: 'dialogName',
- label: 'jqui_dialog_name',
- type: 'text',
- hidden: (data: any) => !data.html_dialog && !data.contains_view,
- },
- {
- name: 'externalDialog',
- label: 'jqui_external_dialog',
- tooltip: 'jqui_external_dialog_tooltip',
- type: 'checkbox',
- hidden: (data: any) => !data.html_dialog && !data.contains_view,
- },
- ],
- },
- ],
- } as const;
- }
-
- static findField(
- widgetInfo: RxWidgetInfo | RxWidgetInfoWriteable,
- name: string,
- ): Writeable | null {
- return VisRxWidget.findField(widgetInfo as RxWidgetInfo, name) as unknown as Writeable;
- }
-
- // eslint-disable-next-line class-methods-use-this
- getWidgetInfo(): RxWidgetInfo {
- return JQuiButton.getWidgetInfo();
- }
-
- async componentDidMount() {
- super.componentDidMount();
- await this.componentDidUpdate();
- }
-
- async componentWillUnmount() {
- this.hideTimeout && clearTimeout(this.hideTimeout);
- this.hideTimeout = null;
- super.componentWillUnmount();
- }
-
- async componentDidUpdate() {
- if (this.refButton.current) {
- if (this.state.rxData.jquery_style && !(this.refButton.current as any)._jQueryDone) {
- (this.refButton.current as any)._jQueryDone = true;
- (window.jQuery as any)(this.refButton.current).button();
- }
- if (
- this.refButton.current.clientWidth !== this.state.width ||
- this.refButton.current.clientHeight !== this.state.height
- ) {
- this.setState({
- width: this.refButton.current.clientWidth,
- height: this.refButton.current.clientHeight,
- });
- }
- }
- // from base class
- if (
- this.refService.current &&
- (this.state.rxData.html_dialog || this.state.rxData.contains_view) &&
- !(this.refService.current as any)._showDialog
- ) {
- (this.refService.current as any)._showDialog = this.showDialog;
- }
- if (this.refService.current) {
- const dialogName = this.refService.current.dataset.dialogName;
- if ((dialogName || '') !== (this.state.rxData.dialogName || '')) {
- if (!this.state.rxData.dialogName) {
- delete this.refService.current.dataset.dialogName;
- } else {
- this.refService.current.dataset.dialogName = this.state.rxData.dialogName;
- }
- }
- }
- }
-
- showDialog = (show: boolean) => {
- this.setState({ dialogVisible: show });
-
- // Auto-close
- let timeout = this.state.rxData.autoclose;
- if (timeout === true || timeout === 'true') {
- timeout = 10000;
- }
- if (timeout === null || timeout === undefined || timeout === '') {
- return;
- }
- timeout = parseInt(timeout as string, 10);
- if (timeout < 60) {
- // maybe this is seconds
- timeout *= 1000;
- }
- timeout = timeout || 1000;
-
- if (timeout) {
- if (show) {
- this.hideTimeout = setTimeout(() => {
- this.hideTimeout = null;
- this.showDialog(false);
- }, timeout);
- } else if (this.hideTimeout) {
- clearTimeout(this.hideTimeout);
- this.hideTimeout = null;
- }
- }
- };
-
- onPasswordEnter() {
- if (this.state.password === this.state.rxData.Password) {
- this.setState({ showPassword: false }, () => this.onClick(true));
- } else {
- window.alert(I18n.t('Wrong password'));
- this.setState({ passwordError: true }, () => {
- setTimeout(() => this.setState({ passwordError: false }), 3000);
- });
- }
- }
-
- renderPasswordDialog() {
- if (!this.state.showPassword) {
- return null;
- }
- return (
-
- );
- }
-
- async setObjectWithState(oid: string, value: ioBroker.State['val']) {
- if (this.setObjectType === undefined) {
- try {
- const obj = await this.props.context.socket.getObject(oid);
- this.setObjectType = obj?.common?.type || 'string';
- await this.setObjectWithState(oid, value);
- } catch (error) {
- console.warn(`Object ${oid} not found: ${error}`);
- }
- return;
- }
- if (this.setObjectType === 'boolean') {
- value =
- value === 'true' || value === true || value === '1' || value === 1 || value === 'on' || value === 'ON';
- } else if (this.setObjectType === 'number') {
- value = parseFloat(value as string);
- } else if (value !== null && value !== undefined) {
- value = value.toString();
- }
-
- await this.props.context.setValue(oid, value);
- }
-
- onCommand(command: VisWidgetCommand) {
- super.onCommand(command);
- if (command === 'openDialog') {
- this.showDialog(true);
- return true;
- }
- if (command === 'closeDialog') {
- this.showDialog(false);
- return true;
- }
- return false;
- }
-
- onClick(passwordChecked?: boolean) {
- if (this.state.dialogVisible) {
- return;
- }
-
- if (!passwordChecked && this.state.rxData.Password) {
- if (this.props.editMode) {
- window.alert(I18n.t('Ignored in edit mode'));
- } else {
- this.setState({ showPassword: true, password: '' });
- }
- return;
- }
-
- if (this.state.rxData.nav_view) {
- this.props.context.changeView(this.state.rxData.nav_view);
- } else if (!this.props.editMode && this.state.rxData.href) {
- if (
- this.state.rxData.target ||
- (this.props.tpl === 'tplJquiButtonLinkBlank' && this.state.rxData.target === undefined)
- ) {
- window.open(this.state.rxData.href, this.state.rxData.target);
- } else {
- window.location.href = this.state.rxData.href;
- }
- } else if (this.state.rxData.url) {
- this.props.context.socket
- .getRawSocket()
- .emit('httpGet', this.state.rxData.url, (data: any) =>
- console.log('httpGet', this.state.rxData.url, data),
- );
- }
-
- if (this.state.rxData.html_dialog || this.state.rxData.contains_view) {
- if (this.state.rxData.setId) {
- this.setObjectWithState(this.state.rxData.setId, this.state.rxData.setValue).catch(error =>
- console.warn(`Cannot set state: ${error}`),
- );
- }
- // show dialog
- this.showDialog(true);
- }
- }
-
- renderRxDialog(dialogStyle: CSSProperties, content: React.JSX.Element) {
- console.log('test');
- if (this.state.rxData.modal) {
- console.log('in');
- return (
-
- );
- }
-
- if (!this.state.dialogVisible) {
- dialogStyle.display = 'none';
- }
-
- if (!dialogStyle.minWidth || (dialogStyle.minWidth as number) < 200) {
- dialogStyle.minWidth = 200;
- }
- if (!dialogStyle.minHeight || (dialogStyle.minHeight as number) < 100) {
- dialogStyle.minHeight = 100;
- }
-
- dialogStyle.backgroundColor = 'blue';
- const paperStyle = { ...dialogStyle };
- delete paperStyle.top;
- delete paperStyle.left;
- paperStyle.padding = this.state.rxData.title ? '0 24px 24px 24px' : '26px 24px 24px 24px';
-
- return (
- {
- if (this.state.rxData.closeOnClick) {
- this.showDialog(false);
- }
- }}
- >
-
- {this.state.rxData.title ? (
-
- {this.state.rxData.title}
-
- ) : null}
- this.showDialog(false)}
- >
-
-
- {content}
-
-
- );
- }
-
- renderJQueryDialog(dialogStyle: CSSProperties, content: React.JSX.Element) {
- return (
-
- {this.state.rxData.preload ? content : null}
-
- );
- }
-
- renderDialog() {
- if (
- this.props.editMode ||
- (!this.state.dialogVisible && !this.state.rxData.persistent && !this.state.rxData.externalDialog) ||
- (!this.state.rxData.html_dialog && !this.state.rxData.contains_view)
- ) {
- return null;
- }
-
- // eslint-disable-next-line no-restricted-properties
- // const top = isVarFinite(this.state.rxData.dialog_top) ? parseFloat(this.state.rxData.dialog_top) : this.state.rxData.dialog_top;
- // eslint-disable-next-line no-restricted-properties
- // const left = isVarFinite(this.state.rxData.dialog_left) ? parseFloat(this.state.rxData.dialog_left) : this.state.rxData.dialog_left;
- // eslint-disable-next-line no-restricted-properties
- const width = isVarFinite(this.state.rxData.dialog_width)
- ? parseFloat(this.state.rxData.dialog_width)
- : this.state.rxData.dialog_width;
- // eslint-disable-next-line no-restricted-properties
- const height = isVarFinite(this.state.rxData.dialog_height)
- ? parseFloat(this.state.rxData.dialog_height)
- : this.state.rxData.dialog_height;
-
- const dialogStyle: CSSProperties = {
- minWidth: width || window.innerWidth - 50,
- minHeight: height || window.innerHeight - 50,
- // top: top || top === 0 ? top : undefined,
- // left: left || left === 0 ? left : undefined,
- overflowX: this.state.rxData.overflowX as any,
- overflowY: this.state.rxData.overflowY as any,
- };
-
- let content;
- if (this.state.rxData.contains_view) {
- content = (
-
- {super.getWidgetView(this.state.rxData.contains_view, undefined)}
-
- );
- } else {
- content = (
-
- );
- }
-
- if (this.state.rxData.jquery_style) {
- // return this.renderJQueryDialog(dialogStyle, content);
- }
-
- return this.renderRxDialog(dialogStyle, content);
- }
-
- renderWidgetBody(props: RxRenderWidgetProps) {
- super.renderWidgetBody(props);
-
- const iconStyle: CSSProperties = {
- marginRight: 4,
- filter: this.state.rxData.invert_icon ? 'invert(1)' : undefined,
- };
-
- if (!this.state.rxData.jquery_style && this.state.rxData.src) {
- if (this.state.width > this.state.height) {
- iconStyle.height = `${this.state.rxData.imageHeight || 100}%`;
- iconStyle.width = 'auto';
- } else {
- iconStyle.width = `${this.state.rxData.imageHeight || 100}%`;
- iconStyle.height = 'auto';
- }
- }
- let iconSrc = !this.state.rxData.jquery_style && (this.state.rxData.src || this.state.rxData.icon);
-
- if (iconSrc && iconSrc.startsWith('_PRJ_NAME/')) {
- iconSrc = iconSrc.replace(
- '_PRJ_NAME/',
- `../${this.props.context.adapterName}.${this.props.context.instance}/${this.props.context.projectName}/`,
- );
- }
- const icon = iconSrc ? (
-
- ) : null;
-
- const buttonStyle: CSSProperties = { textTransform: 'none' };
- // apply style from the element
- Object.keys(this.state.rxStyle).forEach(attr => {
- const value = (this.state.rxStyle as any)[attr];
- if (value !== null && value !== undefined && VisRxWidget.POSSIBLE_MUI_STYLES.includes(attr)) {
- attr = attr.replace(/(-\w)/g, text => text[1].toUpperCase());
- (buttonStyle as any)[attr] = value;
- }
- });
- if (buttonStyle.borderWidth) {
- buttonStyle.borderWidth = VisBaseWidget.correctStylePxValue(buttonStyle.borderWidth);
- }
- if (buttonStyle.fontSize) {
- buttonStyle.fontSize = VisBaseWidget.correctStylePxValue(buttonStyle.fontSize);
- }
-
- // the following widgets are resizable by default
- let visResizable = this.state.data.visResizable;
- if (visResizable === undefined || visResizable === null) {
- if (
- this.props.tpl === 'tplJquiButtonNav' ||
- this.props.tpl === 'tplJquiNavPw' ||
- this.props.tpl === 'tplContainerDialog' ||
- this.props.tpl === 'tplContainerIconDialog' ||
- this.props.tpl === 'tplJquiDialog' ||
- this.props.tpl === 'tplJquiIconDialog' ||
- this.props.tpl === 'tplIconHttpGet' ||
- this.props.tpl === 'tplIconLink' ||
- this.props.tpl === 'tplJquiIconNav'
- ) {
- visResizable = true;
- }
- }
-
- // extra no rxData here, as it is not possible to set it with bindings
- if (visResizable) {
- buttonStyle.width = '100%';
- buttonStyle.height = '100%';
- } else {
- buttonStyle.padding = this.state.rxData.padding;
- }
- buttonStyle.minWidth = 'unset';
-
- let buttonText;
- if (this.state.rxData.html) {
- // ignore
- } else if (this.state.rxData.nav_view && this.state.rxData.buttontext_view) {
- buttonText =
- this.props.context.views[this.state.rxData.nav_view]?.settings?.navigationTitle ||
- this.state.rxData.nav_view;
- } else if (this.state.rxData.buttontext === undefined) {
- buttonText = this.state.rxData.text || ''; // back compatibility
- } else {
- buttonText = this.state.rxData.buttontext;
- }
-
- let content;
- if (this.state.rxData.externalDialog) {
- content = this.props.editMode ? (
-
-
{
- e.stopPropagation();
- e.preventDefault();
- const text = `setState('${this.props.context.adapterName}.${this.props.context.instance}.control.command', '${JSON.stringify({ command: 'dialog', instance: window.localStorage.getItem('visInstance'), data: this.state.rxData.dialogName || this.props.id })}')`;
- window.alert(I18n.t('Copied %s', text));
- Utils.copyToClipboard(text);
- }}
- >
-
-
-
{I18n.t('External dialog')}
-
{this.state.rxData.html_dialog ? 'HTML' : `View: ${this.state.rxData.contains_view}`}
-
{`Name: ${this.state.rxData.dialogName ? `${this.state.rxData.dialogName} (${this.props.id})` : this.props.id}`}
-
{I18n.t('You can open dialog with following script:')}
-
{`setState('${this.props.context.adapterName}.${this.props.context.instance}.control.command', '${JSON.stringify({ command: 'dialog', instance: window.localStorage.getItem('visInstance'), data: this.state.rxData.dialogName || this.props.id })}')`}
-
- ) : null;
- } else {
- content = [
- this.state.rxData.html_prepend ? (
-
- ) : null,
- this.state.rxData.html ? (
-
- ) : this.state.rxData.no_style || this.state.rxData.jquery_style ? (
-
- ) : (
-
- ),
- this.state.rxData.html_append ? (
-
- ) : null,
- ];
- }
-
- return (
- this.onClick() : undefined}
- >
- {content}
- {this.renderDialog()}
- {this.renderPasswordDialog()}
-
- );
- }
-}
-
-export default JQuiButton;
+/**
+ * ioBroker.vis-2
+ * https://github.com/ioBroker/ioBroker.vis-2
+ *
+ * Copyright (c) 2023-2025 Denis Haev https://github.com/GermanBluefox,
+ * Creative Common Attribution-NonCommercial (CC BY-NC)
+ *
+ * http://creativecommons.org/licenses/by-nc/4.0/
+ *
+ * Short content:
+ * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
+ * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
+ * (Free for non-commercial use).
+ */
+
+import type { CSSProperties } from 'react';
+import React from 'react';
+
+import {
+ Button,
+ Dialog,
+ DialogContent,
+ DialogTitle,
+ IconButton,
+ Popper,
+ Paper,
+ TextField,
+ DialogActions,
+} from '@mui/material';
+
+import { Close, Check } from '@mui/icons-material';
+
+import { I18n, Icon, Utils, IconCopy } from '@iobroker/adapter-react-v5';
+
+import VisBaseWidget from '@/Vis/visBaseWidget';
+import type {
+ RxRenderWidgetProps,
+ RxWidgetInfo,
+ RxWidgetInfoAttributesField,
+ RxWidgetInfoWriteable,
+ Writeable,
+ VisBaseWidgetProps,
+ VisWidgetCommand,
+} from '@iobroker/types-vis-2';
+import { isVarFinite } from '../../../Utils/utils';
+import VisRxWidget, { type VisRxWidgetState } from '../../visRxWidget';
+
+// eslint-disable-next-line no-use-before-define
+export type JQuiButtonDataProps = {
+ buttontext: string;
+ html: string;
+ Password: string;
+ nav_view: string;
+ buttontext_view: boolean;
+ sub_view: string;
+ href: string;
+ url: string;
+ target: string;
+ no_style: boolean;
+ jquery_style: boolean;
+ padding: number;
+ variant: string;
+ color: string;
+ html_prepend: string;
+ html_append: string;
+ visResizable: boolean;
+ src: string;
+ icon: string;
+ invert_icon: boolean;
+ imageHeight: number;
+ html_dialog: string;
+ contains_view: string;
+ title: string;
+ modal: boolean;
+ dialog_width: string;
+ dialog_height: string;
+ dialog_class: string;
+ persistent: boolean;
+ preload: boolean;
+ closeOnClick: boolean;
+ hideCloseButton: boolean;
+ dialogBackgroundColor: string;
+ dialogTitleColor: string;
+ overflowX: string;
+ overflowY: string;
+ setId: string;
+ setValue: string;
+ dialogName: string;
+ externalDialog: boolean;
+ autoclose: number | string | boolean;
+ text: string;
+};
+
+export interface JQuiButtonState extends VisRxWidgetState {
+ width: number;
+ height: number;
+ dialogVisible: boolean;
+ showPassword: boolean;
+ password: string;
+ passwordError: boolean;
+}
+
+class JQuiButton<
+ P extends JQuiButtonDataProps = JQuiButtonDataProps,
+ S extends JQuiButtonState = JQuiButtonState,
+> extends VisRxWidget {
+ refButton: React.RefObject;
+
+ refDialog: React.RefObject;
+
+ hideTimeout: ReturnType;
+
+ setObjectType: string;
+
+ constructor(props: VisBaseWidgetProps) {
+ super(props);
+ (this.state as JQuiButtonState).width = 0;
+ (this.state as JQuiButtonState).height = 0;
+ (this.state as JQuiButtonState).dialogVisible = false;
+ (this.state as JQuiButtonState).showPassword = false;
+ (this.state as JQuiButtonState).password = '';
+ this.refButton = React.createRef();
+ this.refDialog = React.createRef();
+ }
+
+ static getWidgetInfo(): RxWidgetInfo {
+ return {
+ id: 'tplJquiButtonLink',
+ visSet: 'jqui',
+ visName: 'Button Link',
+ visSetLabel: 'jqui_set_label',
+ visWidgetLabel: 'jqui_button_link',
+ visPrev: 'widgets/jqui/img/Prev_ButtonLink.png',
+ visOrder: 1,
+ visAttrs: [
+ {
+ name: 'common',
+ fields: [
+ {
+ name: 'buttontext',
+ type: 'text',
+ default: 'URL',
+ hidden: (data: any) =>
+ !!data.html || !!(data.buttontext_view && data.nav_view) || !!data.externalDialog,
+ },
+ {
+ name: 'html',
+ type: 'html',
+ default: '',
+ tooltip: 'jqui_html_tooltip',
+ disabled: (data: any) =>
+ !!data.buttontext || !!data.icon || !!data.src || !!data.externalDialog,
+ },
+ {
+ name: 'Password',
+ type: 'password',
+ label: 'password',
+ tooltip: 'jqui_password_tooltip',
+ disabled: (data: any) =>
+ !data.nav_view && !data.url && !data.href && !data.html_dialog && !data.contains_view,
+ },
+ ],
+ },
+ {
+ name: 'view',
+ label: 'jqui_view_group',
+ hidden: (data: any) => !!data.url || !!data.href || !!data.html_dialog || !!data.contains_view,
+ fields: [
+ {
+ name: 'nav_view',
+ label: 'jqui_nav_view',
+ type: 'views',
+ },
+ {
+ name: 'buttontext_view',
+ label: 'jqui_buttontext_view',
+ type: 'checkbox',
+ hidden: (data: any) => !data.nav_view,
+ },
+ {
+ name: 'sub_view',
+ label: 'basic_sub_view',
+ type: 'text',
+ tooltip: 'sub_view_tooltip',
+ hidden: (data: any) => !data.nav_view,
+ },
+ ],
+ },
+ {
+ name: 'URL',
+ label: 'jqui_url_group',
+ hidden: (data: any) => !!data.html_dialog || !!data.contains_view || !!data.nav_view,
+ fields: [
+ {
+ name: 'href',
+ label: 'jqui_url_in_browser',
+ type: 'url',
+ hidden: (data: any) => !!data.url,
+ tooltip: 'jqui_href_tooltip',
+ },
+ {
+ name: 'url',
+ label: 'jqui_url_in_background',
+ type: 'url',
+ hidden: (data: any) => !!data.href,
+ tooltip: 'jqui_url_tooltip',
+ },
+ {
+ name: 'target',
+ type: 'auto',
+ options: ['_blank', '_self', '_parent', '_top'],
+ hidden: (data: any) => !!data.url || !data.href,
+ },
+ ],
+ },
+ {
+ name: 'style',
+ label: 'Style',
+ hidden: (data: any) => !!data.externalDialog,
+ fields: [
+ { name: 'no_style', type: 'checkbox', hidden: (data: any) => data.jquery_style },
+ {
+ name: 'jquery_style',
+ label: 'jqui_jquery_style',
+ type: 'checkbox',
+ hidden: (data: any) => data.no_style,
+ },
+ {
+ name: 'padding',
+ type: 'slider',
+ min: 0,
+ max: 100,
+ default: 5,
+ // hidden: (data: any) => !data.no_style && !data.jquery_style,
+ },
+ {
+ name: 'variant',
+ label: 'jqui_variant',
+ type: 'select',
+ noTranslation: true,
+ options: ['contained', 'outlined', 'standard'],
+ default: 'contained',
+ hidden: (data: any) => data.jquery_style || data.no_style,
+ },
+ {
+ name: 'color',
+ label: 'jqui_button_color',
+ type: 'select',
+ noTranslation: true,
+ options: ['', 'primary', 'secondary'],
+ default: '',
+ hidden: (data: any) => data.jquery_style || data.no_style,
+ },
+ { name: 'html_prepend', type: 'html' },
+ { name: 'html_append', type: 'html' },
+ {
+ name: 'visResizable', // reserved name for resizable
+ label: 'visResizable',
+ type: 'checkbox',
+ default: false,
+ desiredSize: false, // If sizes should be deleted or set to specific value. `false` - delete sizes, or {width: 100, height: 100}
+ },
+ ],
+ },
+ {
+ name: 'icon',
+ hidden: (data: any) => !!data.externalDialog || data.jquery_style,
+ fields: [
+ {
+ name: 'src',
+ label: 'jqui_image',
+ type: 'image',
+ hidden: (data: any) => data.icon,
+ },
+ {
+ name: 'icon',
+ label: 'jqui_icon',
+ type: 'icon64',
+ hidden: (data: any) => data.src,
+ },
+ {
+ name: 'invert_icon',
+ type: 'checkbox',
+ hidden: (data: any) => !data.icon && !data.src,
+ },
+ {
+ name: 'imageHeight',
+ type: 'slider',
+ min: 0,
+ max: 200,
+ default: 100,
+ hidden: (data: any) => !data.src,
+ },
+ ],
+ },
+ {
+ name: 'dialog',
+ hidden: (data: any) => !!data.url || !!data.href || !!data.nav_view,
+ fields: [
+ {
+ name: 'html_dialog',
+ type: 'html',
+ hidden: (data: any) => !!data.contains_view,
+ },
+ {
+ name: 'contains_view',
+ type: 'views',
+ hidden: (data: any) => !!data.html_dialog,
+ },
+ {
+ name: 'title',
+ type: 'text',
+ hidden: (data: any) => !data.html_dialog && !data.contains_view,
+ },
+ {
+ name: 'autoclose',
+ type: 'slider',
+ min: 0,
+ max: 30000,
+ step: 100,
+ hidden: (data: any) => !data.html_dialog && !data.contains_view,
+ },
+ {
+ name: 'modal',
+ type: 'checkbox',
+ default: true,
+ hidden: (data: any) => !data.html_dialog && !data.contains_view,
+ },
+ {
+ name: 'dialog_width',
+ type: 'text',
+ hidden: (data: any) => !data.html_dialog && !data.contains_view,
+ },
+ {
+ name: 'dialog_height',
+ type: 'text',
+ hidden: (data: any) => !data.html_dialog && !data.contains_view,
+ },
+ {
+ name: 'dialog_class',
+ label: 'CSS Class',
+ type: 'text',
+ hidden: (data: any) => !data.html_dialog && !data.contains_view,
+ },
+ {
+ name: 'persistent',
+ type: 'checkbox',
+ hidden: (data: any) => !data.html_dialog && !data.contains_view,
+ },
+ {
+ name: 'preload',
+ type: 'checkbox',
+ hidden: (data: any) => !data.html_dialog && !data.contains_view,
+ },
+ {
+ name: 'closeOnClick',
+ type: 'checkbox',
+ hidden: (data: any) => !data.html_dialog && !data.contains_view,
+ },
+ {
+ name: 'hideCloseButton',
+ label: 'jqui_hide_close_button',
+ type: 'checkbox',
+ hidden: (data: any) => !data.html_dialog && !data.contains_view && !!data.closeOnClick,
+ },
+ {
+ name: 'dialogBackgroundColor',
+ label: 'Background color',
+ type: 'color',
+ hidden: (data: any) => !data.html_dialog && !data.contains_view,
+ },
+ {
+ name: 'dialogTitleColor',
+ type: 'color',
+ label: 'Text color',
+ hidden: (data: any) => !data.html_dialog && !data.contains_view,
+ },
+ /*
+ {
+ name: 'dialog_top',
+ type: 'text',
+ hidden: (data: any) => !data.html_dialog && !data.contains_view,
+ },
+ {
+ name: 'dialog_left',
+ type: 'text',
+ hidden: (data: any) => !data.html_dialog && !data.contains_view,
+ },
+ */
+ {
+ name: 'overflowX',
+ type: 'select',
+ noTranslation: true,
+ options: ['', 'auto', 'hidden', 'visible', 'scroll', 'initial', 'inherit'],
+ hidden: (data: any) => !data.html_dialog && !data.contains_view,
+ },
+ {
+ name: 'overflowY',
+ type: 'select',
+ noTranslation: true,
+ options: ['', 'auto', 'hidden', 'visible', 'scroll', 'initial', 'inherit'],
+ hidden: (data: any) => !data.html_dialog && !data.contains_view,
+ },
+ {
+ name: 'setId',
+ type: 'id',
+ tooltip: 'jqui_dialog_set_id_tooltip',
+ hidden: (data: any) => !data.html_dialog && !data.contains_view,
+ },
+ {
+ name: 'setValue',
+ type: 'text',
+ hidden: (data: any) => !data.setId || (!data.html_dialog && !data.contains_view),
+ },
+ {
+ name: 'dialogName',
+ label: 'jqui_dialog_name',
+ type: 'text',
+ hidden: (data: any) => !data.html_dialog && !data.contains_view,
+ },
+ {
+ name: 'externalDialog',
+ label: 'jqui_external_dialog',
+ tooltip: 'jqui_external_dialog_tooltip',
+ type: 'checkbox',
+ hidden: (data: any) => !data.html_dialog && !data.contains_view,
+ },
+ ],
+ },
+ ],
+ } as const;
+ }
+
+ static findField(
+ widgetInfo: RxWidgetInfo | RxWidgetInfoWriteable,
+ name: string,
+ ): Writeable | null {
+ return VisRxWidget.findField(widgetInfo as RxWidgetInfo, name) as unknown as Writeable;
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ getWidgetInfo(): RxWidgetInfo {
+ return JQuiButton.getWidgetInfo();
+ }
+
+ async componentDidMount() {
+ super.componentDidMount();
+ await this.componentDidUpdate();
+ }
+
+ async componentWillUnmount() {
+ this.hideTimeout && clearTimeout(this.hideTimeout);
+ this.hideTimeout = null;
+ super.componentWillUnmount();
+ }
+
+ async componentDidUpdate() {
+ if (this.refButton.current) {
+ if (this.state.rxData.jquery_style && !(this.refButton.current as any)._jQueryDone) {
+ (this.refButton.current as any)._jQueryDone = true;
+ (window.jQuery as any)(this.refButton.current).button();
+ }
+ if (
+ this.refButton.current.clientWidth !== this.state.width ||
+ this.refButton.current.clientHeight !== this.state.height
+ ) {
+ this.setState({
+ width: this.refButton.current.clientWidth,
+ height: this.refButton.current.clientHeight,
+ });
+ }
+ }
+ // from base class
+ if (
+ this.refService.current &&
+ (this.state.rxData.html_dialog || this.state.rxData.contains_view) &&
+ !(this.refService.current as any)._showDialog
+ ) {
+ (this.refService.current as any)._showDialog = this.showDialog;
+ }
+ if (this.refService.current) {
+ const dialogName = this.refService.current.dataset.dialogName;
+ if ((dialogName || '') !== (this.state.rxData.dialogName || '')) {
+ if (!this.state.rxData.dialogName) {
+ delete this.refService.current.dataset.dialogName;
+ } else {
+ this.refService.current.dataset.dialogName = this.state.rxData.dialogName;
+ }
+ }
+ }
+ }
+
+ showDialog = (show: boolean) => {
+ this.setState({ dialogVisible: show });
+
+ // Auto-close
+ let timeout = this.state.rxData.autoclose;
+ if (timeout === true || timeout === 'true') {
+ timeout = 10000;
+ }
+ if (timeout === null || timeout === undefined || timeout === '') {
+ return;
+ }
+ timeout = parseInt(timeout as string, 10);
+ if (timeout < 60) {
+ // maybe this is seconds
+ timeout *= 1000;
+ }
+ timeout = timeout || 1000;
+
+ if (timeout) {
+ if (show) {
+ this.hideTimeout = setTimeout(() => {
+ this.hideTimeout = null;
+ this.showDialog(false);
+ }, timeout);
+ } else if (this.hideTimeout) {
+ clearTimeout(this.hideTimeout);
+ this.hideTimeout = null;
+ }
+ }
+ };
+
+ onPasswordEnter() {
+ if (this.state.password === this.state.rxData.Password) {
+ this.setState({ showPassword: false }, () => this.onClick(true));
+ } else {
+ window.alert(I18n.t('Wrong password'));
+ this.setState({ passwordError: true }, () => {
+ setTimeout(() => this.setState({ passwordError: false }), 3000);
+ });
+ }
+ }
+
+ renderPasswordDialog() {
+ if (!this.state.showPassword) {
+ return null;
+ }
+ return (
+
+ );
+ }
+
+ async setObjectWithState(oid: string, value: ioBroker.State['val']) {
+ if (this.setObjectType === undefined) {
+ try {
+ const obj = await this.props.context.socket.getObject(oid);
+ this.setObjectType = obj?.common?.type || 'string';
+ await this.setObjectWithState(oid, value);
+ } catch (error) {
+ console.warn(`Object ${oid} not found: ${error}`);
+ }
+ return;
+ }
+ if (this.setObjectType === 'boolean') {
+ value =
+ value === 'true' || value === true || value === '1' || value === 1 || value === 'on' || value === 'ON';
+ } else if (this.setObjectType === 'number') {
+ value = parseFloat(value as string);
+ } else if (value !== null && value !== undefined) {
+ value = value.toString();
+ }
+
+ await this.props.context.setValue(oid, value);
+ }
+
+ onCommand(command: VisWidgetCommand) {
+ super.onCommand(command);
+ if (command === 'openDialog') {
+ this.showDialog(true);
+ return true;
+ }
+ if (command === 'closeDialog') {
+ this.showDialog(false);
+ return true;
+ }
+ return false;
+ }
+
+ onClick(passwordChecked?: boolean) {
+ if (this.state.dialogVisible) {
+ return;
+ }
+
+ if (!passwordChecked && this.state.rxData.Password) {
+ if (this.props.editMode) {
+ window.alert(I18n.t('Ignored in edit mode'));
+ } else {
+ this.setState({ showPassword: true, password: '' });
+ }
+ return;
+ }
+
+ if (this.state.rxData.nav_view) {
+ this.props.context.changeView(this.state.rxData.nav_view);
+ } else if (!this.props.editMode && this.state.rxData.href) {
+ if (
+ this.state.rxData.target ||
+ (this.props.tpl === 'tplJquiButtonLinkBlank' && this.state.rxData.target === undefined)
+ ) {
+ window.open(this.state.rxData.href, this.state.rxData.target);
+ } else {
+ window.location.href = this.state.rxData.href;
+ }
+ } else if (this.state.rxData.url) {
+ this.props.context.socket
+ .getRawSocket()
+ .emit('httpGet', this.state.rxData.url, (data: any) =>
+ console.log('httpGet', this.state.rxData.url, data),
+ );
+ }
+
+ if (this.state.rxData.html_dialog || this.state.rxData.contains_view) {
+ if (this.state.rxData.setId) {
+ this.setObjectWithState(this.state.rxData.setId, this.state.rxData.setValue).catch(error =>
+ console.warn(`Cannot set state: ${error}`),
+ );
+ }
+ // show dialog
+ this.showDialog(true);
+ }
+ }
+
+ renderRxDialog(dialogStyle: CSSProperties, content: React.JSX.Element) {
+ console.log('test');
+ if (this.state.rxData.modal) {
+ console.log('in');
+ return (
+
+ );
+ }
+
+ if (!this.state.dialogVisible) {
+ dialogStyle.display = 'none';
+ }
+
+ if (!dialogStyle.minWidth || (dialogStyle.minWidth as number) < 200) {
+ dialogStyle.minWidth = 200;
+ }
+ if (!dialogStyle.minHeight || (dialogStyle.minHeight as number) < 100) {
+ dialogStyle.minHeight = 100;
+ }
+
+ dialogStyle.backgroundColor = 'blue';
+ const paperStyle = { ...dialogStyle };
+ delete paperStyle.top;
+ delete paperStyle.left;
+ paperStyle.padding = this.state.rxData.title ? '0 24px 24px 24px' : '26px 24px 24px 24px';
+
+ return (
+ {
+ if (this.state.rxData.closeOnClick) {
+ this.showDialog(false);
+ }
+ }}
+ >
+
+ {this.state.rxData.title ? (
+
+ {this.state.rxData.title}
+
+ ) : null}
+ this.showDialog(false)}
+ >
+
+
+ {content}
+
+
+ );
+ }
+
+ renderJQueryDialog(dialogStyle: CSSProperties, content: React.JSX.Element) {
+ return (
+
+ {this.state.rxData.preload ? content : null}
+
+ );
+ }
+
+ renderDialog() {
+ if (
+ this.props.editMode ||
+ (!this.state.dialogVisible && !this.state.rxData.persistent && !this.state.rxData.externalDialog) ||
+ (!this.state.rxData.html_dialog && !this.state.rxData.contains_view)
+ ) {
+ return null;
+ }
+
+ // eslint-disable-next-line no-restricted-properties
+ // const top = isVarFinite(this.state.rxData.dialog_top) ? parseFloat(this.state.rxData.dialog_top) : this.state.rxData.dialog_top;
+ // eslint-disable-next-line no-restricted-properties
+ // const left = isVarFinite(this.state.rxData.dialog_left) ? parseFloat(this.state.rxData.dialog_left) : this.state.rxData.dialog_left;
+ // eslint-disable-next-line no-restricted-properties
+ const width = isVarFinite(this.state.rxData.dialog_width)
+ ? parseFloat(this.state.rxData.dialog_width)
+ : this.state.rxData.dialog_width;
+ // eslint-disable-next-line no-restricted-properties
+ const height = isVarFinite(this.state.rxData.dialog_height)
+ ? parseFloat(this.state.rxData.dialog_height)
+ : this.state.rxData.dialog_height;
+
+ const dialogStyle: CSSProperties = {
+ minWidth: width || window.innerWidth - 50,
+ minHeight: height || window.innerHeight - 50,
+ // top: top || top === 0 ? top : undefined,
+ // left: left || left === 0 ? left : undefined,
+ overflowX: this.state.rxData.overflowX as any,
+ overflowY: this.state.rxData.overflowY as any,
+ };
+
+ let content;
+ if (this.state.rxData.contains_view) {
+ content = (
+
+ {super.getWidgetView(this.state.rxData.contains_view, undefined)}
+
+ );
+ } else {
+ content = (
+
+ );
+ }
+
+ if (this.state.rxData.jquery_style) {
+ // return this.renderJQueryDialog(dialogStyle, content);
+ }
+
+ return this.renderRxDialog(dialogStyle, content);
+ }
+
+ renderWidgetBody(props: RxRenderWidgetProps) {
+ super.renderWidgetBody(props);
+
+ const iconStyle: CSSProperties = {
+ marginRight: 4,
+ filter: this.state.rxData.invert_icon ? 'invert(1)' : undefined,
+ };
+
+ if (!this.state.rxData.jquery_style && this.state.rxData.src) {
+ if (this.state.width > this.state.height) {
+ iconStyle.height = `${this.state.rxData.imageHeight || 100}%`;
+ iconStyle.width = 'auto';
+ } else {
+ iconStyle.width = `${this.state.rxData.imageHeight || 100}%`;
+ iconStyle.height = 'auto';
+ }
+ }
+ let iconSrc = !this.state.rxData.jquery_style && (this.state.rxData.src || this.state.rxData.icon);
+
+ if (iconSrc && iconSrc.startsWith('_PRJ_NAME/')) {
+ iconSrc = iconSrc.replace(
+ '_PRJ_NAME/',
+ `../${this.props.context.adapterName}.${this.props.context.instance}/${this.props.context.projectName}/`,
+ );
+ }
+ const icon = iconSrc ? (
+
+ ) : null;
+
+ const buttonStyle: CSSProperties = { textTransform: 'none' };
+ // apply style from the element
+ Object.keys(this.state.rxStyle).forEach(attr => {
+ const value = (this.state.rxStyle as any)[attr];
+ if (value !== null && value !== undefined && VisRxWidget.POSSIBLE_MUI_STYLES.includes(attr)) {
+ attr = attr.replace(/(-\w)/g, text => text[1].toUpperCase());
+ (buttonStyle as any)[attr] = value;
+ }
+ });
+ if (buttonStyle.borderWidth) {
+ buttonStyle.borderWidth = VisBaseWidget.correctStylePxValue(buttonStyle.borderWidth);
+ }
+ if (buttonStyle.fontSize) {
+ buttonStyle.fontSize = VisBaseWidget.correctStylePxValue(buttonStyle.fontSize);
+ }
+
+ // the following widgets are resizable by default
+ let visResizable = this.state.data.visResizable;
+ if (visResizable === undefined || visResizable === null) {
+ if (
+ this.props.tpl === 'tplJquiButtonNav' ||
+ this.props.tpl === 'tplJquiNavPw' ||
+ this.props.tpl === 'tplContainerDialog' ||
+ this.props.tpl === 'tplContainerIconDialog' ||
+ this.props.tpl === 'tplJquiDialog' ||
+ this.props.tpl === 'tplJquiIconDialog' ||
+ this.props.tpl === 'tplIconHttpGet' ||
+ this.props.tpl === 'tplIconLink' ||
+ this.props.tpl === 'tplJquiIconNav'
+ ) {
+ visResizable = true;
+ }
+ }
+
+ // extra no rxData here, as it is not possible to set it with bindings
+ if (visResizable) {
+ buttonStyle.width = '100%';
+ buttonStyle.height = '100%';
+ } else {
+ buttonStyle.padding = this.state.rxData.padding;
+ }
+ buttonStyle.minWidth = 'unset';
+
+ let buttonText;
+ if (this.state.rxData.html) {
+ // ignore
+ } else if (this.state.rxData.nav_view && this.state.rxData.buttontext_view) {
+ buttonText =
+ this.props.context.views[this.state.rxData.nav_view]?.settings?.navigationTitle ||
+ this.state.rxData.nav_view;
+ } else if (this.state.rxData.buttontext === undefined) {
+ buttonText = this.state.rxData.text || ''; // back compatibility
+ } else {
+ buttonText = this.state.rxData.buttontext;
+ }
+
+ let content;
+ if (this.state.rxData.externalDialog) {
+ content = this.props.editMode ? (
+
+
{
+ e.stopPropagation();
+ e.preventDefault();
+ const text = `setState('${this.props.context.adapterName}.${this.props.context.instance}.control.command', '${JSON.stringify({ command: 'dialog', instance: window.localStorage.getItem('visInstance'), data: this.state.rxData.dialogName || this.props.id })}')`;
+ window.alert(I18n.t('Copied %s', text));
+ Utils.copyToClipboard(text);
+ }}
+ >
+
+
+
{I18n.t('External dialog')}
+
{this.state.rxData.html_dialog ? 'HTML' : `View: ${this.state.rxData.contains_view}`}
+
{`Name: ${this.state.rxData.dialogName ? `${this.state.rxData.dialogName} (${this.props.id})` : this.props.id}`}
+
{I18n.t('You can open dialog with following script:')}
+
{`setState('${this.props.context.adapterName}.${this.props.context.instance}.control.command', '${JSON.stringify({ command: 'dialog', instance: window.localStorage.getItem('visInstance'), data: this.state.rxData.dialogName || this.props.id })}')`}
+
+ ) : null;
+ } else {
+ content = [
+ this.state.rxData.html_prepend ? (
+
+ ) : null,
+ this.state.rxData.html ? (
+
+ ) : this.state.rxData.no_style || this.state.rxData.jquery_style ? (
+
+ ) : (
+
+ ),
+ this.state.rxData.html_append ? (
+
+ ) : null,
+ ];
+ }
+
+ return (
+ this.onClick() : undefined}
+ >
+ {content}
+ {this.renderDialog()}
+ {this.renderPasswordDialog()}
+
+ );
+ }
+}
+
+export default JQuiButton;
diff --git a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiButtonBlank.tsx b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiButtonBlank.tsx
index bce4ff34..8a330a7e 100644
--- a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiButtonBlank.tsx
+++ b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiButtonBlank.tsx
@@ -1,62 +1,62 @@
-/**
- * ioBroker.vis-2
- * https://github.com/ioBroker/ioBroker.vis-2
- *
- * Copyright (c) 2023-2024 Denis Haev https://github.com/GermanBluefox,
- * Creative Common Attribution-NonCommercial (CC BY-NC)
- *
- * http://creativecommons.org/licenses/by-nc/4.0/
- *
- * Short content:
- * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
- * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
- * (Free for non-commercial use).
- */
-
-import type {
- RxWidgetInfo,
- RxWidgetInfoAttributesFieldCheckbox,
- RxWidgetInfoAttributesFieldSelect,
- RxWidgetInfoAttributesFieldText,
- RxWidgetInfoWriteable,
-} from '@iobroker/types-vis-2';
-import JQuiButton from './JQuiButton';
-
-class JQuiButtonBlank extends JQuiButton {
- static getWidgetInfo(): RxWidgetInfo {
- const widgetInfo = JQuiButton.getWidgetInfo() as unknown as RxWidgetInfoWriteable;
- const newWidgetInfo = {
- id: 'tplJquiButtonLinkBlank',
- visSet: 'jqui',
- visName: 'Button Link',
- visWidgetLabel: 'jqui_button_link_blank',
- visPrev: 'widgets/jqui/img/Prev_ButtonLinkBlank.png',
- visOrder: 2,
- visAttrs: widgetInfo.visAttrs,
- };
-
- // Add note
- newWidgetInfo.visAttrs[0].fields.unshift({
- name: '_note',
- type: 'help',
- text: 'jqui_button_link_blank_note',
- });
- const target = JQuiButton.findField(newWidgetInfo, 'target');
- target.default = '_blank';
-
- const visResizable = JQuiButton.findField(newWidgetInfo, 'visResizable');
- visResizable.default = false;
-
- const text = JQuiButton.findField(newWidgetInfo, 'buttontext');
- text.default = 'URL Browser';
-
- return newWidgetInfo as RxWidgetInfo;
- }
-
- // eslint-disable-next-line class-methods-use-this
- getWidgetInfo(): RxWidgetInfo {
- return JQuiButtonBlank.getWidgetInfo();
- }
-}
-
-export default JQuiButtonBlank;
+/**
+ * ioBroker.vis-2
+ * https://github.com/ioBroker/ioBroker.vis-2
+ *
+ * Copyright (c) 2023-2025 Denis Haev https://github.com/GermanBluefox,
+ * Creative Common Attribution-NonCommercial (CC BY-NC)
+ *
+ * http://creativecommons.org/licenses/by-nc/4.0/
+ *
+ * Short content:
+ * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
+ * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
+ * (Free for non-commercial use).
+ */
+
+import type {
+ RxWidgetInfo,
+ RxWidgetInfoAttributesFieldCheckbox,
+ RxWidgetInfoAttributesFieldSelect,
+ RxWidgetInfoAttributesFieldText,
+ RxWidgetInfoWriteable,
+} from '@iobroker/types-vis-2';
+import JQuiButton from './JQuiButton';
+
+class JQuiButtonBlank extends JQuiButton {
+ static getWidgetInfo(): RxWidgetInfo {
+ const widgetInfo = JQuiButton.getWidgetInfo() as unknown as RxWidgetInfoWriteable;
+ const newWidgetInfo = {
+ id: 'tplJquiButtonLinkBlank',
+ visSet: 'jqui',
+ visName: 'Button Link',
+ visWidgetLabel: 'jqui_button_link_blank',
+ visPrev: 'widgets/jqui/img/Prev_ButtonLinkBlank.png',
+ visOrder: 2,
+ visAttrs: widgetInfo.visAttrs,
+ };
+
+ // Add note
+ newWidgetInfo.visAttrs[0].fields.unshift({
+ name: '_note',
+ type: 'help',
+ text: 'jqui_button_link_blank_note',
+ });
+ const target = JQuiButton.findField(newWidgetInfo, 'target');
+ target.default = '_blank';
+
+ const visResizable = JQuiButton.findField(newWidgetInfo, 'visResizable');
+ visResizable.default = false;
+
+ const text = JQuiButton.findField(newWidgetInfo, 'buttontext');
+ text.default = 'URL Browser';
+
+ return newWidgetInfo as RxWidgetInfo;
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ getWidgetInfo(): RxWidgetInfo {
+ return JQuiButtonBlank.getWidgetInfo();
+ }
+}
+
+export default JQuiButtonBlank;
diff --git a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiButtonDialogClose.tsx b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiButtonDialogClose.tsx
index a12019e4..8e72f237 100644
--- a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiButtonDialogClose.tsx
+++ b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiButtonDialogClose.tsx
@@ -1,428 +1,428 @@
-/**
- * ioBroker.vis-2
- * https://github.com/ioBroker/ioBroker.vis-2
- *
- * Copyright (c) 2023-2024 Denis Haev https://github.com/GermanBluefox,
- * Creative Common Attribution-NonCommercial (CC BY-NC)
- *
- * http://creativecommons.org/licenses/by-nc/4.0/
- *
- * Short content:
- * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
- * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
- * (Free for non-commercial use).
- */
-
-import React, { type CSSProperties } from 'react';
-
-import { Autocomplete, Button, Fab, TextField } from '@mui/material';
-
-import { I18n, Icon } from '@iobroker/adapter-react-v5';
-
-import VisBaseWidget, { type WidgetStyleState } from '@/Vis/visBaseWidget';
-import type {
- AnyWidgetId,
- RxRenderWidgetProps,
- RxWidgetInfoAttributesField,
- RxWidgetInfoCustomComponentProperties,
- ViewCommand,
- WidgetData,
- VisBaseWidgetProps,
- RxWidgetInfo,
-} from '@iobroker/types-vis-2';
-import VisRxWidget, { type VisRxWidgetState } from '../../visRxWidget';
-
-// eslint-disable-next-line no-use-before-define
-type RxData = {
- dlgName: string;
- buttontext: string;
- html: string;
- no_style: boolean;
- jquery_style: boolean;
- padding: number;
- variant: 'contained' | 'outlined' | 'standard';
- color: '' | 'primary' | 'secondary';
- html_prepend: string;
- html_append: string;
- visResizable: boolean;
- src: string;
- icon: string;
- invert_icon: boolean;
- imageHeight: number;
-};
-
-interface JQuiButtonDialogCloseState extends VisRxWidgetState {
- width: number;
- height: number;
-}
-
-class JQuiButtonDialogClose extends VisRxWidget {
- constructor(props: VisBaseWidgetProps) {
- super(props);
- (this.state as JQuiButtonDialogCloseState).width = 0;
- (this.state as JQuiButtonDialogCloseState).height = 0;
- }
-
- static getWidgetInfo(): RxWidgetInfo {
- return {
- id: 'tplJquiButtonDialogClose',
- visSet: 'jqui',
- visName: 'Button dialog close',
- visWidgetLabel: 'jqui_button_dialog_close',
- visPrev: 'widgets/jqui/img/Prev_ButtonDialogClose.png',
- visOrder: 13,
- visAttrs: [
- {
- name: 'common',
- fields: [
- {
- label: 'jqui_dialog_name',
- tooltip: 'jqui_dialog_name_tooltip',
- type: 'custom',
- component: (
- field: RxWidgetInfoAttributesField,
- data: WidgetData,
- onDataChange: (newData: WidgetData) => void,
- options: RxWidgetInfoCustomComponentProperties,
- ): React.JSX.Element | React.JSX.Element[] => {
- // find all possible dialogs
- const names: { label: string; value: string }[] = [];
- Object.keys(options.context.views).forEach(id => {
- const widgets = options.context.views[id].widgets;
- widgets &&
- Object.keys(widgets).forEach((widget: AnyWidgetId) => {
- if (
- widgets[widget].data?.html_dialog ||
- widgets[widget].data?.contains_view ||
- widgets[widget].data?.externalDialog
- ) {
- if (widgets[widget].data.dialogName) {
- names.push({
- label: `${widgets[widget].data.dialogName} (${widget})`,
- value: widgets[widget].data.dialogName,
- });
- } else {
- names.push({ label: widget, value: widget });
- }
- }
- });
- });
- return (
-
- freeSolo
- options={names}
- // variant="standard"
- value={data.dlgName || ''}
- sx={{ width: '100%' }}
- onInputChange={(e, inputValue) => {
- if (typeof inputValue === 'object' && inputValue !== null) {
- inputValue = (inputValue as { label: string; value: string }).value;
- }
- onDataChange({ dlgName: inputValue });
- }}
- onChange={(e, inputValue) => {
- if (typeof inputValue === 'object' && inputValue !== null) {
- inputValue = inputValue.value;
- }
- onDataChange({ dlgName: inputValue });
- }}
- getOptionLabel={option => {
- if (typeof option === 'string') {
- return option;
- }
- return option.label;
- }}
- renderInput={params => (
-
- )}
- />
- );
- },
- },
- {
- name: 'buttontext',
- type: 'text',
- default: I18n.t('jqui_Close').replace('jqui_', ''),
- hidden: (data: any) => !!data.html,
- },
- {
- name: 'html',
- type: 'html',
- default: '',
- tooltip: 'jqui_html_tooltip',
- disabled: (data: any) => !!data.buttontext || !!data.icon || !!data.src,
- },
- ],
- },
- {
- name: 'style',
- hidden: (data: any) => !!data.externalDialog,
- fields: [
- { name: 'no_style', type: 'checkbox', hidden: (data: any) => data.jquery_style },
- {
- name: 'jquery_style',
- label: 'jqui_jquery_style',
- type: 'checkbox',
- hidden: (data: any) => data.no_style,
- },
- {
- name: 'padding',
- type: 'slider',
- min: 0,
- max: 100,
- default: 5,
- // hidden: (data: any) => !data.no_style && !data.jquery_style,
- },
- {
- name: 'variant',
- label: 'jqui_variant',
- type: 'select',
- noTranslation: true,
- options: ['contained', 'outlined', 'standard'],
- default: 'contained',
- hidden: (data: any) => data.jquery_style || data.no_style,
- },
- {
- name: 'color',
- label: 'jqui_button_color',
- type: 'select',
- noTranslation: true,
- options: ['', 'primary', 'secondary'],
- default: '',
- hidden: (data: any) => data.jquery_style || data.no_style,
- },
- { name: 'html_prepend', type: 'html' },
- { name: 'html_append', type: 'html' },
- {
- name: 'visResizable', // reserved name for resizable
- label: 'visResizable',
- type: 'checkbox',
- default: false,
- desiredSize: false, // If sizes should be deleted or set to specific value. `false` - delete sizes, or {width: 100, height: 100}
- },
- ],
- },
- {
- name: 'icon',
- hidden: (data: any) => !!data.html,
- fields: [
- {
- name: 'src',
- label: 'jqui_image',
- type: 'image',
- hidden: (data: any) => data.icon || data.jquery_style,
- },
- {
- name: 'icon',
- label: 'jqui_icon',
- type: 'icon64',
- default:
- 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBmaWxsPSJjdXJyZW50Q29sb3IiIGQ9Ik0xOSA2LjQxTDE3LjU5IDVMMTIgMTAuNTlMNi40MSA1TDUgNi40MUwxMC41OSAxMkw1IDE3LjU5TDYuNDEgMTlMMTIgMTMuNDFMMTcuNTkgMTlMMTkgMTcuNTlMMTMuNDEgMTJ6Ii8+PC9zdmc+',
- hidden: (data: any) => data.src || data.jquery_style,
- },
- {
- name: 'invert_icon',
- type: 'checkbox',
- hidden: (data: any) => (!data.icon || !data.image) && data.jquery_style,
- },
- {
- name: 'imageHeight',
- type: 'slider',
- min: 0,
- max: 200,
- default: 100,
- hidden: (data: any) => !data.src || data.jquery_style,
- },
- ],
- },
- ],
- } as const;
- }
-
- // eslint-disable-next-line class-methods-use-this
- getWidgetInfo(): RxWidgetInfo {
- return JQuiButtonDialogClose.getWidgetInfo();
- }
-
- onClick(): void {
- let dlgName: AnyWidgetId = this.state.rxData.dlgName as AnyWidgetId;
- if (!dlgName) {
- // go through all widgets and find the one with dialog content as this view
- const views = Object.keys(this.props.context.views);
- for (let i = 0; i < views.length; i++) {
- const widgets = this.props.context.views[views[i]].widgets;
- if (widgets) {
- const wids: AnyWidgetId[] = Object.keys(widgets) as AnyWidgetId[];
- for (let j = 0; j < wids.length; j++) {
- if (widgets[wids[j]].data?.contains_view === this.props.view) {
- dlgName = wids[j];
- break;
- }
- }
- }
- if (dlgName) {
- break;
- }
- }
- }
- if (dlgName) {
- const el =
- window.document.getElementById(dlgName) ||
- window.document.querySelector(`[data-dialog-name="${dlgName}"]`);
-
- const viewName = Object.keys(this.props.context.views).find(
- view => this.props.context.views[view].widgets[dlgName],
- );
- this.props.context.onCommand(
- 'closeDialog',
- viewName as ViewCommand,
- dlgName as unknown as Record,
- );
-
- if ((el as any)?._showDialog) {
- (el as any)._showDialog(false);
- } else {
- // noinspection JSJQueryEfficiency
- (window.jQuery as any)(`#${dlgName}_dialog`).dialog('close');
- }
- } else {
- window.alert('Dialog not found');
- }
- }
-
- renderWidgetBody(props: RxRenderWidgetProps): React.JSX.Element {
- super.renderWidgetBody(props);
-
- const iconStyle: CSSProperties = {
- filter: this.state.rxData.invert_icon ? 'invert(1)' : undefined,
- };
-
- if (!this.state.rxData.jquery_style && this.state.rxData.src) {
- if (this.state.width > this.state.height) {
- iconStyle.height = `${this.state.rxData.imageHeight || 100}%`;
- iconStyle.width = 'auto';
- } else {
- iconStyle.width = `${this.state.rxData.imageHeight || 100}%`;
- iconStyle.height = 'auto';
- }
- }
- let iconSrc = !this.state.rxData.jquery_style && (this.state.rxData.src || this.state.rxData.icon);
-
- if (iconSrc && iconSrc.startsWith('_PRJ_NAME/')) {
- iconSrc = iconSrc.replace(
- '_PRJ_NAME/',
- `../${this.props.context.adapterName}.${this.props.context.instance}/${this.props.context.projectName}/`,
- );
- }
-
- const icon = iconSrc ? (
-
- ) : null;
-
- const buttonStyle: CSSProperties = {};
- // apply style from the element
- Object.keys(this.state.rxStyle).forEach((attr: keyof WidgetStyleState) => {
- const value = this.state.rxStyle[attr];
- if (value !== null && value !== undefined && VisRxWidget.POSSIBLE_MUI_STYLES.includes(attr)) {
- (attr as string) = attr.replace(/(-\w)/g, text => text[1].toUpperCase());
- (buttonStyle as any)[attr] = value;
- }
- });
- buttonStyle.minWidth = 'unset';
- if (buttonStyle.borderWidth) {
- buttonStyle.borderWidth = VisBaseWidget.correctStylePxValue(buttonStyle.borderWidth);
- }
- if (buttonStyle.fontSize) {
- buttonStyle.fontSize = VisBaseWidget.correctStylePxValue(buttonStyle.fontSize);
- }
-
- // extra no rxData here, as it is not possible to set it with bindings
- if (this.state.data.visResizable) {
- buttonStyle.width = '100%';
- buttonStyle.height = '100%';
- } else {
- buttonStyle.padding = this.state.rxData.padding;
- }
-
- let buttonText;
- if (this.state.rxData.html) {
- // ignore
- } else {
- buttonText = this.state.rxData.buttontext;
- }
-
- const content = [
- this.state.rxData.html_prepend ? (
-
- ) : null,
- this.state.rxData.html ? (
-
- ) : this.state.rxData.no_style || this.state.rxData.jquery_style ? (
-
- ) : !buttonText ? (
- this.onClick()}
- size="small"
- >
- {icon}
-
- ) : (
-
- ),
- this.state.rxData.html_append ? (
-
- ) : null,
- ];
-
- return (
- this.onClick() : undefined}
- >
- {content}
-
- );
- }
-}
-
-export default JQuiButtonDialogClose;
+/**
+ * ioBroker.vis-2
+ * https://github.com/ioBroker/ioBroker.vis-2
+ *
+ * Copyright (c) 2023-2025 Denis Haev https://github.com/GermanBluefox,
+ * Creative Common Attribution-NonCommercial (CC BY-NC)
+ *
+ * http://creativecommons.org/licenses/by-nc/4.0/
+ *
+ * Short content:
+ * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
+ * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
+ * (Free for non-commercial use).
+ */
+
+import React, { type CSSProperties } from 'react';
+
+import { Autocomplete, Button, Fab, TextField } from '@mui/material';
+
+import { I18n, Icon } from '@iobroker/adapter-react-v5';
+
+import VisBaseWidget, { type WidgetStyleState } from '@/Vis/visBaseWidget';
+import type {
+ AnyWidgetId,
+ RxRenderWidgetProps,
+ RxWidgetInfoAttributesField,
+ RxWidgetInfoCustomComponentProperties,
+ ViewCommand,
+ WidgetData,
+ VisBaseWidgetProps,
+ RxWidgetInfo,
+} from '@iobroker/types-vis-2';
+import VisRxWidget, { type VisRxWidgetState } from '../../visRxWidget';
+
+// eslint-disable-next-line no-use-before-define
+type RxData = {
+ dlgName: string;
+ buttontext: string;
+ html: string;
+ no_style: boolean;
+ jquery_style: boolean;
+ padding: number;
+ variant: 'contained' | 'outlined' | 'standard';
+ color: '' | 'primary' | 'secondary';
+ html_prepend: string;
+ html_append: string;
+ visResizable: boolean;
+ src: string;
+ icon: string;
+ invert_icon: boolean;
+ imageHeight: number;
+};
+
+interface JQuiButtonDialogCloseState extends VisRxWidgetState {
+ width: number;
+ height: number;
+}
+
+class JQuiButtonDialogClose extends VisRxWidget {
+ constructor(props: VisBaseWidgetProps) {
+ super(props);
+ (this.state as JQuiButtonDialogCloseState).width = 0;
+ (this.state as JQuiButtonDialogCloseState).height = 0;
+ }
+
+ static getWidgetInfo(): RxWidgetInfo {
+ return {
+ id: 'tplJquiButtonDialogClose',
+ visSet: 'jqui',
+ visName: 'Button dialog close',
+ visWidgetLabel: 'jqui_button_dialog_close',
+ visPrev: 'widgets/jqui/img/Prev_ButtonDialogClose.png',
+ visOrder: 13,
+ visAttrs: [
+ {
+ name: 'common',
+ fields: [
+ {
+ label: 'jqui_dialog_name',
+ tooltip: 'jqui_dialog_name_tooltip',
+ type: 'custom',
+ component: (
+ field: RxWidgetInfoAttributesField,
+ data: WidgetData,
+ onDataChange: (newData: WidgetData) => void,
+ options: RxWidgetInfoCustomComponentProperties,
+ ): React.JSX.Element | React.JSX.Element[] => {
+ // find all possible dialogs
+ const names: { label: string; value: string }[] = [];
+ Object.keys(options.context.views).forEach(id => {
+ const widgets = options.context.views[id].widgets;
+ widgets &&
+ Object.keys(widgets).forEach((widget: AnyWidgetId) => {
+ if (
+ widgets[widget].data?.html_dialog ||
+ widgets[widget].data?.contains_view ||
+ widgets[widget].data?.externalDialog
+ ) {
+ if (widgets[widget].data.dialogName) {
+ names.push({
+ label: `${widgets[widget].data.dialogName} (${widget})`,
+ value: widgets[widget].data.dialogName,
+ });
+ } else {
+ names.push({ label: widget, value: widget });
+ }
+ }
+ });
+ });
+ return (
+
+ freeSolo
+ options={names}
+ // variant="standard"
+ value={data.dlgName || ''}
+ sx={{ width: '100%' }}
+ onInputChange={(e, inputValue) => {
+ if (typeof inputValue === 'object' && inputValue !== null) {
+ inputValue = (inputValue as { label: string; value: string }).value;
+ }
+ onDataChange({ dlgName: inputValue });
+ }}
+ onChange={(e, inputValue) => {
+ if (typeof inputValue === 'object' && inputValue !== null) {
+ inputValue = inputValue.value;
+ }
+ onDataChange({ dlgName: inputValue });
+ }}
+ getOptionLabel={option => {
+ if (typeof option === 'string') {
+ return option;
+ }
+ return option.label;
+ }}
+ renderInput={params => (
+
+ )}
+ />
+ );
+ },
+ },
+ {
+ name: 'buttontext',
+ type: 'text',
+ default: I18n.t('jqui_Close').replace('jqui_', ''),
+ hidden: (data: any) => !!data.html,
+ },
+ {
+ name: 'html',
+ type: 'html',
+ default: '',
+ tooltip: 'jqui_html_tooltip',
+ disabled: (data: any) => !!data.buttontext || !!data.icon || !!data.src,
+ },
+ ],
+ },
+ {
+ name: 'style',
+ hidden: (data: any) => !!data.externalDialog,
+ fields: [
+ { name: 'no_style', type: 'checkbox', hidden: (data: any) => data.jquery_style },
+ {
+ name: 'jquery_style',
+ label: 'jqui_jquery_style',
+ type: 'checkbox',
+ hidden: (data: any) => data.no_style,
+ },
+ {
+ name: 'padding',
+ type: 'slider',
+ min: 0,
+ max: 100,
+ default: 5,
+ // hidden: (data: any) => !data.no_style && !data.jquery_style,
+ },
+ {
+ name: 'variant',
+ label: 'jqui_variant',
+ type: 'select',
+ noTranslation: true,
+ options: ['contained', 'outlined', 'standard'],
+ default: 'contained',
+ hidden: (data: any) => data.jquery_style || data.no_style,
+ },
+ {
+ name: 'color',
+ label: 'jqui_button_color',
+ type: 'select',
+ noTranslation: true,
+ options: ['', 'primary', 'secondary'],
+ default: '',
+ hidden: (data: any) => data.jquery_style || data.no_style,
+ },
+ { name: 'html_prepend', type: 'html' },
+ { name: 'html_append', type: 'html' },
+ {
+ name: 'visResizable', // reserved name for resizable
+ label: 'visResizable',
+ type: 'checkbox',
+ default: false,
+ desiredSize: false, // If sizes should be deleted or set to specific value. `false` - delete sizes, or {width: 100, height: 100}
+ },
+ ],
+ },
+ {
+ name: 'icon',
+ hidden: (data: any) => !!data.html,
+ fields: [
+ {
+ name: 'src',
+ label: 'jqui_image',
+ type: 'image',
+ hidden: (data: any) => data.icon || data.jquery_style,
+ },
+ {
+ name: 'icon',
+ label: 'jqui_icon',
+ type: 'icon64',
+ default:
+ 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBmaWxsPSJjdXJyZW50Q29sb3IiIGQ9Ik0xOSA2LjQxTDE3LjU5IDVMMTIgMTAuNTlMNi40MSA1TDUgNi40MUwxMC41OSAxMkw1IDE3LjU5TDYuNDEgMTlMMTIgMTMuNDFMMTcuNTkgMTlMMTkgMTcuNTlMMTMuNDEgMTJ6Ii8+PC9zdmc+',
+ hidden: (data: any) => data.src || data.jquery_style,
+ },
+ {
+ name: 'invert_icon',
+ type: 'checkbox',
+ hidden: (data: any) => (!data.icon || !data.image) && data.jquery_style,
+ },
+ {
+ name: 'imageHeight',
+ type: 'slider',
+ min: 0,
+ max: 200,
+ default: 100,
+ hidden: (data: any) => !data.src || data.jquery_style,
+ },
+ ],
+ },
+ ],
+ } as const;
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ getWidgetInfo(): RxWidgetInfo {
+ return JQuiButtonDialogClose.getWidgetInfo();
+ }
+
+ onClick(): void {
+ let dlgName: AnyWidgetId = this.state.rxData.dlgName as AnyWidgetId;
+ if (!dlgName) {
+ // go through all widgets and find the one with dialog content as this view
+ const views = Object.keys(this.props.context.views);
+ for (let i = 0; i < views.length; i++) {
+ const widgets = this.props.context.views[views[i]].widgets;
+ if (widgets) {
+ const wids: AnyWidgetId[] = Object.keys(widgets) as AnyWidgetId[];
+ for (let j = 0; j < wids.length; j++) {
+ if (widgets[wids[j]].data?.contains_view === this.props.view) {
+ dlgName = wids[j];
+ break;
+ }
+ }
+ }
+ if (dlgName) {
+ break;
+ }
+ }
+ }
+ if (dlgName) {
+ const el =
+ window.document.getElementById(dlgName) ||
+ window.document.querySelector(`[data-dialog-name="${dlgName}"]`);
+
+ const viewName = Object.keys(this.props.context.views).find(
+ view => this.props.context.views[view].widgets[dlgName],
+ );
+ this.props.context.onCommand(
+ 'closeDialog',
+ viewName as ViewCommand,
+ dlgName as unknown as Record,
+ );
+
+ if ((el as any)?._showDialog) {
+ (el as any)._showDialog(false);
+ } else {
+ // noinspection JSJQueryEfficiency
+ (window.jQuery as any)(`#${dlgName}_dialog`).dialog('close');
+ }
+ } else {
+ window.alert('Dialog not found');
+ }
+ }
+
+ renderWidgetBody(props: RxRenderWidgetProps): React.JSX.Element {
+ super.renderWidgetBody(props);
+
+ const iconStyle: CSSProperties = {
+ filter: this.state.rxData.invert_icon ? 'invert(1)' : undefined,
+ };
+
+ if (!this.state.rxData.jquery_style && this.state.rxData.src) {
+ if (this.state.width > this.state.height) {
+ iconStyle.height = `${this.state.rxData.imageHeight || 100}%`;
+ iconStyle.width = 'auto';
+ } else {
+ iconStyle.width = `${this.state.rxData.imageHeight || 100}%`;
+ iconStyle.height = 'auto';
+ }
+ }
+ let iconSrc = !this.state.rxData.jquery_style && (this.state.rxData.src || this.state.rxData.icon);
+
+ if (iconSrc && iconSrc.startsWith('_PRJ_NAME/')) {
+ iconSrc = iconSrc.replace(
+ '_PRJ_NAME/',
+ `../${this.props.context.adapterName}.${this.props.context.instance}/${this.props.context.projectName}/`,
+ );
+ }
+
+ const icon = iconSrc ? (
+
+ ) : null;
+
+ const buttonStyle: CSSProperties = {};
+ // apply style from the element
+ Object.keys(this.state.rxStyle).forEach((attr: keyof WidgetStyleState) => {
+ const value = this.state.rxStyle[attr];
+ if (value !== null && value !== undefined && VisRxWidget.POSSIBLE_MUI_STYLES.includes(attr)) {
+ (attr as string) = attr.replace(/(-\w)/g, text => text[1].toUpperCase());
+ (buttonStyle as any)[attr] = value;
+ }
+ });
+ buttonStyle.minWidth = 'unset';
+ if (buttonStyle.borderWidth) {
+ buttonStyle.borderWidth = VisBaseWidget.correctStylePxValue(buttonStyle.borderWidth);
+ }
+ if (buttonStyle.fontSize) {
+ buttonStyle.fontSize = VisBaseWidget.correctStylePxValue(buttonStyle.fontSize);
+ }
+
+ // extra no rxData here, as it is not possible to set it with bindings
+ if (this.state.data.visResizable) {
+ buttonStyle.width = '100%';
+ buttonStyle.height = '100%';
+ } else {
+ buttonStyle.padding = this.state.rxData.padding;
+ }
+
+ let buttonText;
+ if (this.state.rxData.html) {
+ // ignore
+ } else {
+ buttonText = this.state.rxData.buttontext;
+ }
+
+ const content = [
+ this.state.rxData.html_prepend ? (
+
+ ) : null,
+ this.state.rxData.html ? (
+
+ ) : this.state.rxData.no_style || this.state.rxData.jquery_style ? (
+
+ ) : !buttonText ? (
+ this.onClick()}
+ size="small"
+ >
+ {icon}
+
+ ) : (
+
+ ),
+ this.state.rxData.html_append ? (
+
+ ) : null,
+ ];
+
+ return (
+ this.onClick() : undefined}
+ >
+ {content}
+
+ );
+ }
+}
+
+export default JQuiButtonDialogClose;
diff --git a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiButtonNavigation.tsx b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiButtonNavigation.tsx
index 5780c5fe..e82b2c3c 100644
--- a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiButtonNavigation.tsx
+++ b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiButtonNavigation.tsx
@@ -1,68 +1,68 @@
-/**
- * ioBroker.vis-2
- * https://github.com/ioBroker/ioBroker.vis
- *
- * Copyright (c) 2023-2024 Denis Haev https://github.com/GermanBluefox,
- * Creative Common Attribution-NonCommercial (CC BY-NC)
- *
- * http://creativecommons.org/licenses/by-nc/4.0/
- *
- * Short content:
- * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
- * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
- * (Free for non-commercial use).
- */
-
-import type {
- RxWidgetInfo,
- RxWidgetInfoAttributesFieldCheckbox,
- RxWidgetInfoAttributesFieldDefault,
- RxWidgetInfoAttributesFieldText,
- RxWidgetInfoWriteable,
-} from '@iobroker/types-vis-2';
-import JQuiButton from './JQuiButton';
-
-class JQuiButtonNavigation extends JQuiButton {
- static getWidgetInfo(): RxWidgetInfo {
- const widgetInfo = JQuiButton.getWidgetInfo() as unknown as RxWidgetInfoWriteable;
-
- const newWidgetInfo = {
- id: 'tplJquiButtonNav',
- visSet: 'jqui',
- visName: 'Navigation Button',
- visWidgetLabel: 'jqui_navigation_button',
- visPrev: 'widgets/jqui/img/Prev_ButtonNav.png',
- visOrder: 8,
- visAttrs: widgetInfo.visAttrs,
- };
-
- // Add note
- newWidgetInfo.visAttrs[0].fields.unshift({
- name: '_note',
- type: 'help',
- text: 'jqui_button_nav_blank_note',
- });
-
- const modal = JQuiButton.findField(newWidgetInfo, 'modal');
- delete modal.default;
-
- const navView = JQuiButton.findField(newWidgetInfo, 'nav_view');
- navView.default = '';
-
- const text = JQuiButton.findField(newWidgetInfo, 'buttontext');
- text.default = 'View';
-
- // set resizable to true
- const visResizable = JQuiButton.findField(newWidgetInfo, 'visResizable');
- visResizable.default = true;
-
- return newWidgetInfo as RxWidgetInfo;
- }
-
- // eslint-disable-next-line class-methods-use-this
- getWidgetInfo() {
- return JQuiButtonNavigation.getWidgetInfo();
- }
-}
-
-export default JQuiButtonNavigation;
+/**
+ * ioBroker.vis-2
+ * https://github.com/ioBroker/ioBroker.vis
+ *
+ * Copyright (c) 2023-2025 Denis Haev https://github.com/GermanBluefox,
+ * Creative Common Attribution-NonCommercial (CC BY-NC)
+ *
+ * http://creativecommons.org/licenses/by-nc/4.0/
+ *
+ * Short content:
+ * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
+ * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
+ * (Free for non-commercial use).
+ */
+
+import type {
+ RxWidgetInfo,
+ RxWidgetInfoAttributesFieldCheckbox,
+ RxWidgetInfoAttributesFieldDefault,
+ RxWidgetInfoAttributesFieldText,
+ RxWidgetInfoWriteable,
+} from '@iobroker/types-vis-2';
+import JQuiButton from './JQuiButton';
+
+class JQuiButtonNavigation extends JQuiButton {
+ static getWidgetInfo(): RxWidgetInfo {
+ const widgetInfo = JQuiButton.getWidgetInfo() as unknown as RxWidgetInfoWriteable;
+
+ const newWidgetInfo = {
+ id: 'tplJquiButtonNav',
+ visSet: 'jqui',
+ visName: 'Navigation Button',
+ visWidgetLabel: 'jqui_navigation_button',
+ visPrev: 'widgets/jqui/img/Prev_ButtonNav.png',
+ visOrder: 8,
+ visAttrs: widgetInfo.visAttrs,
+ };
+
+ // Add note
+ newWidgetInfo.visAttrs[0].fields.unshift({
+ name: '_note',
+ type: 'help',
+ text: 'jqui_button_nav_blank_note',
+ });
+
+ const modal = JQuiButton.findField(newWidgetInfo, 'modal');
+ delete modal.default;
+
+ const navView = JQuiButton.findField(newWidgetInfo, 'nav_view');
+ navView.default = '';
+
+ const text = JQuiButton.findField(newWidgetInfo, 'buttontext');
+ text.default = 'View';
+
+ // set resizable to true
+ const visResizable = JQuiButton.findField(newWidgetInfo, 'visResizable');
+ visResizable.default = true;
+
+ return newWidgetInfo as RxWidgetInfo;
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ getWidgetInfo() {
+ return JQuiButtonNavigation.getWidgetInfo();
+ }
+}
+
+export default JQuiButtonNavigation;
diff --git a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiButtonPasswordNavigation.tsx b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiButtonPasswordNavigation.tsx
index 3a36d871..f4eda3e8 100644
--- a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiButtonPasswordNavigation.tsx
+++ b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiButtonPasswordNavigation.tsx
@@ -1,71 +1,71 @@
-/**
- * ioBroker.vis-2
- * https://github.com/ioBroker/ioBroker.vis-2
- *
- * Copyright (c) 2023-2024 Denis Haev https://github.com/GermanBluefox,
- * Creative Common Attribution-NonCommercial (CC BY-NC)
- *
- * http://creativecommons.org/licenses/by-nc/4.0/
- *
- * Short content:
- * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
- * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
- * (Free for non-commercial use).
- */
-
-import type {
- RxWidgetInfo,
- RxWidgetInfoAttributesFieldCheckbox,
- RxWidgetInfoAttributesFieldDefault,
- RxWidgetInfoAttributesFieldText,
- RxWidgetInfoWriteable,
-} from '@iobroker/types-vis-2';
-import JQuiButton from './JQuiButton';
-
-class JQuiButtonPasswordNavigation extends JQuiButton {
- static getWidgetInfo(): RxWidgetInfo {
- const widgetInfo = JQuiButton.getWidgetInfo() as unknown as RxWidgetInfoWriteable;
-
- const newWidgetInfo = {
- id: 'tplJquiNavPw',
- visSet: 'jqui',
- visName: 'Navigation with password',
- visWidgetLabel: 'jqui_navigation_password',
- visPrev: 'widgets/jqui/img/Prev_ButtonNavPw.png',
- visOrder: 10,
- visAttrs: widgetInfo.visAttrs,
- };
-
- // Add note
- newWidgetInfo.visAttrs[0].fields.unshift({
- name: '_note',
- type: 'help',
- text: 'jqui_button_nav_blank_note',
- });
-
- const modal = JQuiButton.findField(newWidgetInfo, 'modal');
- delete modal.default;
-
- const text = JQuiButton.findField(newWidgetInfo, 'buttontext');
- text.default = 'Password';
-
- const navView = JQuiButton.findField(newWidgetInfo, 'nav_view');
- navView.default = '';
-
- const password = JQuiButton.findField(newWidgetInfo, 'Password');
- password.default = '';
-
- // set resizable to true
- const visResizable = JQuiButton.findField(newWidgetInfo, 'visResizable');
- visResizable.default = true;
-
- return newWidgetInfo as RxWidgetInfo;
- }
-
- // eslint-disable-next-line class-methods-use-this
- getWidgetInfo() {
- return JQuiButtonPasswordNavigation.getWidgetInfo();
- }
-}
-
-export default JQuiButtonPasswordNavigation;
+/**
+ * ioBroker.vis-2
+ * https://github.com/ioBroker/ioBroker.vis-2
+ *
+ * Copyright (c) 2023-2025 Denis Haev https://github.com/GermanBluefox,
+ * Creative Common Attribution-NonCommercial (CC BY-NC)
+ *
+ * http://creativecommons.org/licenses/by-nc/4.0/
+ *
+ * Short content:
+ * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
+ * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
+ * (Free for non-commercial use).
+ */
+
+import type {
+ RxWidgetInfo,
+ RxWidgetInfoAttributesFieldCheckbox,
+ RxWidgetInfoAttributesFieldDefault,
+ RxWidgetInfoAttributesFieldText,
+ RxWidgetInfoWriteable,
+} from '@iobroker/types-vis-2';
+import JQuiButton from './JQuiButton';
+
+class JQuiButtonPasswordNavigation extends JQuiButton {
+ static getWidgetInfo(): RxWidgetInfo {
+ const widgetInfo = JQuiButton.getWidgetInfo() as unknown as RxWidgetInfoWriteable;
+
+ const newWidgetInfo = {
+ id: 'tplJquiNavPw',
+ visSet: 'jqui',
+ visName: 'Navigation with password',
+ visWidgetLabel: 'jqui_navigation_password',
+ visPrev: 'widgets/jqui/img/Prev_ButtonNavPw.png',
+ visOrder: 10,
+ visAttrs: widgetInfo.visAttrs,
+ };
+
+ // Add note
+ newWidgetInfo.visAttrs[0].fields.unshift({
+ name: '_note',
+ type: 'help',
+ text: 'jqui_button_nav_blank_note',
+ });
+
+ const modal = JQuiButton.findField(newWidgetInfo, 'modal');
+ delete modal.default;
+
+ const text = JQuiButton.findField(newWidgetInfo, 'buttontext');
+ text.default = 'Password';
+
+ const navView = JQuiButton.findField(newWidgetInfo, 'nav_view');
+ navView.default = '';
+
+ const password = JQuiButton.findField(newWidgetInfo, 'Password');
+ password.default = '';
+
+ // set resizable to true
+ const visResizable = JQuiButton.findField(newWidgetInfo, 'visResizable');
+ visResizable.default = true;
+
+ return newWidgetInfo as RxWidgetInfo;
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ getWidgetInfo() {
+ return JQuiButtonPasswordNavigation.getWidgetInfo();
+ }
+}
+
+export default JQuiButtonPasswordNavigation;
diff --git a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiContainerButtonDialog.tsx b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiContainerButtonDialog.tsx
index 73af171f..05b97d49 100644
--- a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiContainerButtonDialog.tsx
+++ b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiContainerButtonDialog.tsx
@@ -1,63 +1,63 @@
-/**
- * ioBroker.vis-2
- * https://github.com/ioBroker/ioBroker.vis-2
- *
- * Copyright (c) 2023-2024 Denis Haev https://github.com/GermanBluefox,
- * Creative Common Attribution-NonCommercial (CC BY-NC)
- *
- * http://creativecommons.org/licenses/by-nc/4.0/
- *
- * Short content:
- * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
- * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
- * (Free for non-commercial use).
- */
-
-import type {
- RxWidgetInfo,
- RxWidgetInfoAttributesFieldSimple,
- RxWidgetInfoAttributesFieldText,
- RxWidgetInfoWriteable,
-} from '@iobroker/types-vis-2';
-import JQuiButton from './JQuiButton';
-
-class JQuiContainerButtonDialog extends JQuiButton {
- static getWidgetInfo(): RxWidgetInfo {
- const widgetInfo = JQuiButton.getWidgetInfo() as unknown as RxWidgetInfoWriteable;
-
- const newWidgetInfo = {
- id: 'tplContainerButtonDialog',
- visSet: 'jqui',
- visName: 'container - Button - view in jqui Dialog',
- visWidgetLabel: 'jqui_container_button_dialog',
- visPrev: 'widgets/jqui/img/Prev_ContainerButtonDialog.png',
- visOrder: 11,
- visAttrs: widgetInfo.visAttrs,
- };
-
- // Add note
- newWidgetInfo.visAttrs[0].fields.unshift({
- name: '_note',
- type: 'help',
- text: 'jqui_button_link_blank_note',
- });
-
- const buttonText = JQuiButton.findField(newWidgetInfo, 'buttontext');
- buttonText.default = 'Container Dialog';
-
- const containsView = JQuiButton.findField(
- newWidgetInfo,
- 'contains_view',
- );
- containsView.default = '';
-
- return newWidgetInfo as RxWidgetInfo;
- }
-
- // eslint-disable-next-line class-methods-use-this
- getWidgetInfo() {
- return JQuiContainerButtonDialog.getWidgetInfo();
- }
-}
-
-export default JQuiContainerButtonDialog;
+/**
+ * ioBroker.vis-2
+ * https://github.com/ioBroker/ioBroker.vis-2
+ *
+ * Copyright (c) 2023-2025 Denis Haev https://github.com/GermanBluefox,
+ * Creative Common Attribution-NonCommercial (CC BY-NC)
+ *
+ * http://creativecommons.org/licenses/by-nc/4.0/
+ *
+ * Short content:
+ * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
+ * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
+ * (Free for non-commercial use).
+ */
+
+import type {
+ RxWidgetInfo,
+ RxWidgetInfoAttributesFieldSimple,
+ RxWidgetInfoAttributesFieldText,
+ RxWidgetInfoWriteable,
+} from '@iobroker/types-vis-2';
+import JQuiButton from './JQuiButton';
+
+class JQuiContainerButtonDialog extends JQuiButton {
+ static getWidgetInfo(): RxWidgetInfo {
+ const widgetInfo = JQuiButton.getWidgetInfo() as unknown as RxWidgetInfoWriteable;
+
+ const newWidgetInfo = {
+ id: 'tplContainerButtonDialog',
+ visSet: 'jqui',
+ visName: 'container - Button - view in jqui Dialog',
+ visWidgetLabel: 'jqui_container_button_dialog',
+ visPrev: 'widgets/jqui/img/Prev_ContainerButtonDialog.png',
+ visOrder: 11,
+ visAttrs: widgetInfo.visAttrs,
+ };
+
+ // Add note
+ newWidgetInfo.visAttrs[0].fields.unshift({
+ name: '_note',
+ type: 'help',
+ text: 'jqui_button_link_blank_note',
+ });
+
+ const buttonText = JQuiButton.findField(newWidgetInfo, 'buttontext');
+ buttonText.default = 'Container Dialog';
+
+ const containsView = JQuiButton.findField(
+ newWidgetInfo,
+ 'contains_view',
+ );
+ containsView.default = '';
+
+ return newWidgetInfo as RxWidgetInfo;
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ getWidgetInfo() {
+ return JQuiContainerButtonDialog.getWidgetInfo();
+ }
+}
+
+export default JQuiContainerButtonDialog;
diff --git a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiContainerDialog.tsx b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiContainerDialog.tsx
index 430f436f..7978dfd3 100644
--- a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiContainerDialog.tsx
+++ b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiContainerDialog.tsx
@@ -1,64 +1,64 @@
-/**
- * ioBroker.vis-2
- * https://github.com/ioBroker/ioBroker.vis-2
- *
- * Copyright (c) 2023-2024 Denis Haev https://github.com/GermanBluefox,
- * Creative Common Attribution-NonCommercial (CC BY-NC)
- *
- * http://creativecommons.org/licenses/by-nc/4.0/
- *
- * Short content:
- * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
- * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
- * (Free for non-commercial use).
- */
-import type {
- RxWidgetInfo,
- RxWidgetInfoAttributesFieldCheckbox,
- RxWidgetInfoAttributesFieldHTML,
- RxWidgetInfoAttributesFieldText,
- RxWidgetInfoWriteable,
-} from '@iobroker/types-vis-2';
-import JQuiButton from './JQuiButton';
-
-class JQuiContainerDialog extends JQuiButton {
- static getWidgetInfo(): RxWidgetInfo {
- const widgetInfo = JQuiButton.getWidgetInfo() as unknown as RxWidgetInfoWriteable;
-
- const newWidgetInfo = {
- id: 'tplContainerDialog',
- visSet: 'jqui',
- visName: 'container - HTML - view in jqui Dialog',
- visWidgetLabel: 'jqui_container_dialog',
- visPrev: 'widgets/jqui/img/Prev_ContainerDialog.png',
- visOrder: 7,
- visAttrs: widgetInfo.visAttrs,
- };
-
- // Add note
- newWidgetInfo.visAttrs[0].fields.unshift({
- name: '_note',
- type: 'help',
- text: 'jqui_button_link_blank_note',
- });
-
- // set resizable to true
- const visResizable = JQuiButton.findField(newWidgetInfo, 'visResizable');
- visResizable.default = true;
-
- const buttonText = JQuiButton.findField(newWidgetInfo, 'buttontext');
- buttonText.default = 'Container Dialog';
-
- const htmlDialog = JQuiButton.findField(newWidgetInfo, 'html_dialog');
- htmlDialog.default = 'HTML Dialog
';
-
- return newWidgetInfo as RxWidgetInfo;
- }
-
- // eslint-disable-next-line class-methods-use-this
- getWidgetInfo() {
- return JQuiContainerDialog.getWidgetInfo();
- }
-}
-
-export default JQuiContainerDialog;
+/**
+ * ioBroker.vis-2
+ * https://github.com/ioBroker/ioBroker.vis-2
+ *
+ * Copyright (c) 2023-2025 Denis Haev https://github.com/GermanBluefox,
+ * Creative Common Attribution-NonCommercial (CC BY-NC)
+ *
+ * http://creativecommons.org/licenses/by-nc/4.0/
+ *
+ * Short content:
+ * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
+ * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
+ * (Free for non-commercial use).
+ */
+import type {
+ RxWidgetInfo,
+ RxWidgetInfoAttributesFieldCheckbox,
+ RxWidgetInfoAttributesFieldHTML,
+ RxWidgetInfoAttributesFieldText,
+ RxWidgetInfoWriteable,
+} from '@iobroker/types-vis-2';
+import JQuiButton from './JQuiButton';
+
+class JQuiContainerDialog extends JQuiButton {
+ static getWidgetInfo(): RxWidgetInfo {
+ const widgetInfo = JQuiButton.getWidgetInfo() as unknown as RxWidgetInfoWriteable;
+
+ const newWidgetInfo = {
+ id: 'tplContainerDialog',
+ visSet: 'jqui',
+ visName: 'container - HTML - view in jqui Dialog',
+ visWidgetLabel: 'jqui_container_dialog',
+ visPrev: 'widgets/jqui/img/Prev_ContainerDialog.png',
+ visOrder: 7,
+ visAttrs: widgetInfo.visAttrs,
+ };
+
+ // Add note
+ newWidgetInfo.visAttrs[0].fields.unshift({
+ name: '_note',
+ type: 'help',
+ text: 'jqui_button_link_blank_note',
+ });
+
+ // set resizable to true
+ const visResizable = JQuiButton.findField(newWidgetInfo, 'visResizable');
+ visResizable.default = true;
+
+ const buttonText = JQuiButton.findField(newWidgetInfo, 'buttontext');
+ buttonText.default = 'Container Dialog';
+
+ const htmlDialog = JQuiButton.findField(newWidgetInfo, 'html_dialog');
+ htmlDialog.default = 'HTML Dialog
';
+
+ return newWidgetInfo as RxWidgetInfo;
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ getWidgetInfo() {
+ return JQuiContainerDialog.getWidgetInfo();
+ }
+}
+
+export default JQuiContainerDialog;
diff --git a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiContainerIconDialog.tsx b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiContainerIconDialog.tsx
index 8193948a..e4e8b8d7 100644
--- a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiContainerIconDialog.tsx
+++ b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiContainerIconDialog.tsx
@@ -1,68 +1,68 @@
-/**
- * ioBroker.vis-2
- * https://github.com/ioBroker/ioBroker.vis-2
- *
- * Copyright (c) 2023-2024 Denis Haev https://github.com/GermanBluefox,
- * Creative Common Attribution-NonCommercial (CC BY-NC)
- *
- * http://creativecommons.org/licenses/by-nc/4.0/
- *
- * Short content:
- * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
- * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
- * (Free for non-commercial use).
- */
-import JQuiButton from './JQuiButton';
-import type {
- RxWidgetInfo,
- RxWidgetInfoAttributesField,
- RxWidgetInfoAttributesFieldCheckbox,
- RxWidgetInfoAttributesFieldSimple,
- Writeable,
-} from '@iobroker/types-vis-2';
-
-class JQuiContainerIconDialog extends JQuiButton {
- static getWidgetInfo(): RxWidgetInfo {
- const widgetInfo = JQuiButton.getWidgetInfo();
-
- const newWidgetInfo: RxWidgetInfo = {
- id: 'tplContainerIconDialog',
- visSet: 'jqui',
- visName: 'container - Icon - view in jqui Dialog',
- visWidgetLabel: 'jqui_container_icon_dialog',
- visPrev: 'widgets/jqui/img/Prev_ContainerIconDialog.png',
- visOrder: 12,
- visAttrs: widgetInfo.visAttrs,
- };
-
- // Add note
- (newWidgetInfo.visAttrs[0].fields as Writeable).unshift({
- name: '_note',
- type: 'help',
- text: 'jqui_button_link_blank_note',
- });
-
- // set resizable to true
- const visResizable = JQuiButton.findField(newWidgetInfo, 'visResizable');
- visResizable.default = true;
-
- const icon = JQuiButton.findField(newWidgetInfo, 'icon');
- icon.default =
- 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBmaWxsPSJjdXJyZW50Q29sb3IiIGQ9Ik0xOSAxOUg1VjVoN1YzSDVhMiAyIDAgMCAwLTIgMnYxNGEyIDIgMCAwIDAgMiAyaDE0YzEuMSAwIDItLjkgMi0ydi03aC0ydjd6TTE0IDN2MmgzLjU5bC05LjgzIDkuODNsMS40MSAxLjQxTDE5IDYuNDFWMTBoMlYzaC03eiIvPjwvc3ZnPg==';
-
- const buttonText = JQuiButton.findField(newWidgetInfo, 'buttontext');
- delete buttonText.default;
-
- const containsView = JQuiButton.findField(newWidgetInfo, 'contains_view');
- containsView.default = '';
-
- return newWidgetInfo;
- }
-
- // eslint-disable-next-line class-methods-use-this
- getWidgetInfo(): RxWidgetInfo {
- return JQuiContainerIconDialog.getWidgetInfo();
- }
-}
-
-export default JQuiContainerIconDialog;
+/**
+ * ioBroker.vis-2
+ * https://github.com/ioBroker/ioBroker.vis-2
+ *
+ * Copyright (c) 2023-2025 Denis Haev https://github.com/GermanBluefox,
+ * Creative Common Attribution-NonCommercial (CC BY-NC)
+ *
+ * http://creativecommons.org/licenses/by-nc/4.0/
+ *
+ * Short content:
+ * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
+ * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
+ * (Free for non-commercial use).
+ */
+import JQuiButton from './JQuiButton';
+import type {
+ RxWidgetInfo,
+ RxWidgetInfoAttributesField,
+ RxWidgetInfoAttributesFieldCheckbox,
+ RxWidgetInfoAttributesFieldSimple,
+ Writeable,
+} from '@iobroker/types-vis-2';
+
+class JQuiContainerIconDialog extends JQuiButton {
+ static getWidgetInfo(): RxWidgetInfo {
+ const widgetInfo = JQuiButton.getWidgetInfo();
+
+ const newWidgetInfo: RxWidgetInfo = {
+ id: 'tplContainerIconDialog',
+ visSet: 'jqui',
+ visName: 'container - Icon - view in jqui Dialog',
+ visWidgetLabel: 'jqui_container_icon_dialog',
+ visPrev: 'widgets/jqui/img/Prev_ContainerIconDialog.png',
+ visOrder: 12,
+ visAttrs: widgetInfo.visAttrs,
+ };
+
+ // Add note
+ (newWidgetInfo.visAttrs[0].fields as Writeable).unshift({
+ name: '_note',
+ type: 'help',
+ text: 'jqui_button_link_blank_note',
+ });
+
+ // set resizable to true
+ const visResizable = JQuiButton.findField(newWidgetInfo, 'visResizable');
+ visResizable.default = true;
+
+ const icon = JQuiButton.findField(newWidgetInfo, 'icon');
+ icon.default =
+ 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBmaWxsPSJjdXJyZW50Q29sb3IiIGQ9Ik0xOSAxOUg1VjVoN1YzSDVhMiAyIDAgMCAwLTIgMnYxNGEyIDIgMCAwIDAgMiAyaDE0YzEuMSAwIDItLjkgMi0ydi03aC0ydjd6TTE0IDN2MmgzLjU5bC05LjgzIDkuODNsMS40MSAxLjQxTDE5IDYuNDFWMTBoMlYzaC03eiIvPjwvc3ZnPg==';
+
+ const buttonText = JQuiButton.findField(newWidgetInfo, 'buttontext');
+ delete buttonText.default;
+
+ const containsView = JQuiButton.findField(newWidgetInfo, 'contains_view');
+ containsView.default = '';
+
+ return newWidgetInfo;
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ getWidgetInfo(): RxWidgetInfo {
+ return JQuiContainerIconDialog.getWidgetInfo();
+ }
+}
+
+export default JQuiContainerIconDialog;
diff --git a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiDialog.tsx b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiDialog.tsx
index b13caf94..d4cc1838 100644
--- a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiDialog.tsx
+++ b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiDialog.tsx
@@ -1,77 +1,77 @@
-/**
- * ioBroker.vis-2
- * https://github.com/ioBroker/ioBroker.vis-2
- *
- * Copyright (c) 2023-2024 Denis Haev https://github.com/GermanBluefox,
- * Creative Common Attribution-NonCommercial (CC BY-NC)
- *
- * http://creativecommons.org/licenses/by-nc/4.0/
- *
- * Short content:
- * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
- * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
- * (Free for non-commercial use).
- */
-import JQuiButton from './JQuiButton';
-import type {
- RxWidgetInfoAttributesField,
- RxWidgetInfoAttributesFieldCheckbox,
- RxWidgetInfoAttributesFieldSimple,
- WidgetStyle,
- Writeable,
- RxWidgetInfo,
-} from '@iobroker/types-vis-2';
-
-class JQuiDialog extends JQuiButton {
- static getWidgetInfo(): RxWidgetInfo {
- const widgetInfo = JQuiButton.getWidgetInfo();
-
- const newWidgetInfo: RxWidgetInfo = {
- id: 'tplJquiDialog',
- visSet: 'jqui',
- visName: 'HTML - Dialog',
- visWidgetLabel: 'jqui_html_dialog',
- visPrev: 'widgets/jqui/img/Prev_JquiDialog.png',
- visOrder: 5,
- visAttrs: widgetInfo.visAttrs,
- };
-
- // Add note
- (newWidgetInfo.visAttrs[0].fields as Writeable).unshift({
- name: '_note',
- type: 'help',
- text: 'jqui_button_link_blank_note',
- });
-
- // set resizable to true
- const visResizable = JQuiButton.findField(newWidgetInfo, 'visResizable');
- visResizable.default = true;
-
- const html = JQuiButton.findField(newWidgetInfo, 'html');
- html.default = 'HTML
';
-
- const buttonText = JQuiButton.findField(newWidgetInfo, 'buttontext');
- delete buttonText.default;
-
- const htmlDialog = JQuiButton.findField(newWidgetInfo, 'html_dialog');
- htmlDialog.default = 'HTML Dialog
';
-
- (newWidgetInfo.visDefaultStyle as Writeable) = {
- 'border-width': '1px',
- 'border-style': 'solid',
- 'border-color': '#000',
- width: '200px',
- height: '130px',
- cursor: 'pointer',
- };
-
- return newWidgetInfo;
- }
-
- // eslint-disable-next-line class-methods-use-this
- getWidgetInfo(): RxWidgetInfo {
- return JQuiDialog.getWidgetInfo();
- }
-}
-
-export default JQuiDialog;
+/**
+ * ioBroker.vis-2
+ * https://github.com/ioBroker/ioBroker.vis-2
+ *
+ * Copyright (c) 2023-2025 Denis Haev https://github.com/GermanBluefox,
+ * Creative Common Attribution-NonCommercial (CC BY-NC)
+ *
+ * http://creativecommons.org/licenses/by-nc/4.0/
+ *
+ * Short content:
+ * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
+ * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
+ * (Free for non-commercial use).
+ */
+import JQuiButton from './JQuiButton';
+import type {
+ RxWidgetInfoAttributesField,
+ RxWidgetInfoAttributesFieldCheckbox,
+ RxWidgetInfoAttributesFieldSimple,
+ WidgetStyle,
+ Writeable,
+ RxWidgetInfo,
+} from '@iobroker/types-vis-2';
+
+class JQuiDialog extends JQuiButton {
+ static getWidgetInfo(): RxWidgetInfo {
+ const widgetInfo = JQuiButton.getWidgetInfo();
+
+ const newWidgetInfo: RxWidgetInfo = {
+ id: 'tplJquiDialog',
+ visSet: 'jqui',
+ visName: 'HTML - Dialog',
+ visWidgetLabel: 'jqui_html_dialog',
+ visPrev: 'widgets/jqui/img/Prev_JquiDialog.png',
+ visOrder: 5,
+ visAttrs: widgetInfo.visAttrs,
+ };
+
+ // Add note
+ (newWidgetInfo.visAttrs[0].fields as Writeable).unshift({
+ name: '_note',
+ type: 'help',
+ text: 'jqui_button_link_blank_note',
+ });
+
+ // set resizable to true
+ const visResizable = JQuiButton.findField(newWidgetInfo, 'visResizable');
+ visResizable.default = true;
+
+ const html = JQuiButton.findField(newWidgetInfo, 'html');
+ html.default = 'HTML
';
+
+ const buttonText = JQuiButton.findField(newWidgetInfo, 'buttontext');
+ delete buttonText.default;
+
+ const htmlDialog = JQuiButton.findField(newWidgetInfo, 'html_dialog');
+ htmlDialog.default = 'HTML Dialog
';
+
+ (newWidgetInfo.visDefaultStyle as Writeable) = {
+ 'border-width': '1px',
+ 'border-style': 'solid',
+ 'border-color': '#000',
+ width: '200px',
+ height: '130px',
+ cursor: 'pointer',
+ };
+
+ return newWidgetInfo;
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ getWidgetInfo(): RxWidgetInfo {
+ return JQuiDialog.getWidgetInfo();
+ }
+}
+
+export default JQuiDialog;
diff --git a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiDialogExternal.tsx b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiDialogExternal.tsx
index 15c03162..c9a8df1e 100644
--- a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiDialogExternal.tsx
+++ b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiDialogExternal.tsx
@@ -1,63 +1,63 @@
-/**
- * ioBroker.vis-2
- * https://github.com/ioBroker/ioBroker.vis-2
- *
- * Copyright (c) 2023-2024 Denis Haev https://github.com/GermanBluefox,
- * Creative Common Attribution-NonCommercial (CC BY-NC)
- *
- * http://creativecommons.org/licenses/by-nc/4.0/
- *
- * Short content:
- * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
- * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
- * (Free for non-commercial use).
- */
-import JQuiButton from './JQuiButton';
-import type {
- RxWidgetInfo,
- RxWidgetInfoAttributesField,
- RxWidgetInfoAttributesFieldCheckbox,
- RxWidgetInfoAttributesFieldSimple,
- Writeable,
-} from '@iobroker/types-vis-2';
-
-class JQuiDialogExternal extends JQuiButton {
- static getWidgetInfo(): RxWidgetInfo {
- const widgetInfo: RxWidgetInfo = JQuiButton.getWidgetInfo();
-
- const newWidgetInfo = {
- id: 'tplContainerDialogExternal',
- visSet: 'jqui',
- visName: 'External Dialog',
- visWidgetLabel: 'jqui_html_external_dialog',
- visPrev: 'widgets/jqui/img/Prev_JquiExternalDialog.png',
- visOrder: 11,
- visAttrs: widgetInfo.visAttrs,
- };
-
- // Add note
- (newWidgetInfo.visAttrs[0].fields as Writeable).unshift({
- name: '_note',
- type: 'help',
- text: 'jqui_button_link_blank_note',
- });
-
- const externalDialog = JQuiButton.findField(
- newWidgetInfo,
- 'externalDialog',
- );
- externalDialog.default = true;
-
- const htmlDialog = JQuiButton.findField(newWidgetInfo, 'html_dialog');
- htmlDialog.default = 'HTML Dialog
';
-
- return newWidgetInfo;
- }
-
- // eslint-disable-next-line class-methods-use-this
- getWidgetInfo(): RxWidgetInfo {
- return JQuiDialogExternal.getWidgetInfo();
- }
-}
-
-export default JQuiDialogExternal;
+/**
+ * ioBroker.vis-2
+ * https://github.com/ioBroker/ioBroker.vis-2
+ *
+ * Copyright (c) 2023-2025 Denis Haev https://github.com/GermanBluefox,
+ * Creative Common Attribution-NonCommercial (CC BY-NC)
+ *
+ * http://creativecommons.org/licenses/by-nc/4.0/
+ *
+ * Short content:
+ * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
+ * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
+ * (Free for non-commercial use).
+ */
+import JQuiButton from './JQuiButton';
+import type {
+ RxWidgetInfo,
+ RxWidgetInfoAttributesField,
+ RxWidgetInfoAttributesFieldCheckbox,
+ RxWidgetInfoAttributesFieldSimple,
+ Writeable,
+} from '@iobroker/types-vis-2';
+
+class JQuiDialogExternal extends JQuiButton {
+ static getWidgetInfo(): RxWidgetInfo {
+ const widgetInfo: RxWidgetInfo = JQuiButton.getWidgetInfo();
+
+ const newWidgetInfo = {
+ id: 'tplContainerDialogExternal',
+ visSet: 'jqui',
+ visName: 'External Dialog',
+ visWidgetLabel: 'jqui_html_external_dialog',
+ visPrev: 'widgets/jqui/img/Prev_JquiExternalDialog.png',
+ visOrder: 11,
+ visAttrs: widgetInfo.visAttrs,
+ };
+
+ // Add note
+ (newWidgetInfo.visAttrs[0].fields as Writeable).unshift({
+ name: '_note',
+ type: 'help',
+ text: 'jqui_button_link_blank_note',
+ });
+
+ const externalDialog = JQuiButton.findField(
+ newWidgetInfo,
+ 'externalDialog',
+ );
+ externalDialog.default = true;
+
+ const htmlDialog = JQuiButton.findField(newWidgetInfo, 'html_dialog');
+ htmlDialog.default = 'HTML Dialog
';
+
+ return newWidgetInfo;
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ getWidgetInfo(): RxWidgetInfo {
+ return JQuiDialogExternal.getWidgetInfo();
+ }
+}
+
+export default JQuiDialogExternal;
diff --git a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiIconDialog.tsx b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiIconDialog.tsx
index 6838be2c..a9468b40 100644
--- a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiIconDialog.tsx
+++ b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiIconDialog.tsx
@@ -1,65 +1,65 @@
-/**
- * ioBroker.vis-2
- * https://github.com/ioBroker/ioBroker.vis-2
- *
- * Copyright (c) 2023-2024 Denis Haev https://github.com/GermanBluefox,
- * Creative Common Attribution-NonCommercial (CC BY-NC)
- *
- * http://creativecommons.org/licenses/by-nc/4.0/
- *
- * Short content:
- * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
- * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
- * (Free for non-commercial use).
- */
-
-import JQuiButton from './JQuiButton';
-import type {
- RxWidgetInfo,
- RxWidgetInfoAttributesField,
- RxWidgetInfoAttributesFieldCheckbox,
- RxWidgetInfoAttributesFieldSimple,
- Writeable,
-} from '@iobroker/types-vis-2';
-
-class JQuiIconDialog extends JQuiButton {
- static getWidgetInfo(): RxWidgetInfo {
- const widgetInfo: RxWidgetInfo = JQuiButton.getWidgetInfo();
-
- const newWidgetInfo = {
- id: 'tplJquiIconDialog',
- visSet: 'jqui',
- visName: 'Icon - Dialog',
- visWidgetLabel: 'jqui_icon_dialog',
- visPrev: 'widgets/jqui/img/Prev_JquiIconDialog.png',
- visOrder: 6,
- visAttrs: widgetInfo.visAttrs,
- };
-
- // Add note
- (newWidgetInfo.visAttrs[0].fields as Writeable).unshift({
- name: '_note',
- type: 'help',
- text: 'jqui_button_link_blank_note',
- });
-
- // set resizable to true
- const visResizable = JQuiButton.findField(newWidgetInfo, 'visResizable');
- visResizable.default = true;
-
- const buttonText = JQuiButton.findField(newWidgetInfo, 'buttontext');
- buttonText.default = 'Icon Dialog';
-
- const htmlDialog = JQuiButton.findField(newWidgetInfo, 'html_dialog');
- htmlDialog.default = 'HTML Dialog
';
-
- return newWidgetInfo;
- }
-
- // eslint-disable-next-line class-methods-use-this
- getWidgetInfo(): RxWidgetInfo {
- return JQuiIconDialog.getWidgetInfo();
- }
-}
-
-export default JQuiIconDialog;
+/**
+ * ioBroker.vis-2
+ * https://github.com/ioBroker/ioBroker.vis-2
+ *
+ * Copyright (c) 2023-2025 Denis Haev https://github.com/GermanBluefox,
+ * Creative Common Attribution-NonCommercial (CC BY-NC)
+ *
+ * http://creativecommons.org/licenses/by-nc/4.0/
+ *
+ * Short content:
+ * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
+ * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
+ * (Free for non-commercial use).
+ */
+
+import JQuiButton from './JQuiButton';
+import type {
+ RxWidgetInfo,
+ RxWidgetInfoAttributesField,
+ RxWidgetInfoAttributesFieldCheckbox,
+ RxWidgetInfoAttributesFieldSimple,
+ Writeable,
+} from '@iobroker/types-vis-2';
+
+class JQuiIconDialog extends JQuiButton {
+ static getWidgetInfo(): RxWidgetInfo {
+ const widgetInfo: RxWidgetInfo = JQuiButton.getWidgetInfo();
+
+ const newWidgetInfo = {
+ id: 'tplJquiIconDialog',
+ visSet: 'jqui',
+ visName: 'Icon - Dialog',
+ visWidgetLabel: 'jqui_icon_dialog',
+ visPrev: 'widgets/jqui/img/Prev_JquiIconDialog.png',
+ visOrder: 6,
+ visAttrs: widgetInfo.visAttrs,
+ };
+
+ // Add note
+ (newWidgetInfo.visAttrs[0].fields as Writeable).unshift({
+ name: '_note',
+ type: 'help',
+ text: 'jqui_button_link_blank_note',
+ });
+
+ // set resizable to true
+ const visResizable = JQuiButton.findField(newWidgetInfo, 'visResizable');
+ visResizable.default = true;
+
+ const buttonText = JQuiButton.findField(newWidgetInfo, 'buttontext');
+ buttonText.default = 'Icon Dialog';
+
+ const htmlDialog = JQuiButton.findField(newWidgetInfo, 'html_dialog');
+ htmlDialog.default = 'HTML Dialog
';
+
+ return newWidgetInfo;
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ getWidgetInfo(): RxWidgetInfo {
+ return JQuiIconDialog.getWidgetInfo();
+ }
+}
+
+export default JQuiIconDialog;
diff --git a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiIconHttpGet.tsx b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiIconHttpGet.tsx
index cb02efaf..cfaebe51 100644
--- a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiIconHttpGet.tsx
+++ b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiIconHttpGet.tsx
@@ -1,65 +1,65 @@
-/**
- * ioBroker.vis-2
- * https://github.com/ioBroker/ioBroker.vis-2
- *
- * Copyright (c) 2023-2024 Denis Haev https://github.com/GermanBluefox,
- * Creative Common Attribution-NonCommercial (CC BY-NC)
- *
- * http://creativecommons.org/licenses/by-nc/4.0/
- *
- * Short content:
- * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
- * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
- * (Free for non-commercial use).
- */
-
-import JQuiButton from './JQuiButton';
-import type {
- RxWidgetInfo,
- RxWidgetInfoAttributesField,
- RxWidgetInfoAttributesFieldCheckbox,
- RxWidgetInfoAttributesFieldSimple,
- Writeable,
-} from '@iobroker/types-vis-2';
-
-class JQuiIconHttpGet extends JQuiButton {
- static getWidgetInfo(): RxWidgetInfo {
- const widgetInfo = JQuiButton.getWidgetInfo();
-
- const newWidgetInfo = {
- id: 'tplIconHttpGet',
- visSet: 'jqui',
- visName: 'Icon HTTP GET',
- visWidgetLabel: 'jqui_icon_http_get',
- visPrev: 'widgets/jqui/img/Prev_IconHttpGet.png',
- visOrder: 4,
- visAttrs: widgetInfo.visAttrs,
- };
-
- // Add note
- (newWidgetInfo.visAttrs[0].fields as Writeable).unshift({
- name: '_note',
- type: 'help',
- text: 'jqui_button_link_blank_note',
- });
-
- const url = JQuiButton.findField(newWidgetInfo, 'url');
- url.default = 'http://';
-
- const text = JQuiButton.findField(newWidgetInfo, 'buttontext');
- text.default = 'URL Backend';
-
- // set resizable to true
- const visResizable = JQuiButton.findField(newWidgetInfo, 'visResizable');
- visResizable.default = true;
-
- return newWidgetInfo;
- }
-
- // eslint-disable-next-line class-methods-use-this
- getWidgetInfo(): RxWidgetInfo {
- return JQuiIconHttpGet.getWidgetInfo();
- }
-}
-
-export default JQuiIconHttpGet;
+/**
+ * ioBroker.vis-2
+ * https://github.com/ioBroker/ioBroker.vis-2
+ *
+ * Copyright (c) 2023-2025 Denis Haev https://github.com/GermanBluefox,
+ * Creative Common Attribution-NonCommercial (CC BY-NC)
+ *
+ * http://creativecommons.org/licenses/by-nc/4.0/
+ *
+ * Short content:
+ * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
+ * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
+ * (Free for non-commercial use).
+ */
+
+import JQuiButton from './JQuiButton';
+import type {
+ RxWidgetInfo,
+ RxWidgetInfoAttributesField,
+ RxWidgetInfoAttributesFieldCheckbox,
+ RxWidgetInfoAttributesFieldSimple,
+ Writeable,
+} from '@iobroker/types-vis-2';
+
+class JQuiIconHttpGet extends JQuiButton {
+ static getWidgetInfo(): RxWidgetInfo {
+ const widgetInfo = JQuiButton.getWidgetInfo();
+
+ const newWidgetInfo = {
+ id: 'tplIconHttpGet',
+ visSet: 'jqui',
+ visName: 'Icon HTTP GET',
+ visWidgetLabel: 'jqui_icon_http_get',
+ visPrev: 'widgets/jqui/img/Prev_IconHttpGet.png',
+ visOrder: 4,
+ visAttrs: widgetInfo.visAttrs,
+ };
+
+ // Add note
+ (newWidgetInfo.visAttrs[0].fields as Writeable).unshift({
+ name: '_note',
+ type: 'help',
+ text: 'jqui_button_link_blank_note',
+ });
+
+ const url = JQuiButton.findField(newWidgetInfo, 'url');
+ url.default = 'http://';
+
+ const text = JQuiButton.findField(newWidgetInfo, 'buttontext');
+ text.default = 'URL Backend';
+
+ // set resizable to true
+ const visResizable = JQuiButton.findField(newWidgetInfo, 'visResizable');
+ visResizable.default = true;
+
+ return newWidgetInfo;
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ getWidgetInfo(): RxWidgetInfo {
+ return JQuiIconHttpGet.getWidgetInfo();
+ }
+}
+
+export default JQuiIconHttpGet;
diff --git a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiIconInc.tsx b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiIconInc.tsx
index 6c3adbb9..9bb36ff8 100644
--- a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiIconInc.tsx
+++ b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiIconInc.tsx
@@ -1,57 +1,57 @@
-/**
- * ioBroker.vis-2
- * https://github.com/ioBroker/ioBroker.vis-2
- *
- * Copyright (c) 2023-2024 Denis Haev https://github.com/GermanBluefox,
- * Creative Common Attribution-NonCommercial (CC BY-NC)
- *
- * http://creativecommons.org/licenses/by-nc/4.0/
- *
- * Short content:
- * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
- * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
- * (Free for non-commercial use).
- */
-
-import JQuiWriteState from './JQuiWriteState';
-import type {
- RxWidgetInfo,
- RxWidgetInfoAttributesFieldSelect,
- RxWidgetInfoAttributesField,
- Writeable,
-} from '@iobroker/types-vis-2';
-
-class JQuiIconInc extends JQuiWriteState {
- static getWidgetInfo(): RxWidgetInfo {
- const widgetInfo: RxWidgetInfo = JQuiWriteState.getWidgetInfo();
-
- const newWidgetInfo: RxWidgetInfo = {
- id: 'tplIconInc',
- visSet: 'jqui',
- visName: 'Icon Increment',
- visWidgetLabel: 'jqui_icon_increment',
- visPrev: 'widgets/jqui/img/Prev_IconInc.png',
- visOrder: 27,
- visAttrs: widgetInfo.visAttrs,
- };
-
- // Add note
- (newWidgetInfo.visAttrs[0].fields as Writeable).unshift({
- name: '_note',
- type: 'help',
- text: 'jqui_write_state_note',
- });
-
- const target = JQuiWriteState.findField(newWidgetInfo, 'type');
- target.default = 'change';
-
- return newWidgetInfo;
- }
-
- // eslint-disable-next-line class-methods-use-this
- getWidgetInfo(): RxWidgetInfo {
- return JQuiIconInc.getWidgetInfo();
- }
-}
-
-export default JQuiIconInc;
+/**
+ * ioBroker.vis-2
+ * https://github.com/ioBroker/ioBroker.vis-2
+ *
+ * Copyright (c) 2023-2025 Denis Haev https://github.com/GermanBluefox,
+ * Creative Common Attribution-NonCommercial (CC BY-NC)
+ *
+ * http://creativecommons.org/licenses/by-nc/4.0/
+ *
+ * Short content:
+ * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
+ * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
+ * (Free for non-commercial use).
+ */
+
+import JQuiWriteState from './JQuiWriteState';
+import type {
+ RxWidgetInfo,
+ RxWidgetInfoAttributesFieldSelect,
+ RxWidgetInfoAttributesField,
+ Writeable,
+} from '@iobroker/types-vis-2';
+
+class JQuiIconInc extends JQuiWriteState {
+ static getWidgetInfo(): RxWidgetInfo {
+ const widgetInfo: RxWidgetInfo = JQuiWriteState.getWidgetInfo();
+
+ const newWidgetInfo: RxWidgetInfo = {
+ id: 'tplIconInc',
+ visSet: 'jqui',
+ visName: 'Icon Increment',
+ visWidgetLabel: 'jqui_icon_increment',
+ visPrev: 'widgets/jqui/img/Prev_IconInc.png',
+ visOrder: 27,
+ visAttrs: widgetInfo.visAttrs,
+ };
+
+ // Add note
+ (newWidgetInfo.visAttrs[0].fields as Writeable).unshift({
+ name: '_note',
+ type: 'help',
+ text: 'jqui_write_state_note',
+ });
+
+ const target = JQuiWriteState.findField(newWidgetInfo, 'type');
+ target.default = 'change';
+
+ return newWidgetInfo;
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ getWidgetInfo(): RxWidgetInfo {
+ return JQuiIconInc.getWidgetInfo();
+ }
+}
+
+export default JQuiIconInc;
diff --git a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiIconLink.tsx b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiIconLink.tsx
index 6cff80d9..e69ba80c 100644
--- a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiIconLink.tsx
+++ b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiIconLink.tsx
@@ -1,61 +1,61 @@
-/**
- * ioBroker.vis-2
- * https://github.com/ioBroker/ioBroker.vis
- *
- * Copyright (c) 2023-2024 Denis Haev https://github.com/GermanBluefox,
- * Creative Common Attribution-NonCommercial (CC BY-NC)
- *
- * http://creativecommons.org/licenses/by-nc/4.0/
- *
- * Short content:
- * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
- * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
- * (Free for non-commercial use).
- */
-import JQuiButton from './JQuiButton';
-import type {
- RxWidgetInfo,
- RxWidgetInfoAttributesField,
- RxWidgetInfoAttributesFieldCheckbox,
- RxWidgetInfoAttributesFieldSimple,
- Writeable,
-} from '@iobroker/types-vis-2';
-
-class JQuiIconLink extends JQuiButton {
- static getWidgetInfo(): RxWidgetInfo {
- const widgetInfo = JQuiButton.getWidgetInfo();
-
- const newWidgetInfo = {
- id: 'tplIconLink',
- visSet: 'jqui',
- visName: 'Button Link',
- visWidgetLabel: 'jqui_icon_link',
- visPrev: 'widgets/jqui/img/Prev_IconLink.png',
- visOrder: 3,
- visAttrs: widgetInfo.visAttrs,
- };
-
- // Add note
- (newWidgetInfo.visAttrs[0].fields as Writeable).unshift({
- name: '_note',
- type: 'help',
- text: 'jqui_button_link_blank_note',
- });
-
- const target = JQuiButton.findField(newWidgetInfo, 'target');
- target.default = '_blank';
-
- // set resizable to true
- const visResizable = JQuiButton.findField(newWidgetInfo, 'visResizable');
- visResizable.default = true;
-
- return newWidgetInfo;
- }
-
- // eslint-disable-next-line class-methods-use-this
- getWidgetInfo(): RxWidgetInfo {
- return JQuiIconLink.getWidgetInfo();
- }
-}
-
-export default JQuiIconLink;
+/**
+ * ioBroker.vis-2
+ * https://github.com/ioBroker/ioBroker.vis
+ *
+ * Copyright (c) 2023-2025 Denis Haev https://github.com/GermanBluefox,
+ * Creative Common Attribution-NonCommercial (CC BY-NC)
+ *
+ * http://creativecommons.org/licenses/by-nc/4.0/
+ *
+ * Short content:
+ * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
+ * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
+ * (Free for non-commercial use).
+ */
+import JQuiButton from './JQuiButton';
+import type {
+ RxWidgetInfo,
+ RxWidgetInfoAttributesField,
+ RxWidgetInfoAttributesFieldCheckbox,
+ RxWidgetInfoAttributesFieldSimple,
+ Writeable,
+} from '@iobroker/types-vis-2';
+
+class JQuiIconLink extends JQuiButton {
+ static getWidgetInfo(): RxWidgetInfo {
+ const widgetInfo = JQuiButton.getWidgetInfo();
+
+ const newWidgetInfo = {
+ id: 'tplIconLink',
+ visSet: 'jqui',
+ visName: 'Button Link',
+ visWidgetLabel: 'jqui_icon_link',
+ visPrev: 'widgets/jqui/img/Prev_IconLink.png',
+ visOrder: 3,
+ visAttrs: widgetInfo.visAttrs,
+ };
+
+ // Add note
+ (newWidgetInfo.visAttrs[0].fields as Writeable).unshift({
+ name: '_note',
+ type: 'help',
+ text: 'jqui_button_link_blank_note',
+ });
+
+ const target = JQuiButton.findField(newWidgetInfo, 'target');
+ target.default = '_blank';
+
+ // set resizable to true
+ const visResizable = JQuiButton.findField(newWidgetInfo, 'visResizable');
+ visResizable.default = true;
+
+ return newWidgetInfo;
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ getWidgetInfo(): RxWidgetInfo {
+ return JQuiIconLink.getWidgetInfo();
+ }
+}
+
+export default JQuiIconLink;
diff --git a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiIconNavigation.tsx b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiIconNavigation.tsx
index 4b0935e0..9672a69a 100644
--- a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiIconNavigation.tsx
+++ b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiIconNavigation.tsx
@@ -1,71 +1,71 @@
-/**
- * ioBroker.vis-2
- * https://github.com/ioBroker/ioBroker.vis-2
- *
- * Copyright (c) 2023-2024 Denis Haev https://github.com/GermanBluefox,
- * Creative Common Attribution-NonCommercial (CC BY-NC)
- *
- * http://creativecommons.org/licenses/by-nc/4.0/
- *
- * Short content:
- * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
- * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
- * (Free for non-commercial use).
- */
-import JQuiButton from './JQuiButton';
-import type {
- RxWidgetInfo,
- RxWidgetInfoAttributesField,
- RxWidgetInfoAttributesFieldCheckbox,
- RxWidgetInfoAttributesFieldSimple,
- Writeable,
-} from '@iobroker/types-vis-2';
-
-class JQuiIconNavigation extends JQuiButton {
- static getWidgetInfo(): RxWidgetInfo {
- const widgetInfo = JQuiButton.getWidgetInfo();
-
- const newWidgetInfo: RxWidgetInfo = {
- id: 'tplJquiIconNav',
- visSet: 'jqui',
- visName: 'Navigation Icon',
- visWidgetLabel: 'jqui_navigation_icon',
- visPrev: 'widgets/jqui/img/Prev_IconNav.png',
- visOrder: 9,
- visAttrs: widgetInfo.visAttrs,
- };
-
- // Add note
- (newWidgetInfo.visAttrs[0].fields as Writeable).unshift({
- name: '_note',
- type: 'help',
- text: 'jqui_button_nav_blank_note',
- });
-
- const buttonText = JQuiButton.findField(newWidgetInfo, 'buttontext');
- delete buttonText.default;
-
- const modal = JQuiButton.findField(newWidgetInfo, 'modal');
- delete modal.default;
-
- const navView = JQuiButton.findField(newWidgetInfo, 'nav_view');
- navView.default = '';
-
- const icon = JQuiButton.findField(newWidgetInfo, 'icon');
- icon.default =
- 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBmaWxsPSJjdXJyZW50Q29sb3IiIGQ9Ik0yMSAzTDMgMTAuNTN2Ljk4bDYuODQgMi42NUwxMi40OCAyMWguOThMMjEgM3oiLz48L3N2Zz4=';
-
- // set resizable to true
- const visResizable = JQuiButton.findField(newWidgetInfo, 'visResizable');
- visResizable.default = true;
-
- return newWidgetInfo;
- }
-
- // eslint-disable-next-line class-methods-use-this
- getWidgetInfo(): RxWidgetInfo {
- return JQuiIconNavigation.getWidgetInfo();
- }
-}
-
-export default JQuiIconNavigation;
+/**
+ * ioBroker.vis-2
+ * https://github.com/ioBroker/ioBroker.vis-2
+ *
+ * Copyright (c) 2023-2025 Denis Haev https://github.com/GermanBluefox,
+ * Creative Common Attribution-NonCommercial (CC BY-NC)
+ *
+ * http://creativecommons.org/licenses/by-nc/4.0/
+ *
+ * Short content:
+ * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
+ * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
+ * (Free for non-commercial use).
+ */
+import JQuiButton from './JQuiButton';
+import type {
+ RxWidgetInfo,
+ RxWidgetInfoAttributesField,
+ RxWidgetInfoAttributesFieldCheckbox,
+ RxWidgetInfoAttributesFieldSimple,
+ Writeable,
+} from '@iobroker/types-vis-2';
+
+class JQuiIconNavigation extends JQuiButton {
+ static getWidgetInfo(): RxWidgetInfo {
+ const widgetInfo = JQuiButton.getWidgetInfo();
+
+ const newWidgetInfo: RxWidgetInfo = {
+ id: 'tplJquiIconNav',
+ visSet: 'jqui',
+ visName: 'Navigation Icon',
+ visWidgetLabel: 'jqui_navigation_icon',
+ visPrev: 'widgets/jqui/img/Prev_IconNav.png',
+ visOrder: 9,
+ visAttrs: widgetInfo.visAttrs,
+ };
+
+ // Add note
+ (newWidgetInfo.visAttrs[0].fields as Writeable).unshift({
+ name: '_note',
+ type: 'help',
+ text: 'jqui_button_nav_blank_note',
+ });
+
+ const buttonText = JQuiButton.findField(newWidgetInfo, 'buttontext');
+ delete buttonText.default;
+
+ const modal = JQuiButton.findField(newWidgetInfo, 'modal');
+ delete modal.default;
+
+ const navView = JQuiButton.findField(newWidgetInfo, 'nav_view');
+ navView.default = '';
+
+ const icon = JQuiButton.findField(newWidgetInfo, 'icon');
+ icon.default =
+ 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBmaWxsPSJjdXJyZW50Q29sb3IiIGQ9Ik0yMSAzTDMgMTAuNTN2Ljk4bDYuODQgMi42NUwxMi40OCAyMWguOThMMjEgM3oiLz48L3N2Zz4=';
+
+ // set resizable to true
+ const visResizable = JQuiButton.findField(newWidgetInfo, 'visResizable');
+ visResizable.default = true;
+
+ return newWidgetInfo;
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ getWidgetInfo(): RxWidgetInfo {
+ return JQuiIconNavigation.getWidgetInfo();
+ }
+}
+
+export default JQuiIconNavigation;
diff --git a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiIconStateBool.tsx b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiIconStateBool.tsx
index cc22591c..863e137e 100644
--- a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiIconStateBool.tsx
+++ b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiIconStateBool.tsx
@@ -1,63 +1,63 @@
-/**
- * ioBroker.vis-2
- * https://github.com/ioBroker/ioBroker.vis-2
- *
- * Copyright (c) 2023-2024 Denis Haev https://github.com/GermanBluefox,
- * Creative Common Attribution-NonCommercial (CC BY-NC)
- *
- * http://creativecommons.org/licenses/by-nc/4.0/
- *
- * Short content:
- * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
- * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
- * (Free for non-commercial use).
- */
-
-import JQuiBinaryState from './JQuiBinaryState';
-import type {
- RxWidgetInfo,
- RxWidgetInfoAttributesField,
- RxWidgetInfoAttributesFieldSimple,
- Writeable,
-} from '@iobroker/types-vis-2';
-
-class JQuiIconStateBool extends JQuiBinaryState {
- static getWidgetInfo(): RxWidgetInfo {
- const widgetInfo = JQuiBinaryState.getWidgetInfo();
- const newWidgetInfo = {
- id: 'tplIconStateBool',
- visSet: 'jqui',
- visName: 'Binary Icon State',
- visWidgetLabel: 'jqui_icon_state_bool',
- visPrev: 'widgets/jqui/img/Prev_IconStateBool.png',
- visOrder: 15,
- visAttrs: widgetInfo.visAttrs,
- visDefaultStyle: {
- width: 70,
- height: 30,
- },
- };
-
- const iconFalse = JQuiBinaryState.findField(newWidgetInfo, 'icon_false');
- if (iconFalse) {
- iconFalse.default =
- 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBmaWxsPSJjdXJyZW50Q29sb3IiIGQ9Ik05IDIxYzAgLjUuNCAxIDEgMWg0Yy42IDAgMS0uNSAxLTF2LTFIOXYxem0zLTE5QzguMSAyIDUgNS4xIDUgOWMwIDIuNCAxLjIgNC41IDMgNS43VjE3YzAgLjUuNCAxIDEgMWg2Yy42IDAgMS0uNSAxLTF2LTIuM2MxLjgtMS4zIDMtMy40IDMtNS43YzAtMy45LTMuMS03LTctN3oiLz48L3N2Zz4=';
- }
-
- // Add note
- (newWidgetInfo.visAttrs[0].fields as Writeable).unshift({
- name: '_note',
- type: 'help',
- text: 'jqui_button_binary_control_note',
- });
-
- return newWidgetInfo;
- }
-
- // eslint-disable-next-line class-methods-use-this
- getWidgetInfo(): RxWidgetInfo {
- return JQuiIconStateBool.getWidgetInfo();
- }
-}
-
-export default JQuiIconStateBool;
+/**
+ * ioBroker.vis-2
+ * https://github.com/ioBroker/ioBroker.vis-2
+ *
+ * Copyright (c) 2023-2025 Denis Haev https://github.com/GermanBluefox,
+ * Creative Common Attribution-NonCommercial (CC BY-NC)
+ *
+ * http://creativecommons.org/licenses/by-nc/4.0/
+ *
+ * Short content:
+ * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
+ * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
+ * (Free for non-commercial use).
+ */
+
+import JQuiBinaryState from './JQuiBinaryState';
+import type {
+ RxWidgetInfo,
+ RxWidgetInfoAttributesField,
+ RxWidgetInfoAttributesFieldSimple,
+ Writeable,
+} from '@iobroker/types-vis-2';
+
+class JQuiIconStateBool extends JQuiBinaryState {
+ static getWidgetInfo(): RxWidgetInfo {
+ const widgetInfo = JQuiBinaryState.getWidgetInfo();
+ const newWidgetInfo = {
+ id: 'tplIconStateBool',
+ visSet: 'jqui',
+ visName: 'Binary Icon State',
+ visWidgetLabel: 'jqui_icon_state_bool',
+ visPrev: 'widgets/jqui/img/Prev_IconStateBool.png',
+ visOrder: 15,
+ visAttrs: widgetInfo.visAttrs,
+ visDefaultStyle: {
+ width: 70,
+ height: 30,
+ },
+ };
+
+ const iconFalse = JQuiBinaryState.findField(newWidgetInfo, 'icon_false');
+ if (iconFalse) {
+ iconFalse.default =
+ 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBmaWxsPSJjdXJyZW50Q29sb3IiIGQ9Ik05IDIxYzAgLjUuNCAxIDEgMWg0Yy42IDAgMS0uNSAxLTF2LTFIOXYxem0zLTE5QzguMSAyIDUgNS4xIDUgOWMwIDIuNCAxLjIgNC41IDMgNS43VjE3YzAgLjUuNCAxIDEgMWg2Yy42IDAgMS0uNSAxLTF2LTIuM2MxLjgtMS4zIDMtMy40IDMtNS43YzAtMy45LTMuMS03LTctN3oiLz48L3N2Zz4=';
+ }
+
+ // Add note
+ (newWidgetInfo.visAttrs[0].fields as Writeable).unshift({
+ name: '_note',
+ type: 'help',
+ text: 'jqui_button_binary_control_note',
+ });
+
+ return newWidgetInfo;
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ getWidgetInfo(): RxWidgetInfo {
+ return JQuiIconStateBool.getWidgetInfo();
+ }
+}
+
+export default JQuiIconStateBool;
diff --git a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiIconStatePushButton.tsx b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiIconStatePushButton.tsx
index 9c65947d..8f79f751 100644
--- a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiIconStatePushButton.tsx
+++ b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiIconStatePushButton.tsx
@@ -1,62 +1,62 @@
-/**
- * ioBroker.vis-2
- * https://github.com/ioBroker/ioBroker.vis-2
- *
- * Copyright (c) 2023-2024 Denis Haev https://github.com/GermanBluefox,
- * Creative Common Attribution-NonCommercial (CC BY-NC)
- *
- * http://creativecommons.org/licenses/by-nc/4.0/
- *
- * Short content:
- * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
- * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
- * (Free for non-commercial use).
- */
-
-import JQuiBinaryState from './JQuiBinaryState';
-import type {
- RxWidgetInfo,
- RxWidgetInfoAttributesField,
- RxWidgetInfoAttributesFieldCheckbox,
- Writeable,
-} from '@iobroker/types-vis-2';
-
-class JQuiIconStatePushButton extends JQuiBinaryState {
- static getWidgetInfo(): RxWidgetInfo {
- const widgetInfo: RxWidgetInfo = JQuiBinaryState.getWidgetInfo();
- const newWidgetInfo = {
- id: 'tplIconStatePushButton',
- visSet: 'jqui',
- visName: 'Binary Icon Push Button',
- visWidgetLabel: 'jqui_icon_state_push_button',
- visPrev: 'widgets/jqui/img/Prev_IconPushButton.png',
- visOrder: 15,
- visAttrs: widgetInfo.visAttrs,
- visDefaultStyle: {
- width: 70,
- height: 30,
- },
- };
-
- const pushMode = JQuiBinaryState.findField(newWidgetInfo, 'pushMode');
- if (pushMode) {
- pushMode.default = true;
- }
-
- // Add note
- (newWidgetInfo.visAttrs[0].fields as Writeable).unshift({
- name: '_note',
- type: 'help',
- text: 'jqui_button_binary_control_note',
- });
-
- return newWidgetInfo;
- }
-
- // eslint-disable-next-line class-methods-use-this
- getWidgetInfo(): RxWidgetInfo {
- return JQuiIconStatePushButton.getWidgetInfo();
- }
-}
-
-export default JQuiIconStatePushButton;
+/**
+ * ioBroker.vis-2
+ * https://github.com/ioBroker/ioBroker.vis-2
+ *
+ * Copyright (c) 2023-2025 Denis Haev https://github.com/GermanBluefox,
+ * Creative Common Attribution-NonCommercial (CC BY-NC)
+ *
+ * http://creativecommons.org/licenses/by-nc/4.0/
+ *
+ * Short content:
+ * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
+ * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
+ * (Free for non-commercial use).
+ */
+
+import JQuiBinaryState from './JQuiBinaryState';
+import type {
+ RxWidgetInfo,
+ RxWidgetInfoAttributesField,
+ RxWidgetInfoAttributesFieldCheckbox,
+ Writeable,
+} from '@iobroker/types-vis-2';
+
+class JQuiIconStatePushButton extends JQuiBinaryState {
+ static getWidgetInfo(): RxWidgetInfo {
+ const widgetInfo: RxWidgetInfo = JQuiBinaryState.getWidgetInfo();
+ const newWidgetInfo = {
+ id: 'tplIconStatePushButton',
+ visSet: 'jqui',
+ visName: 'Binary Icon Push Button',
+ visWidgetLabel: 'jqui_icon_state_push_button',
+ visPrev: 'widgets/jqui/img/Prev_IconPushButton.png',
+ visOrder: 15,
+ visAttrs: widgetInfo.visAttrs,
+ visDefaultStyle: {
+ width: 70,
+ height: 30,
+ },
+ };
+
+ const pushMode = JQuiBinaryState.findField(newWidgetInfo, 'pushMode');
+ if (pushMode) {
+ pushMode.default = true;
+ }
+
+ // Add note
+ (newWidgetInfo.visAttrs[0].fields as Writeable).unshift({
+ name: '_note',
+ type: 'help',
+ text: 'jqui_button_binary_control_note',
+ });
+
+ return newWidgetInfo;
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ getWidgetInfo(): RxWidgetInfo {
+ return JQuiIconStatePushButton.getWidgetInfo();
+ }
+}
+
+export default JQuiIconStatePushButton;
diff --git a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiInput.tsx b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiInput.tsx
index 081d3ddf..30015ffe 100644
--- a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiInput.tsx
+++ b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiInput.tsx
@@ -1,390 +1,390 @@
-/**
- * ioBroker.vis-2
- * https://github.com/ioBroker/ioBroker.vis-2
- *
- * Copyright (c) 2023-2024 Denis Haev https://github.com/GermanBluefox,
- * Creative Common Attribution-NonCommercial (CC BY-NC)
- *
- * http://creativecommons.org/licenses/by-nc/4.0/
- *
- * Short content:
- * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
- * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
- * (Free for non-commercial use).
- */
-
-import React from 'react';
-
-import { IconButton, TextField, InputAdornment, Button } from '@mui/material';
-
-import { KeyboardReturn } from '@mui/icons-material';
-
-import { I18n, type LegacyConnection } from '@iobroker/adapter-react-v5';
-
-import VisRxWidget, { type VisRxWidgetState } from '../../visRxWidget';
-import type {
- RxRenderWidgetProps,
- RxWidgetInfo,
- RxWidgetInfoAttributesField,
- VisBaseWidgetProps,
- Writeable,
-} from '@iobroker/types-vis-2';
-
-type RxData = {
- label: string;
- oid: string;
- asString: boolean;
- autoFocus: boolean;
- readOnly: boolean;
- withEnter: boolean;
- buttontext: string;
- selectAllOnFocus: boolean;
- unit: string;
- no_style: boolean;
- jquery_style: boolean;
- variant: 'filled' | 'outlined' | 'standard';
- size: number;
-};
-
-interface JQuiInputState extends VisRxWidgetState {
- input: string;
-}
-
-class JQuiInput extends VisRxWidget
{
- private focused: boolean = false;
- private readonly inputRef: React.RefObject;
- private jQueryDone: boolean = false;
- private object: ioBroker.StateObject | null = null;
-
- constructor(props: VisBaseWidgetProps) {
- super(props);
- Object.assign(this.state, {
- input: '',
- });
- this.inputRef = React.createRef();
- }
-
- static getWidgetInfo(): RxWidgetInfo {
- return {
- id: 'tplJquiInput',
- visSet: 'jqui',
- visName: 'Input',
- visWidgetLabel: 'jqui_input',
- visPrev: 'widgets/jqui/img/Prev_Input.png',
- visOrder: 13,
- visAttrs: [
- {
- name: 'common',
- fields: [
- {
- name: 'label',
- type: 'text',
- default: I18n.t('jqui_input').replace('jqui_', ''),
- },
- {
- name: 'oid',
- type: 'id',
- onChange: async (
- _field: RxWidgetInfoAttributesField,
- data: RxData,
- changeData: (newData: RxData) => void,
- socket: LegacyConnection,
- ): Promise => {
- if (data.oid && data.oid !== 'nothing_selected') {
- const obj = await socket.getObject(data.oid);
- let changed = false;
- if (obj?.common?.unit) {
- if (data.unit !== obj.common.unit) {
- data.unit = obj.common.unit;
- changed = true;
- }
- }
- if (obj?.common?.type !== 'number') {
- if (!data.asString) {
- data.asString = true;
- changed = true;
- }
- } else if (obj?.common?.type === 'number') {
- if (data.asString) {
- data.asString = false;
- changed = true;
- }
- }
- changed && changeData(data);
- }
- },
- },
- {
- name: 'asString',
- type: 'checkbox',
- label: 'jqui_as_string',
- },
- // {
- // name: 'digits',
- // type: 'slider',
- // min: 0,
- // max: 5,
- // hidden: data => !!data.asString,
- // },
- {
- name: 'autoFocus',
- type: 'checkbox',
- },
- {
- name: 'readOnly',
- type: 'checkbox',
- label: 'jqui_read_only',
- },
- {
- name: 'withEnter',
- type: 'checkbox',
- label: 'jqui_with_enter_button',
- hidden: '!!data.readOnly',
- },
- {
- name: 'buttontext',
- type: 'text',
- label: 'jqui_button_text',
- hidden: '!data.withEnter || !!data.readOnly',
- },
- {
- name: 'selectAllOnFocus',
- type: 'checkbox',
- label: 'jqui_select_all_on_focus',
- tooltip: 'jqui_select_all_on_focus_tooltip',
- },
- {
- name: 'unit',
- type: 'text',
- label: 'jqui_unit',
- },
- ],
- },
- {
- name: 'style',
- fields: [
- { name: 'no_style', type: 'checkbox', hidden: (data: RxData): boolean => data.jquery_style },
- {
- name: 'jquery_style',
- label: 'jqui_jquery_style',
- type: 'checkbox',
- hidden: (data: RxData): boolean => data.no_style,
- },
- {
- name: 'variant',
- label: 'jqui_variant',
- type: 'select',
- noTranslation: true,
- options: ['filled', 'outlined', 'standard'],
- default: 'standard',
- hidden: (data: RxData): boolean => data.jquery_style || data.no_style,
- },
- {
- name: 'size',
- type: 'slider',
- min: 4,
- max: 100,
- default: 10,
- hidden: (data: RxData): boolean => !data.no_style,
- },
- ],
- },
- ],
- };
- }
-
- // eslint-disable-next-line class-methods-use-this
- getWidgetInfo(): RxWidgetInfo {
- return JQuiInput.getWidgetInfo();
- }
-
- static findField(
- widgetInfo: RxWidgetInfo,
- name: string,
- ): Writeable | null {
- return VisRxWidget.findField(widgetInfo, name) as unknown as Writeable;
- }
-
- async componentDidMount(): Promise {
- super.componentDidMount();
-
- try {
- const input = await this.props.context.socket.getState(this.state.rxData.oid);
- if (input && input.val !== undefined && input.val !== null) {
- input.val = input.val.toString();
- this.setState({ input: input.val });
- }
- } catch (error) {
- console.error(`Cannot get state ${this.state.rxData.oid}: ${error}`);
- }
-
- if (
- this.inputRef.current &&
- this.state.rxData.autoFocus &&
- !this.props.editMode &&
- (this.state.rxData.jquery_style || this.state.rxData.no_style)
- ) {
- setTimeout(() => this.inputRef.current.focus(), 100);
- }
- }
-
- onStateUpdated(id: string, state: ioBroker.State | null | undefined): void {
- super.onStateUpdated(id, state);
- if (state?.val || state?.val === 0) {
- if (id === this.state.rxData.oid && !this.focused) {
- if (state.val.toString() !== this.state.input.toString()) {
- this.setState({ input: state.val as string });
- }
- }
- }
- }
-
- componentDidUpdate(): void {
- if (this.inputRef.current) {
- if (this.state.rxData.jquery_style && !this.jQueryDone) {
- this.jQueryDone = true;
- (window as any).jQuery(this.inputRef.current).button().addClass('ui-state-default');
- }
- }
- }
-
- async setValue(value: string): Promise {
- if (this.object?._id !== this.state.rxData.oid) {
- this.object = (await this.props.context.socket.getObject(this.state.rxData.oid)) as
- | ioBroker.StateObject
- | null
- | undefined;
- if (!this.object) {
- return;
- }
- }
- if (this.object?.common?.type === 'number') {
- let fValue = parseFloat(value.replace(',', '.'));
- if (Number.isNaN(value)) {
- fValue = 0;
- }
- this.props.context.setValue(this.state.rxData.oid, fValue);
- } else {
- this.props.context.setValue(this.state.rxData.oid, value);
- }
- }
-
- onChange(value: string): void {
- this.setState({ input: value });
- if (!this.state.rxData.withEnter) {
- void this.setValue(value);
- }
- }
-
- renderWidgetBody(props: RxRenderWidgetProps): React.JSX.Element {
- super.renderWidgetBody(props);
-
- props.style.overflow = 'visible';
-
- let content;
- const label = this.state.rxData.label; // title for back compatibility with tplJquiInputSet
- if (!this.state.rxData.jquery_style && !this.state.rxData.no_style) {
- content = (
- {
- this.focused = true;
- if (this.state.rxData.selectAllOnFocus) {
- e.target.select();
- }
- }}
- onBlur={() => (this.focused = false)}
- autoFocus={!this.props.editMode && this.state.rxData.autoFocus}
- variant={this.state.rxData.variant === undefined ? 'standard' : this.state.rxData.variant}
- slotProps={{
- htmlInput: {
- readOnly: this.state.rxData.readOnly,
- },
- input: {
- endAdornment:
- this.state.rxData.withEnter && !this.state.rxData.readOnly ? (
-
- {this.state.rxData.buttontext ? (
-
- ) : (
- this.setValue(this.state.input)}
- edge="end"
- >
-
-
- )}
-
- ) : undefined,
- startAdornment: this.state.rxData.unit ? (
- {this.state.rxData.unit}
- ) : undefined,
- },
- }}
- label={label}
- onChange={e => this.onChange(e.target.value)}
- />
- );
- } else {
- content = [
-
- {label}
-
,
- {
- this.focused = true;
- if (this.state.rxData.selectAllOnFocus) {
- e.target.select();
- }
- }}
- onBlur={() => (this.focused = false)}
- onChange={e => this.onChange(e.target.value)}
- />,
- this.state.rxData.withEnter && !this.state.rxData.readOnly ? (
- this.setValue(this.state.input)}
- edge="end"
- >
-
-
- ) : undefined,
- ];
- }
-
- return (
-
- {content}
-
- );
- }
-}
-
-export default JQuiInput;
+/**
+ * ioBroker.vis-2
+ * https://github.com/ioBroker/ioBroker.vis-2
+ *
+ * Copyright (c) 2023-2025 Denis Haev https://github.com/GermanBluefox,
+ * Creative Common Attribution-NonCommercial (CC BY-NC)
+ *
+ * http://creativecommons.org/licenses/by-nc/4.0/
+ *
+ * Short content:
+ * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
+ * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
+ * (Free for non-commercial use).
+ */
+
+import React from 'react';
+
+import { IconButton, TextField, InputAdornment, Button } from '@mui/material';
+
+import { KeyboardReturn } from '@mui/icons-material';
+
+import { I18n, type LegacyConnection } from '@iobroker/adapter-react-v5';
+
+import VisRxWidget, { type VisRxWidgetState } from '../../visRxWidget';
+import type {
+ RxRenderWidgetProps,
+ RxWidgetInfo,
+ RxWidgetInfoAttributesField,
+ VisBaseWidgetProps,
+ Writeable,
+} from '@iobroker/types-vis-2';
+
+type RxData = {
+ label: string;
+ oid: string;
+ asString: boolean;
+ autoFocus: boolean;
+ readOnly: boolean;
+ withEnter: boolean;
+ buttontext: string;
+ selectAllOnFocus: boolean;
+ unit: string;
+ no_style: boolean;
+ jquery_style: boolean;
+ variant: 'filled' | 'outlined' | 'standard';
+ size: number;
+};
+
+interface JQuiInputState extends VisRxWidgetState {
+ input: string;
+}
+
+class JQuiInput extends VisRxWidget
{
+ private focused: boolean = false;
+ private readonly inputRef: React.RefObject;
+ private jQueryDone: boolean = false;
+ private object: ioBroker.StateObject | null = null;
+
+ constructor(props: VisBaseWidgetProps) {
+ super(props);
+ Object.assign(this.state, {
+ input: '',
+ });
+ this.inputRef = React.createRef();
+ }
+
+ static getWidgetInfo(): RxWidgetInfo {
+ return {
+ id: 'tplJquiInput',
+ visSet: 'jqui',
+ visName: 'Input',
+ visWidgetLabel: 'jqui_input',
+ visPrev: 'widgets/jqui/img/Prev_Input.png',
+ visOrder: 13,
+ visAttrs: [
+ {
+ name: 'common',
+ fields: [
+ {
+ name: 'label',
+ type: 'text',
+ default: I18n.t('jqui_input').replace('jqui_', ''),
+ },
+ {
+ name: 'oid',
+ type: 'id',
+ onChange: async (
+ _field: RxWidgetInfoAttributesField,
+ data: RxData,
+ changeData: (newData: RxData) => void,
+ socket: LegacyConnection,
+ ): Promise => {
+ if (data.oid && data.oid !== 'nothing_selected') {
+ const obj = await socket.getObject(data.oid);
+ let changed = false;
+ if (obj?.common?.unit) {
+ if (data.unit !== obj.common.unit) {
+ data.unit = obj.common.unit;
+ changed = true;
+ }
+ }
+ if (obj?.common?.type !== 'number') {
+ if (!data.asString) {
+ data.asString = true;
+ changed = true;
+ }
+ } else if (obj?.common?.type === 'number') {
+ if (data.asString) {
+ data.asString = false;
+ changed = true;
+ }
+ }
+ changed && changeData(data);
+ }
+ },
+ },
+ {
+ name: 'asString',
+ type: 'checkbox',
+ label: 'jqui_as_string',
+ },
+ // {
+ // name: 'digits',
+ // type: 'slider',
+ // min: 0,
+ // max: 5,
+ // hidden: data => !!data.asString,
+ // },
+ {
+ name: 'autoFocus',
+ type: 'checkbox',
+ },
+ {
+ name: 'readOnly',
+ type: 'checkbox',
+ label: 'jqui_read_only',
+ },
+ {
+ name: 'withEnter',
+ type: 'checkbox',
+ label: 'jqui_with_enter_button',
+ hidden: '!!data.readOnly',
+ },
+ {
+ name: 'buttontext',
+ type: 'text',
+ label: 'jqui_button_text',
+ hidden: '!data.withEnter || !!data.readOnly',
+ },
+ {
+ name: 'selectAllOnFocus',
+ type: 'checkbox',
+ label: 'jqui_select_all_on_focus',
+ tooltip: 'jqui_select_all_on_focus_tooltip',
+ },
+ {
+ name: 'unit',
+ type: 'text',
+ label: 'jqui_unit',
+ },
+ ],
+ },
+ {
+ name: 'style',
+ fields: [
+ { name: 'no_style', type: 'checkbox', hidden: (data: RxData): boolean => data.jquery_style },
+ {
+ name: 'jquery_style',
+ label: 'jqui_jquery_style',
+ type: 'checkbox',
+ hidden: (data: RxData): boolean => data.no_style,
+ },
+ {
+ name: 'variant',
+ label: 'jqui_variant',
+ type: 'select',
+ noTranslation: true,
+ options: ['filled', 'outlined', 'standard'],
+ default: 'standard',
+ hidden: (data: RxData): boolean => data.jquery_style || data.no_style,
+ },
+ {
+ name: 'size',
+ type: 'slider',
+ min: 4,
+ max: 100,
+ default: 10,
+ hidden: (data: RxData): boolean => !data.no_style,
+ },
+ ],
+ },
+ ],
+ };
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ getWidgetInfo(): RxWidgetInfo {
+ return JQuiInput.getWidgetInfo();
+ }
+
+ static findField(
+ widgetInfo: RxWidgetInfo,
+ name: string,
+ ): Writeable | null {
+ return VisRxWidget.findField(widgetInfo, name) as unknown as Writeable;
+ }
+
+ async componentDidMount(): Promise {
+ super.componentDidMount();
+
+ try {
+ const input = await this.props.context.socket.getState(this.state.rxData.oid);
+ if (input && input.val !== undefined && input.val !== null) {
+ input.val = input.val.toString();
+ this.setState({ input: input.val });
+ }
+ } catch (error) {
+ console.error(`Cannot get state ${this.state.rxData.oid}: ${error}`);
+ }
+
+ if (
+ this.inputRef.current &&
+ this.state.rxData.autoFocus &&
+ !this.props.editMode &&
+ (this.state.rxData.jquery_style || this.state.rxData.no_style)
+ ) {
+ setTimeout(() => this.inputRef.current.focus(), 100);
+ }
+ }
+
+ onStateUpdated(id: string, state: ioBroker.State | null | undefined): void {
+ super.onStateUpdated(id, state);
+ if (state?.val || state?.val === 0) {
+ if (id === this.state.rxData.oid && !this.focused) {
+ if (state.val.toString() !== this.state.input.toString()) {
+ this.setState({ input: state.val as string });
+ }
+ }
+ }
+ }
+
+ componentDidUpdate(): void {
+ if (this.inputRef.current) {
+ if (this.state.rxData.jquery_style && !this.jQueryDone) {
+ this.jQueryDone = true;
+ (window as any).jQuery(this.inputRef.current).button().addClass('ui-state-default');
+ }
+ }
+ }
+
+ async setValue(value: string): Promise {
+ if (this.object?._id !== this.state.rxData.oid) {
+ this.object = (await this.props.context.socket.getObject(this.state.rxData.oid)) as
+ | ioBroker.StateObject
+ | null
+ | undefined;
+ if (!this.object) {
+ return;
+ }
+ }
+ if (this.object?.common?.type === 'number') {
+ let fValue = parseFloat(value.replace(',', '.'));
+ if (Number.isNaN(value)) {
+ fValue = 0;
+ }
+ this.props.context.setValue(this.state.rxData.oid, fValue);
+ } else {
+ this.props.context.setValue(this.state.rxData.oid, value);
+ }
+ }
+
+ onChange(value: string): void {
+ this.setState({ input: value });
+ if (!this.state.rxData.withEnter) {
+ void this.setValue(value);
+ }
+ }
+
+ renderWidgetBody(props: RxRenderWidgetProps): React.JSX.Element {
+ super.renderWidgetBody(props);
+
+ props.style.overflow = 'visible';
+
+ let content;
+ const label = this.state.rxData.label; // title for back compatibility with tplJquiInputSet
+ if (!this.state.rxData.jquery_style && !this.state.rxData.no_style) {
+ content = (
+ {
+ this.focused = true;
+ if (this.state.rxData.selectAllOnFocus) {
+ e.target.select();
+ }
+ }}
+ onBlur={() => (this.focused = false)}
+ autoFocus={!this.props.editMode && this.state.rxData.autoFocus}
+ variant={this.state.rxData.variant === undefined ? 'standard' : this.state.rxData.variant}
+ slotProps={{
+ htmlInput: {
+ readOnly: this.state.rxData.readOnly,
+ },
+ input: {
+ endAdornment:
+ this.state.rxData.withEnter && !this.state.rxData.readOnly ? (
+
+ {this.state.rxData.buttontext ? (
+
+ ) : (
+ this.setValue(this.state.input)}
+ edge="end"
+ >
+
+
+ )}
+
+ ) : undefined,
+ startAdornment: this.state.rxData.unit ? (
+ {this.state.rxData.unit}
+ ) : undefined,
+ },
+ }}
+ label={label}
+ onChange={e => this.onChange(e.target.value)}
+ />
+ );
+ } else {
+ content = [
+
+ {label}
+
,
+ {
+ this.focused = true;
+ if (this.state.rxData.selectAllOnFocus) {
+ e.target.select();
+ }
+ }}
+ onBlur={() => (this.focused = false)}
+ onChange={e => this.onChange(e.target.value)}
+ />,
+ this.state.rxData.withEnter && !this.state.rxData.readOnly ? (
+ this.setValue(this.state.input)}
+ edge="end"
+ >
+
+
+ ) : undefined,
+ ];
+ }
+
+ return (
+
+ {content}
+
+ );
+ }
+}
+
+export default JQuiInput;
diff --git a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiInputDate.tsx b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiInputDate.tsx
index 9ccb7e5b..2adce23c 100644
--- a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiInputDate.tsx
+++ b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiInputDate.tsx
@@ -1,201 +1,201 @@
-/**
- * ioBroker.vis-2
- * https://github.com/ioBroker/ioBroker.vis-2
- *
- * Copyright (c) 2023-2024 Denis Haev https://github.com/GermanBluefox,
- * Creative Common Attribution-NonCommercial (CC BY-NC)
- *
- * http://creativecommons.org/licenses/by-nc/4.0/
- *
- * Short content:
- * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
- * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
- * (Free for non-commercial use).
- */
-
-import React from 'react';
-import dayjs from 'dayjs';
-
-import { DatePicker, LocalizationProvider } from '@mui/x-date-pickers';
-import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
-import 'dayjs/locale/de';
-import 'dayjs/locale/en';
-import 'dayjs/locale/ru';
-import 'dayjs/locale/zh-cn';
-import 'dayjs/locale/uk';
-import 'dayjs/locale/it';
-import 'dayjs/locale/fr';
-import 'dayjs/locale/es';
-import 'dayjs/locale/pl';
-import 'dayjs/locale/pt';
-import 'dayjs/locale/nl';
-
-import type { TextFieldVariants } from '@mui/material';
-
-import type { RxRenderWidgetProps, RxWidgetInfo } from '@iobroker/types-vis-2';
-import VisRxWidget from '../../visRxWidget';
-
-const styles: { textRoot: { [key: string]: React.CSSProperties } } = {
- textRoot: {
- '& .MuiInputBase-root': {
- width: '100%',
- height: '100%',
- },
- },
-};
-
-type RxData = {
- oid: string;
- variant: TextFieldVariants;
- autoFocus: boolean;
- clearable: boolean;
- widgetTitle: string;
- disableFuture: boolean;
- disablePast: boolean;
- asFullDate: boolean;
- displayWeekNumber: boolean;
- wideFormat: boolean;
-};
-
-class JQuiInputDate extends VisRxWidget {
- /** If a user does not want to use full date */
- private readonly EASY_DATE_FORMAT = 'DD.MM.YYYY';
-
- static getWidgetInfo(): RxWidgetInfo {
- return {
- id: 'tplJquiInputDate',
- visSet: 'jqui',
- visName: 'Input Date',
- visWidgetLabel: 'jqui_input_date',
- visPrev: 'widgets/jqui/img/Prev_InputDate.png',
- visOrder: 30,
- visAttrs: [
- {
- name: 'common',
- fields: [
- {
- name: 'oid',
- type: 'id',
- },
- {
- name: 'variant',
- label: 'jqui_variant',
- type: 'select',
- options: [
- { label: 'standard', value: 'standard' },
- { label: 'outlined', value: 'outlined' },
- { label: 'filled', value: 'filled' },
- ],
- default: 'standard',
- },
- {
- name: 'autoFocus',
- type: 'checkbox',
- },
- {
- name: 'clearable',
- label: 'jqui_clearable',
- type: 'checkbox',
- },
- {
- name: 'widgetTitle',
- label: 'jqui_widgetTitle',
- type: 'text',
- },
- {
- name: 'disableFuture',
- label: 'jqui_disableFuture',
- type: 'checkbox',
- hidden: '!!data.disablePast',
- },
- {
- name: 'disablePast',
- label: 'jqui_disablePast',
- type: 'checkbox',
- hidden: '!!data.disableFuture',
- },
- {
- name: 'asFullDate',
- label: 'jqui_asFullDate',
- type: 'checkbox',
- },
- {
- name: 'displayWeekNumber',
- label: 'jqui_displayWeekNumber',
- type: 'checkbox',
- },
- {
- name: 'wideFormat',
- label: 'jqui_wideFormat',
- type: 'checkbox',
- },
- ],
- },
- ],
- visDefaultStyle: {
- width: 250,
- height: 56,
- },
- } as const;
- }
-
- // eslint-disable-next-line class-methods-use-this
- getWidgetInfo(): RxWidgetInfo {
- return JQuiInputDate.getWidgetInfo();
- }
-
- renderWidgetBody(props: RxRenderWidgetProps): React.JSX.Element {
- super.renderWidgetBody(props);
- props.style.overflow = 'visible';
-
- return (
-
-
- {
- if (!newValue) {
- return;
- }
-
- const val = this.state.rxData.asFullDate
- ? newValue.toDate().toString()
- : newValue.format(this.EASY_DATE_FORMAT);
- this.props.context.setValue(this.state.rxData.oid, val);
- }}
- formatDensity={this.state.rxData.wideFormat ? 'spacious' : 'dense'}
- slotProps={{
- textField: {
- variant: this.state.rxData.variant || 'standard',
- style: {
- width: '100%',
- height: '100%',
- },
- sx: styles.textRoot,
- },
- field: {
- clearable: this.state.rxData.clearable,
- onClear: () => this.props.context.setValue(this.state.rxData.oid, ''),
- },
- }}
- disableFuture={this.state.rxData.disableFuture || false}
- disablePast={this.state.rxData.disablePast || false}
- displayWeekNumber={this.state.rxData.displayWeekNumber || false}
- />
-
-
- );
- }
-}
-
-export default JQuiInputDate;
+/**
+ * ioBroker.vis-2
+ * https://github.com/ioBroker/ioBroker.vis-2
+ *
+ * Copyright (c) 2023-2025 Denis Haev https://github.com/GermanBluefox,
+ * Creative Common Attribution-NonCommercial (CC BY-NC)
+ *
+ * http://creativecommons.org/licenses/by-nc/4.0/
+ *
+ * Short content:
+ * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
+ * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
+ * (Free for non-commercial use).
+ */
+
+import React from 'react';
+import dayjs from 'dayjs';
+
+import { DatePicker, LocalizationProvider } from '@mui/x-date-pickers';
+import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
+import 'dayjs/locale/de';
+import 'dayjs/locale/en';
+import 'dayjs/locale/ru';
+import 'dayjs/locale/zh-cn';
+import 'dayjs/locale/uk';
+import 'dayjs/locale/it';
+import 'dayjs/locale/fr';
+import 'dayjs/locale/es';
+import 'dayjs/locale/pl';
+import 'dayjs/locale/pt';
+import 'dayjs/locale/nl';
+
+import type { TextFieldVariants } from '@mui/material';
+
+import type { RxRenderWidgetProps, RxWidgetInfo } from '@iobroker/types-vis-2';
+import VisRxWidget from '../../visRxWidget';
+
+const styles: { textRoot: { [key: string]: React.CSSProperties } } = {
+ textRoot: {
+ '& .MuiInputBase-root': {
+ width: '100%',
+ height: '100%',
+ },
+ },
+};
+
+type RxData = {
+ oid: string;
+ variant: TextFieldVariants;
+ autoFocus: boolean;
+ clearable: boolean;
+ widgetTitle: string;
+ disableFuture: boolean;
+ disablePast: boolean;
+ asFullDate: boolean;
+ displayWeekNumber: boolean;
+ wideFormat: boolean;
+};
+
+class JQuiInputDate extends VisRxWidget {
+ /** If a user does not want to use full date */
+ private readonly EASY_DATE_FORMAT = 'DD.MM.YYYY';
+
+ static getWidgetInfo(): RxWidgetInfo {
+ return {
+ id: 'tplJquiInputDate',
+ visSet: 'jqui',
+ visName: 'Input Date',
+ visWidgetLabel: 'jqui_input_date',
+ visPrev: 'widgets/jqui/img/Prev_InputDate.png',
+ visOrder: 30,
+ visAttrs: [
+ {
+ name: 'common',
+ fields: [
+ {
+ name: 'oid',
+ type: 'id',
+ },
+ {
+ name: 'variant',
+ label: 'jqui_variant',
+ type: 'select',
+ options: [
+ { label: 'standard', value: 'standard' },
+ { label: 'outlined', value: 'outlined' },
+ { label: 'filled', value: 'filled' },
+ ],
+ default: 'standard',
+ },
+ {
+ name: 'autoFocus',
+ type: 'checkbox',
+ },
+ {
+ name: 'clearable',
+ label: 'jqui_clearable',
+ type: 'checkbox',
+ },
+ {
+ name: 'widgetTitle',
+ label: 'jqui_widgetTitle',
+ type: 'text',
+ },
+ {
+ name: 'disableFuture',
+ label: 'jqui_disableFuture',
+ type: 'checkbox',
+ hidden: '!!data.disablePast',
+ },
+ {
+ name: 'disablePast',
+ label: 'jqui_disablePast',
+ type: 'checkbox',
+ hidden: '!!data.disableFuture',
+ },
+ {
+ name: 'asFullDate',
+ label: 'jqui_asFullDate',
+ type: 'checkbox',
+ },
+ {
+ name: 'displayWeekNumber',
+ label: 'jqui_displayWeekNumber',
+ type: 'checkbox',
+ },
+ {
+ name: 'wideFormat',
+ label: 'jqui_wideFormat',
+ type: 'checkbox',
+ },
+ ],
+ },
+ ],
+ visDefaultStyle: {
+ width: 250,
+ height: 56,
+ },
+ } as const;
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ getWidgetInfo(): RxWidgetInfo {
+ return JQuiInputDate.getWidgetInfo();
+ }
+
+ renderWidgetBody(props: RxRenderWidgetProps): React.JSX.Element {
+ super.renderWidgetBody(props);
+ props.style.overflow = 'visible';
+
+ return (
+
+
+ {
+ if (!newValue) {
+ return;
+ }
+
+ const val = this.state.rxData.asFullDate
+ ? newValue.toDate().toString()
+ : newValue.format(this.EASY_DATE_FORMAT);
+ this.props.context.setValue(this.state.rxData.oid, val);
+ }}
+ formatDensity={this.state.rxData.wideFormat ? 'spacious' : 'dense'}
+ slotProps={{
+ textField: {
+ variant: this.state.rxData.variant || 'standard',
+ style: {
+ width: '100%',
+ height: '100%',
+ },
+ sx: styles.textRoot,
+ },
+ field: {
+ clearable: this.state.rxData.clearable,
+ onClear: () => this.props.context.setValue(this.state.rxData.oid, ''),
+ },
+ }}
+ disableFuture={this.state.rxData.disableFuture || false}
+ disablePast={this.state.rxData.disablePast || false}
+ displayWeekNumber={this.state.rxData.displayWeekNumber || false}
+ />
+
+
+ );
+ }
+}
+
+export default JQuiInputDate;
diff --git a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiInputDateTime.tsx b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiInputDateTime.tsx
index 6db590c7..2f2d89f7 100644
--- a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiInputDateTime.tsx
+++ b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiInputDateTime.tsx
@@ -1,195 +1,195 @@
-/**
- * ioBroker.vis-2
- * https://github.com/ioBroker/ioBroker.vis-2
- *
- * Copyright (c) 2023-2024 Denis Haev https://github.com/GermanBluefox,
- * Creative Common Attribution-NonCommercial (CC BY-NC)
- *
- * http://creativecommons.org/licenses/by-nc/4.0/
- *
- * Short content:
- * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
- * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
- * (Free for non-commercial use).
- */
-
-import React from 'react';
-
-import { TimePicker, LocalizationProvider } from '@mui/x-date-pickers';
-import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
-import dayjs from 'dayjs';
-import 'dayjs/locale/de';
-import 'dayjs/locale/en';
-import 'dayjs/locale/ru';
-import 'dayjs/locale/zh-cn';
-import 'dayjs/locale/uk';
-import 'dayjs/locale/it';
-import 'dayjs/locale/fr';
-import 'dayjs/locale/es';
-import 'dayjs/locale/pl';
-import 'dayjs/locale/pt';
-import 'dayjs/locale/nl';
-
-import type { TextFieldVariants } from '@mui/material';
-
-import type { RxRenderWidgetProps, RxWidgetInfo } from '@iobroker/types-vis-2';
-import VisRxWidget from '../../visRxWidget';
-
-const styles: { textRoot: { [key: string]: React.CSSProperties } } = {
- textRoot: {
- '& .MuiInputBase-root': {
- width: '100%',
- height: '100%',
- },
- },
-};
-
-type RxData = {
- oid: string;
- variant: TextFieldVariants;
- autoFocus: boolean;
- clearable: boolean;
- widgetTitle: string;
- ampm: boolean;
- asDate: boolean;
- stepMinute: number;
-};
-
-class JQuiInputDateTime extends VisRxWidget {
- static getWidgetInfo(): RxWidgetInfo {
- return {
- id: 'tplJquiInputDatetime',
- visSet: 'jqui',
- visName: 'Input Time',
- visWidgetLabel: 'jqui_input_time',
- visPrev: 'widgets/jqui/img/Prev_InputDateTime.png',
- visOrder: 31,
- visAttrs: [
- {
- name: 'common',
- fields: [
- {
- name: 'oid',
- type: 'id',
- },
- {
- name: 'variant',
- label: 'jqui_variant',
- type: 'select',
- options: [
- { label: 'standard', value: 'standard' },
- { label: 'outlined', value: 'outlined' },
- { label: 'filled', value: 'filled' },
- ],
- default: 'standard',
- },
- {
- name: 'autoFocus',
- type: 'checkbox',
- },
- {
- name: 'clearable',
- label: 'jqui_clearable',
- type: 'checkbox',
- },
- {
- name: 'widgetTitle',
- label: 'jqui_widgetTitle',
- type: 'text',
- },
- {
- name: 'ampm',
- label: 'jqui_ampm',
- type: 'checkbox',
- },
- {
- name: 'asDate',
- label: 'jqui_asDate',
- type: 'checkbox',
- },
- {
- name: 'stepMinute',
- label: 'jqui_stepMinute',
- type: 'select',
- options: [
- { label: '1 minute', value: 1 },
- { label: '2 minutes', value: 2 },
- { label: '3 minutes', value: 3 },
- { label: '4 minutes', value: 4 },
- { label: '5 minutes', value: 5 },
- { label: '10 minutes', value: 10 },
- { label: '15 minutes', value: 15 },
- { label: '20 minutes', value: 20 },
- { label: '30 minutes', value: 30 },
- { label: '60 minutes', value: 60 },
- ],
- },
- ],
- },
- ],
- visDefaultStyle: {
- width: 250,
- height: 56,
- },
- } as const;
- }
-
- // eslint-disable-next-line class-methods-use-this
- getWidgetInfo(): RxWidgetInfo {
- return JQuiInputDateTime.getWidgetInfo();
- }
-
- renderWidgetBody(props: RxRenderWidgetProps): React.JSX.Element {
- super.renderWidgetBody(props);
-
- const val = this.state.values[`${this.state.rxData.oid}.val`];
- const asDate = this.state.rxData.asDate;
- props.style.overflow = 'visible';
-
- return (
-
-
- {
- if (!value) {
- return;
- }
-
- const res = !asDate
- ? value.format('HH:mm')
- : value.second(0).millisecond(0).toDate().toString();
-
- this.props.context.setValue(this.state.rxData.oid, res);
- }}
- slotProps={{
- textField: {
- variant: this.state.rxData.variant || 'standard',
- style: {
- width: '100%',
- height: '100%',
- },
- sx: styles.textRoot,
- },
- field: {
- clearable: this.state.rxData.clearable,
- onClear: () => this.props.context.setValue(this.state.rxData.oid, ''),
- },
- }}
- />
-
-
- );
- }
-}
-
-export default JQuiInputDateTime;
+/**
+ * ioBroker.vis-2
+ * https://github.com/ioBroker/ioBroker.vis-2
+ *
+ * Copyright (c) 2023-2025 Denis Haev https://github.com/GermanBluefox,
+ * Creative Common Attribution-NonCommercial (CC BY-NC)
+ *
+ * http://creativecommons.org/licenses/by-nc/4.0/
+ *
+ * Short content:
+ * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
+ * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
+ * (Free for non-commercial use).
+ */
+
+import React from 'react';
+
+import { TimePicker, LocalizationProvider } from '@mui/x-date-pickers';
+import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
+import dayjs from 'dayjs';
+import 'dayjs/locale/de';
+import 'dayjs/locale/en';
+import 'dayjs/locale/ru';
+import 'dayjs/locale/zh-cn';
+import 'dayjs/locale/uk';
+import 'dayjs/locale/it';
+import 'dayjs/locale/fr';
+import 'dayjs/locale/es';
+import 'dayjs/locale/pl';
+import 'dayjs/locale/pt';
+import 'dayjs/locale/nl';
+
+import type { TextFieldVariants } from '@mui/material';
+
+import type { RxRenderWidgetProps, RxWidgetInfo } from '@iobroker/types-vis-2';
+import VisRxWidget from '../../visRxWidget';
+
+const styles: { textRoot: { [key: string]: React.CSSProperties } } = {
+ textRoot: {
+ '& .MuiInputBase-root': {
+ width: '100%',
+ height: '100%',
+ },
+ },
+};
+
+type RxData = {
+ oid: string;
+ variant: TextFieldVariants;
+ autoFocus: boolean;
+ clearable: boolean;
+ widgetTitle: string;
+ ampm: boolean;
+ asDate: boolean;
+ stepMinute: number;
+};
+
+class JQuiInputDateTime extends VisRxWidget {
+ static getWidgetInfo(): RxWidgetInfo {
+ return {
+ id: 'tplJquiInputDatetime',
+ visSet: 'jqui',
+ visName: 'Input Time',
+ visWidgetLabel: 'jqui_input_time',
+ visPrev: 'widgets/jqui/img/Prev_InputDateTime.png',
+ visOrder: 31,
+ visAttrs: [
+ {
+ name: 'common',
+ fields: [
+ {
+ name: 'oid',
+ type: 'id',
+ },
+ {
+ name: 'variant',
+ label: 'jqui_variant',
+ type: 'select',
+ options: [
+ { label: 'standard', value: 'standard' },
+ { label: 'outlined', value: 'outlined' },
+ { label: 'filled', value: 'filled' },
+ ],
+ default: 'standard',
+ },
+ {
+ name: 'autoFocus',
+ type: 'checkbox',
+ },
+ {
+ name: 'clearable',
+ label: 'jqui_clearable',
+ type: 'checkbox',
+ },
+ {
+ name: 'widgetTitle',
+ label: 'jqui_widgetTitle',
+ type: 'text',
+ },
+ {
+ name: 'ampm',
+ label: 'jqui_ampm',
+ type: 'checkbox',
+ },
+ {
+ name: 'asDate',
+ label: 'jqui_asDate',
+ type: 'checkbox',
+ },
+ {
+ name: 'stepMinute',
+ label: 'jqui_stepMinute',
+ type: 'select',
+ options: [
+ { label: '1 minute', value: 1 },
+ { label: '2 minutes', value: 2 },
+ { label: '3 minutes', value: 3 },
+ { label: '4 minutes', value: 4 },
+ { label: '5 minutes', value: 5 },
+ { label: '10 minutes', value: 10 },
+ { label: '15 minutes', value: 15 },
+ { label: '20 minutes', value: 20 },
+ { label: '30 minutes', value: 30 },
+ { label: '60 minutes', value: 60 },
+ ],
+ },
+ ],
+ },
+ ],
+ visDefaultStyle: {
+ width: 250,
+ height: 56,
+ },
+ } as const;
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ getWidgetInfo(): RxWidgetInfo {
+ return JQuiInputDateTime.getWidgetInfo();
+ }
+
+ renderWidgetBody(props: RxRenderWidgetProps): React.JSX.Element {
+ super.renderWidgetBody(props);
+
+ const val = this.state.values[`${this.state.rxData.oid}.val`];
+ const asDate = this.state.rxData.asDate;
+ props.style.overflow = 'visible';
+
+ return (
+
+
+ {
+ if (!value) {
+ return;
+ }
+
+ const res = !asDate
+ ? value.format('HH:mm')
+ : value.second(0).millisecond(0).toDate().toString();
+
+ this.props.context.setValue(this.state.rxData.oid, res);
+ }}
+ slotProps={{
+ textField: {
+ variant: this.state.rxData.variant || 'standard',
+ style: {
+ width: '100%',
+ height: '100%',
+ },
+ sx: styles.textRoot,
+ },
+ field: {
+ clearable: this.state.rxData.clearable,
+ onClear: () => this.props.context.setValue(this.state.rxData.oid, ''),
+ },
+ }}
+ />
+
+
+ );
+ }
+}
+
+export default JQuiInputDateTime;
diff --git a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiInputSet.tsx b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiInputSet.tsx
index 1112087f..787b2e0a 100644
--- a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiInputSet.tsx
+++ b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiInputSet.tsx
@@ -1,68 +1,68 @@
-/**
- * ioBroker.vis-2
- * https://github.com/ioBroker/ioBroker.vis-2
- *
- * Copyright (c) 2023-2024 Denis Haev https://github.com/GermanBluefox,
- * Creative Common Attribution-NonCommercial (CC BY-NC)
- *
- * http://creativecommons.org/licenses/by-nc/4.0/
- *
- * Short content:
- * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
- * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
- * (Free for non-commercial use).
- */
-
-import JQuiInput from './JQuiInput';
-import type {
- RxWidgetInfo,
- RxWidgetInfoAttributesField,
- RxWidgetInfoAttributesFieldCheckbox,
- RxWidgetInfoAttributesFieldSimple,
- Writeable,
-} from '@iobroker/types-vis-2';
-
-class JQuiInputSet extends JQuiInput {
- static getWidgetInfo(): RxWidgetInfo {
- const widgetInfo = JQuiInput.getWidgetInfo();
- const newWidgetInfo: RxWidgetInfo = {
- id: 'tplJquiInputSet',
- visSet: 'jqui',
- visName: 'Input + Button',
- visWidgetLabel: 'jqui_input_with_button',
- visPrev: 'widgets/jqui/img/Prev_InputWithButton.png',
- visOrder: 14,
- visAttrs: widgetInfo.visAttrs,
- visDefaultStyle: {
- width: 150,
- height: 45,
- },
- };
-
- // Add note
- (newWidgetInfo.visAttrs[0].fields as Writeable).unshift({
- name: '_note',
- type: 'help',
- text: 'jqui_button_input_note',
- });
-
- const withEnter = JQuiInput.findField(newWidgetInfo, 'withEnter');
- if (withEnter) {
- withEnter.default = true;
- }
-
- const buttonText = JQuiInput.findField(newWidgetInfo, 'buttontext');
- if (buttonText) {
- buttonText.default = 'OK';
- }
-
- return newWidgetInfo;
- }
-
- // eslint-disable-next-line class-methods-use-this
- getWidgetInfo(): RxWidgetInfo {
- return JQuiInputSet.getWidgetInfo();
- }
-}
-
-export default JQuiInputSet;
+/**
+ * ioBroker.vis-2
+ * https://github.com/ioBroker/ioBroker.vis-2
+ *
+ * Copyright (c) 2023-2025 Denis Haev https://github.com/GermanBluefox,
+ * Creative Common Attribution-NonCommercial (CC BY-NC)
+ *
+ * http://creativecommons.org/licenses/by-nc/4.0/
+ *
+ * Short content:
+ * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
+ * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
+ * (Free for non-commercial use).
+ */
+
+import JQuiInput from './JQuiInput';
+import type {
+ RxWidgetInfo,
+ RxWidgetInfoAttributesField,
+ RxWidgetInfoAttributesFieldCheckbox,
+ RxWidgetInfoAttributesFieldSimple,
+ Writeable,
+} from '@iobroker/types-vis-2';
+
+class JQuiInputSet extends JQuiInput {
+ static getWidgetInfo(): RxWidgetInfo {
+ const widgetInfo = JQuiInput.getWidgetInfo();
+ const newWidgetInfo: RxWidgetInfo = {
+ id: 'tplJquiInputSet',
+ visSet: 'jqui',
+ visName: 'Input + Button',
+ visWidgetLabel: 'jqui_input_with_button',
+ visPrev: 'widgets/jqui/img/Prev_InputWithButton.png',
+ visOrder: 14,
+ visAttrs: widgetInfo.visAttrs,
+ visDefaultStyle: {
+ width: 150,
+ height: 45,
+ },
+ };
+
+ // Add note
+ (newWidgetInfo.visAttrs[0].fields as Writeable).unshift({
+ name: '_note',
+ type: 'help',
+ text: 'jqui_button_input_note',
+ });
+
+ const withEnter = JQuiInput.findField(newWidgetInfo, 'withEnter');
+ if (withEnter) {
+ withEnter.default = true;
+ }
+
+ const buttonText = JQuiInput.findField(newWidgetInfo, 'buttontext');
+ if (buttonText) {
+ buttonText.default = 'OK';
+ }
+
+ return newWidgetInfo;
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ getWidgetInfo(): RxWidgetInfo {
+ return JQuiInputSet.getWidgetInfo();
+ }
+}
+
+export default JQuiInputSet;
diff --git a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiRadio.tsx b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiRadio.tsx
index f6ea7434..a30c4103 100644
--- a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiRadio.tsx
+++ b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiRadio.tsx
@@ -1,62 +1,62 @@
-/**
- * ioBroker.vis-2
- * https://github.com/ioBroker/ioBroker.vis-2
- *
- * Copyright (c) 2023-2024 Denis Haev https://github.com/GermanBluefox,
- * Creative Common Attribution-NonCommercial (CC BY-NC)
- *
- * http://creativecommons.org/licenses/by-nc/4.0/
- *
- * Short content:
- * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
- * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
- * (Free for non-commercial use).
- */
-
-import JQuiBinaryState from './JQuiBinaryState';
-import type {
- RxWidgetInfo,
- RxWidgetInfoAttributesFieldSelect,
- Writeable,
- RxWidgetInfoAttributesField,
-} from '@iobroker/types-vis-2';
-
-class JQuiRadio extends JQuiBinaryState {
- static getWidgetInfo(): RxWidgetInfo {
- const widgetInfo: RxWidgetInfo = JQuiBinaryState.getWidgetInfo();
- const newWidgetInfo: RxWidgetInfo = {
- id: 'tplJquiRadio',
- visSet: 'jqui',
- visName: 'Radiobuttons on/off',
- visWidgetLabel: 'jqui_radio_buttons_on_off',
- visPrev: 'widgets/jqui/img/Prev_RadioButtonsOnOff.png',
- visOrder: 15,
- visAttrs: widgetInfo.visAttrs,
- visDefaultStyle: {
- width: 150,
- height: 45,
- },
- };
-
- // Add note
- (newWidgetInfo.visAttrs[0].fields as Writeable).unshift({
- name: '_note',
- type: 'help',
- text: 'jqui_button_binary_control_note',
- });
-
- const type = JQuiBinaryState.findField(newWidgetInfo, 'type');
- if (type) {
- type.default = 'radio';
- }
-
- return newWidgetInfo;
- }
-
- // eslint-disable-next-line class-methods-use-this
- getWidgetInfo(): RxWidgetInfo {
- return JQuiRadio.getWidgetInfo();
- }
-}
-
-export default JQuiRadio;
+/**
+ * ioBroker.vis-2
+ * https://github.com/ioBroker/ioBroker.vis-2
+ *
+ * Copyright (c) 2023-2025 Denis Haev https://github.com/GermanBluefox,
+ * Creative Common Attribution-NonCommercial (CC BY-NC)
+ *
+ * http://creativecommons.org/licenses/by-nc/4.0/
+ *
+ * Short content:
+ * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
+ * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
+ * (Free for non-commercial use).
+ */
+
+import JQuiBinaryState from './JQuiBinaryState';
+import type {
+ RxWidgetInfo,
+ RxWidgetInfoAttributesFieldSelect,
+ Writeable,
+ RxWidgetInfoAttributesField,
+} from '@iobroker/types-vis-2';
+
+class JQuiRadio extends JQuiBinaryState {
+ static getWidgetInfo(): RxWidgetInfo {
+ const widgetInfo: RxWidgetInfo = JQuiBinaryState.getWidgetInfo();
+ const newWidgetInfo: RxWidgetInfo = {
+ id: 'tplJquiRadio',
+ visSet: 'jqui',
+ visName: 'Radiobuttons on/off',
+ visWidgetLabel: 'jqui_radio_buttons_on_off',
+ visPrev: 'widgets/jqui/img/Prev_RadioButtonsOnOff.png',
+ visOrder: 15,
+ visAttrs: widgetInfo.visAttrs,
+ visDefaultStyle: {
+ width: 150,
+ height: 45,
+ },
+ };
+
+ // Add note
+ (newWidgetInfo.visAttrs[0].fields as Writeable).unshift({
+ name: '_note',
+ type: 'help',
+ text: 'jqui_button_binary_control_note',
+ });
+
+ const type = JQuiBinaryState.findField(newWidgetInfo, 'type');
+ if (type) {
+ type.default = 'radio';
+ }
+
+ return newWidgetInfo;
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ getWidgetInfo(): RxWidgetInfo {
+ return JQuiRadio.getWidgetInfo();
+ }
+}
+
+export default JQuiRadio;
diff --git a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiRadioList.tsx b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiRadioList.tsx
index 42af0bb0..44ea8cf5 100644
--- a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiRadioList.tsx
+++ b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiRadioList.tsx
@@ -1,60 +1,60 @@
-/**
- * ioBroker.vis-2
- * https://github.com/ioBroker/ioBroker.vis-2
- *
- * Copyright (c) 2023-2024 Denis Haev https://github.com/GermanBluefox,
- * Creative Common Attribution-NonCommercial (CC BY-NC)
- *
- * http://creativecommons.org/licenses/by-nc/4.0/
- *
- * Short content:
- * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
- * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
- * (Free for non-commercial use).
- */
-
-import JQuiState from './JQuiState';
-import type {
- RxWidgetInfo,
- RxWidgetInfoAttributesFieldSelect,
- Writeable,
- RxWidgetInfoAttributesField,
-} from '@iobroker/types-vis-2';
-
-class JQuiRadioList extends JQuiState {
- static getWidgetInfo(): RxWidgetInfo {
- const widgetInfo: RxWidgetInfo = JQuiState.getWidgetInfo();
- const newWidgetInfo: RxWidgetInfo = {
- id: 'tplJquiRadioList',
- visSet: 'jqui',
- visName: 'Radiobuttons ValueList',
- visWidgetLabel: 'jqui_radio_list',
- visPrev: 'widgets/jqui/img/Prev_RadioList.png',
- visOrder: 15,
- visAttrs: widgetInfo.visAttrs,
- visDefaultStyle: {
- width: 250,
- height: 45,
- },
- };
-
- const type = JQuiState.findField(newWidgetInfo, 'type');
- type.default = 'radio';
-
- // Add note
- (newWidgetInfo.visAttrs[0].fields as Writeable).unshift({
- name: '_note',
- type: 'help',
- text: 'jqui_state_note',
- });
-
- return newWidgetInfo;
- }
-
- // eslint-disable-next-line class-methods-use-this
- getWidgetInfo(): RxWidgetInfo {
- return JQuiRadioList.getWidgetInfo();
- }
-}
-
-export default JQuiRadioList;
+/**
+ * ioBroker.vis-2
+ * https://github.com/ioBroker/ioBroker.vis-2
+ *
+ * Copyright (c) 2023-2025 Denis Haev https://github.com/GermanBluefox,
+ * Creative Common Attribution-NonCommercial (CC BY-NC)
+ *
+ * http://creativecommons.org/licenses/by-nc/4.0/
+ *
+ * Short content:
+ * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
+ * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
+ * (Free for non-commercial use).
+ */
+
+import JQuiState from './JQuiState';
+import type {
+ RxWidgetInfo,
+ RxWidgetInfoAttributesFieldSelect,
+ Writeable,
+ RxWidgetInfoAttributesField,
+} from '@iobroker/types-vis-2';
+
+class JQuiRadioList extends JQuiState {
+ static getWidgetInfo(): RxWidgetInfo {
+ const widgetInfo: RxWidgetInfo = JQuiState.getWidgetInfo();
+ const newWidgetInfo: RxWidgetInfo = {
+ id: 'tplJquiRadioList',
+ visSet: 'jqui',
+ visName: 'Radiobuttons ValueList',
+ visWidgetLabel: 'jqui_radio_list',
+ visPrev: 'widgets/jqui/img/Prev_RadioList.png',
+ visOrder: 15,
+ visAttrs: widgetInfo.visAttrs,
+ visDefaultStyle: {
+ width: 250,
+ height: 45,
+ },
+ };
+
+ const type = JQuiState.findField(newWidgetInfo, 'type');
+ type.default = 'radio';
+
+ // Add note
+ (newWidgetInfo.visAttrs[0].fields as Writeable).unshift({
+ name: '_note',
+ type: 'help',
+ text: 'jqui_state_note',
+ });
+
+ return newWidgetInfo;
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ getWidgetInfo(): RxWidgetInfo {
+ return JQuiRadioList.getWidgetInfo();
+ }
+}
+
+export default JQuiRadioList;
diff --git a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiRadioSteps.tsx b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiRadioSteps.tsx
index 54d42625..94c01c9f 100644
--- a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiRadioSteps.tsx
+++ b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiRadioSteps.tsx
@@ -1,52 +1,52 @@
-/**
- * ioBroker.vis-2
- * https://github.com/ioBroker/ioBroker.vis-2
- *
- * Copyright (c) 2023-2024 Denis Haev https://github.com/GermanBluefox,
- * Creative Common Attribution-NonCommercial (CC BY-NC)
- *
- * http://creativecommons.org/licenses/by-nc/4.0/
- *
- * Short content:
- * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
- * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
- * (Free for non-commercial use).
- */
-
-import JQuiState from './JQuiState';
-import type { RxWidgetInfo, Writeable, RxWidgetInfoAttributesField } from '@iobroker/types-vis-2';
-
-class JQuiRadioSteps extends JQuiState {
- static getWidgetInfo(): RxWidgetInfo {
- const widgetInfo: RxWidgetInfo = JQuiState.getWidgetInfo();
- const newWidgetInfo: RxWidgetInfo = {
- id: 'tplJquiRadioSteps',
- visSet: 'jqui',
- visName: 'Radiobuttons 25%',
- visWidgetLabel: 'jqui_radio_steps',
- visPrev: 'widgets/jqui/img/Prev_RadioSteps.png',
- visOrder: 25,
- visAttrs: widgetInfo.visAttrs,
- visDefaultStyle: {
- width: 350,
- height: 35,
- },
- };
-
- // Add note
- (newWidgetInfo.visAttrs[0].fields as Writeable).unshift({
- name: '_note',
- type: 'help',
- text: 'jqui_state_note',
- });
-
- return newWidgetInfo;
- }
-
- // eslint-disable-next-line class-methods-use-this
- getWidgetInfo(): RxWidgetInfo {
- return JQuiRadioSteps.getWidgetInfo();
- }
-}
-
-export default JQuiRadioSteps;
+/**
+ * ioBroker.vis-2
+ * https://github.com/ioBroker/ioBroker.vis-2
+ *
+ * Copyright (c) 2023-2025 Denis Haev https://github.com/GermanBluefox,
+ * Creative Common Attribution-NonCommercial (CC BY-NC)
+ *
+ * http://creativecommons.org/licenses/by-nc/4.0/
+ *
+ * Short content:
+ * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
+ * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
+ * (Free for non-commercial use).
+ */
+
+import JQuiState from './JQuiState';
+import type { RxWidgetInfo, Writeable, RxWidgetInfoAttributesField } from '@iobroker/types-vis-2';
+
+class JQuiRadioSteps extends JQuiState {
+ static getWidgetInfo(): RxWidgetInfo {
+ const widgetInfo: RxWidgetInfo = JQuiState.getWidgetInfo();
+ const newWidgetInfo: RxWidgetInfo = {
+ id: 'tplJquiRadioSteps',
+ visSet: 'jqui',
+ visName: 'Radiobuttons 25%',
+ visWidgetLabel: 'jqui_radio_steps',
+ visPrev: 'widgets/jqui/img/Prev_RadioSteps.png',
+ visOrder: 25,
+ visAttrs: widgetInfo.visAttrs,
+ visDefaultStyle: {
+ width: 350,
+ height: 35,
+ },
+ };
+
+ // Add note
+ (newWidgetInfo.visAttrs[0].fields as Writeable).unshift({
+ name: '_note',
+ type: 'help',
+ text: 'jqui_state_note',
+ });
+
+ return newWidgetInfo;
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ getWidgetInfo(): RxWidgetInfo {
+ return JQuiRadioSteps.getWidgetInfo();
+ }
+}
+
+export default JQuiRadioSteps;
diff --git a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiSelectList.tsx b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiSelectList.tsx
index 654d9eb9..c81804ef 100644
--- a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiSelectList.tsx
+++ b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiSelectList.tsx
@@ -1,61 +1,61 @@
-/**
- * ioBroker.vis-2
- * https://github.com/ioBroker/ioBroker.vis-2
- *
- * Copyright (c) 2023-2024 Denis Haev https://github.com/GermanBluefox,
- * Creative Common Attribution-NonCommercial (CC BY-NC)
- *
- * http://creativecommons.org/licenses/by-nc/4.0/
- *
- * Short content:
- * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
- * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
- * (Free for non-commercial use).
- */
-
-import JQuiState from './JQuiState';
-import type {
- RxWidgetInfo,
- RxWidgetInfoAttributesField,
- RxWidgetInfoAttributesFieldSelect,
- Writeable,
-} from '@iobroker/types-vis-2';
-
-class JQuiSelectList extends JQuiState {
- static getWidgetInfo(): RxWidgetInfo {
- const widgetInfo = JQuiState.getWidgetInfo();
- const newWidgetInfo = {
- id: 'tplJquiSelectList',
- visSet: 'jqui',
- visName: 'Select ValueList',
- visWidgetLabel: 'jqui_select_list',
- visPrev: 'widgets/jqui/img/Prev_SelectList.png',
- visOrder: 16,
- visAttrs: widgetInfo.visAttrs,
- visDefaultStyle: {
- width: 250,
- height: 45,
- },
- };
-
- const type: Writeable =
- JQuiState.findField(newWidgetInfo, 'type');
- type.default = 'select';
-
- // Add note
- (newWidgetInfo.visAttrs[0].fields as Writeable).unshift({
- name: '_note',
- type: 'help',
- text: 'jqui_state_note',
- });
-
- return newWidgetInfo;
- }
-
- // eslint-disable-next-line class-methods-use-this
- getWidgetInfo(): RxWidgetInfo {
- return JQuiSelectList.getWidgetInfo();
- }
-}
-
-export default JQuiSelectList;
+/**
+ * ioBroker.vis-2
+ * https://github.com/ioBroker/ioBroker.vis-2
+ *
+ * Copyright (c) 2023-2025 Denis Haev https://github.com/GermanBluefox,
+ * Creative Common Attribution-NonCommercial (CC BY-NC)
+ *
+ * http://creativecommons.org/licenses/by-nc/4.0/
+ *
+ * Short content:
+ * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
+ * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
+ * (Free for non-commercial use).
+ */
+
+import JQuiState from './JQuiState';
+import type {
+ RxWidgetInfo,
+ RxWidgetInfoAttributesField,
+ RxWidgetInfoAttributesFieldSelect,
+ Writeable,
+} from '@iobroker/types-vis-2';
+
+class JQuiSelectList extends JQuiState {
+ static getWidgetInfo(): RxWidgetInfo {
+ const widgetInfo = JQuiState.getWidgetInfo();
+ const newWidgetInfo = {
+ id: 'tplJquiSelectList',
+ visSet: 'jqui',
+ visName: 'Select ValueList',
+ visWidgetLabel: 'jqui_select_list',
+ visPrev: 'widgets/jqui/img/Prev_SelectList.png',
+ visOrder: 16,
+ visAttrs: widgetInfo.visAttrs,
+ visDefaultStyle: {
+ width: 250,
+ height: 45,
+ },
+ };
+
+ const type: Writeable =
+ JQuiState.findField(newWidgetInfo, 'type');
+ type.default = 'select';
+
+ // Add note
+ (newWidgetInfo.visAttrs[0].fields as Writeable).unshift({
+ name: '_note',
+ type: 'help',
+ text: 'jqui_state_note',
+ });
+
+ return newWidgetInfo;
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ getWidgetInfo(): RxWidgetInfo {
+ return JQuiSelectList.getWidgetInfo();
+ }
+}
+
+export default JQuiSelectList;
diff --git a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiSlider.tsx b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiSlider.tsx
index 2449f3b9..e1df3d18 100644
--- a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiSlider.tsx
+++ b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiSlider.tsx
@@ -2,7 +2,7 @@
* ioBroker.vis-2
* https://github.com/ioBroker/ioBroker.vis-2
*
- * Copyright (c) 2023-2024 Denis Haev https://github.com/GermanBluefox,
+ * Copyright (c) 2023-2025 Denis Haev https://github.com/GermanBluefox,
* Creative Common Attribution-NonCommercial (CC BY-NC)
*
* http://creativecommons.org/licenses/by-nc/4.0/
diff --git a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiSliderVertical.tsx b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiSliderVertical.tsx
index 7879a894..3b4f5db6 100644
--- a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiSliderVertical.tsx
+++ b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiSliderVertical.tsx
@@ -1,58 +1,58 @@
-/**
- * ioBroker.vis-2
- * https://github.com/ioBroker/ioBroker.vis-2
- *
- * Copyright (c) 2023-2024 Denis Haev https://github.com/GermanBluefox,
- * Creative Common Attribution-NonCommercial (CC BY-NC)
- *
- * http://creativecommons.org/licenses/by-nc/4.0/
- *
- * Short content:
- * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
- * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
- * (Free for non-commercial use).
- */
-
-import JQuiSlider from './JQuiSlider';
-import type {
- RxWidgetInfo,
- RxWidgetInfoAttributesFieldSelect,
- Writeable,
- RxWidgetInfoAttributesField,
-} from '@iobroker/types-vis-2';
-
-class JQuiSliderVertical extends JQuiSlider {
- static getWidgetInfo(): RxWidgetInfo {
- const widgetInfo: RxWidgetInfo = JQuiSlider.getWidgetInfo();
- const newWidgetInfo: RxWidgetInfo = {
- id: 'tplJquiSliderVertical',
- visSet: 'jqui',
- visName: 'Vertical slider ',
- visWidgetLabel: 'jqui_slider_vertical',
- visPrev: 'widgets/jqui/img/Prev_SliderVertical.png',
- visOrder: 25,
- visAttrs: widgetInfo.visAttrs,
- visDefaultStyle: {
- width: 40,
- height: 300,
- },
- };
- (newWidgetInfo.visAttrs[0].fields as Writeable).unshift({
- name: '_note',
- type: 'help',
- text: 'jqui_slider_note',
- });
-
- const orientation = JQuiSlider.findField(newWidgetInfo, 'orientation');
- orientation.default = 'vertical';
-
- return newWidgetInfo;
- }
-
- // eslint-disable-next-line class-methods-use-this
- getWidgetInfo(): RxWidgetInfo {
- return JQuiSliderVertical.getWidgetInfo();
- }
-}
-
-export default JQuiSliderVertical;
+/**
+ * ioBroker.vis-2
+ * https://github.com/ioBroker/ioBroker.vis-2
+ *
+ * Copyright (c) 2023-2025 Denis Haev https://github.com/GermanBluefox,
+ * Creative Common Attribution-NonCommercial (CC BY-NC)
+ *
+ * http://creativecommons.org/licenses/by-nc/4.0/
+ *
+ * Short content:
+ * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
+ * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
+ * (Free for non-commercial use).
+ */
+
+import JQuiSlider from './JQuiSlider';
+import type {
+ RxWidgetInfo,
+ RxWidgetInfoAttributesFieldSelect,
+ Writeable,
+ RxWidgetInfoAttributesField,
+} from '@iobroker/types-vis-2';
+
+class JQuiSliderVertical extends JQuiSlider {
+ static getWidgetInfo(): RxWidgetInfo {
+ const widgetInfo: RxWidgetInfo = JQuiSlider.getWidgetInfo();
+ const newWidgetInfo: RxWidgetInfo = {
+ id: 'tplJquiSliderVertical',
+ visSet: 'jqui',
+ visName: 'Vertical slider ',
+ visWidgetLabel: 'jqui_slider_vertical',
+ visPrev: 'widgets/jqui/img/Prev_SliderVertical.png',
+ visOrder: 25,
+ visAttrs: widgetInfo.visAttrs,
+ visDefaultStyle: {
+ width: 40,
+ height: 300,
+ },
+ };
+ (newWidgetInfo.visAttrs[0].fields as Writeable).unshift({
+ name: '_note',
+ type: 'help',
+ text: 'jqui_slider_note',
+ });
+
+ const orientation = JQuiSlider.findField(newWidgetInfo, 'orientation');
+ orientation.default = 'vertical';
+
+ return newWidgetInfo;
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ getWidgetInfo(): RxWidgetInfo {
+ return JQuiSliderVertical.getWidgetInfo();
+ }
+}
+
+export default JQuiSliderVertical;
diff --git a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiState.tsx b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiState.tsx
index 647c6cc0..9d03ac6b 100644
--- a/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiState.tsx
+++ b/packages/iobroker.vis-2/src-vis/src/Vis/Widgets/JQui/JQuiState.tsx
@@ -1,907 +1,907 @@
-/**
- * ioBroker.vis-2
- * https://github.com/ioBroker/ioBroker.vis-2
- *
- * Copyright (c) 2023-2024 Denis Haev https://github.com/GermanBluefox,
- * Creative Common Attribution-NonCommercial (CC BY-NC)
- *
- * http://creativecommons.org/licenses/by-nc/4.0/
- *
- * Short content:
- * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
- * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
- * (Free for non-commercial use).
- */
-
-import React from 'react';
-
-import {
- Button,
- Tooltip,
- ButtonGroup,
- Radio,
- RadioGroup,
- FormControlLabel,
- MenuItem,
- Select,
- FormControl,
- InputLabel,
- FormLabel,
- Slider,
- List,
-} from '@mui/material';
-
-import { I18n, Icon, type LegacyConnection } from '@iobroker/adapter-react-v5';
-
-import VisBaseWidget from '@/Vis/visBaseWidget';
-import { deepClone } from '@/Utils/utils';
-
-import VisRxWidget, { type VisRxWidgetState } from '../../visRxWidget';
-import BulkEditor from './BulkEditor';
-import type {
- RxRenderWidgetProps,
- RxWidgetInfo,
- RxWidgetInfoAttributesField,
- RxWidgetInfoAttributesFieldCheckbox,
- RxWidgetInfoCustomComponentProperties,
- VisBaseWidgetProps,
- WidgetData,
- Writeable,
-} from '@iobroker/types-vis-2';
-
-interface BulkEditorData {
- variant?: 'outlined' | 'contained';
- type: 'select' | 'radio';
- oid: string;
- count: number;
- [colors: `color${number}`]: string;
- [values: `value${number}`]: string | number;
- [values: `text${number}`]: string;
- [values: `icon${number}`]: string | null;
- [values: `g_states-${number}`]: boolean;
- [values: `image${number}`]: string;
- [values: `activeColor${number}`]: string;
- [values: `tooltip${number}`]: string;
-}
-
-type RxData = {
- oid: string;
- count: number;
-
- type: 'button' | 'select' | 'radio' | 'slider';
- readOnly: boolean;
- click_id: string;
- variant: 'contained' | 'outlined' | 'text' | 'standard';
- orientation: 'horizontal' | 'vertical';
- widgetTitle: string;
- timeout: number;
- open: boolean;
-
- [key: `value${number}`]: string | number;
- [key: `color${number}`]: string;
- [key: `text${number}`]: string;
- [key: `icon${number}`]: string | null;
- [key: `g_states-${number}`]: boolean;
- [key: `image${number}`]: string;
- [key: `activeColor${number}`]: string;
- [key: `tooltip${number}`]: string;
-
- [key: `onlyIcon${number}`]: boolean;
- [key: `test${number}`]: boolean;
-};
-
-interface JQuiStateState extends VisRxWidgetState {
- value: string | number | boolean;
- object: ioBroker.StateObject | null | false;
-}
-
-class JQuiState extends VisRxWidget
{
- private controlTimeout: ReturnType | null = null;
-
- constructor(props: VisBaseWidgetProps) {
- super(props);
- Object.assign(this.state, {
- value: '',
- object: null,
- });
- }
-
- static getWidgetInfo(): RxWidgetInfo {
- return {
- id: 'tplJquiButtonState',
- visSet: 'jqui',
- visName: 'States control',
- visWidgetLabel: 'jqui_states_control',
- visPrev: 'widgets/jqui/img/Prev_ButtonState.png',
- visOrder: 14,
- visAttrs: [
- {
- name: 'common',
- fields: [
- {
- name: 'type',
- label: 'jqui_type',
- type: 'select',
- noTranslation: true,
- default: 'button',
- options: ['button', 'select', 'radio', 'slider'],
- },
- {
- name: 'oid',
- type: 'id',
- onChange: async (
- _field: RxWidgetInfoAttributesField,
- data: RxData,
- changeData: (newData: RxData) => void,
- socket: LegacyConnection,
- ): Promise => {
- if (data.oid) {
- // unknown bug by compilation
- if (await (BulkEditor.generateFields as any)(data, socket)) {
- changeData(data);
- }
- }
- },
- },
- {
- name: 'readOnly',
- type: 'checkbox',
- },
- {
- name: 'click_id',
- type: 'id',
- noSubscribe: true,
- hidden: (data: Record): boolean => !!data.readOnly,
- },
- {
- name: 'count',
- type: 'slider',
- min: 0,
- default: 1,
- max: 10,
- hidden: (data: Record): boolean => !!data.percents,
- },
- {
- type: 'custom',
- component: (
- _field: RxWidgetInfoAttributesField,
- data: WidgetData,
- onDataChange: (newData: WidgetData) => void,
- props: RxWidgetInfoCustomComponentProperties,
- ) => (
-
- ),
- },
- {
- name: 'variant',
- label: 'jqui_variant',
- type: 'select',
- noTranslation: true,
- options: ['contained', 'outlined', 'text', 'standard'],
- default: 'contained',
- hidden: (data: Record): boolean =>
- data.type !== 'button' && data.type !== 'select',
- },
- {
- name: 'orientation',
- label: 'orientation',
- type: 'select',
- options: ['horizontal', 'vertical'],
- default: 'horizontal',
- hidden: (data: Record): boolean =>
- data.type !== 'button' && data.type !== 'slider',
- },
- {
- name: 'widgetTitle',
- label: 'jqui_name',
- type: 'text',
- },
- {
- name: 'timeout',
- label: 'jqui_set_timeout',
- type: 'number',
- hidden: (data: Record): boolean => data.type !== 'slider',
- },
- {
- name: 'open',
- label: 'jqui_open',
- type: 'checkbox',
- hidden: (data: Record): boolean => data.type !== 'select',
- },
- ],
- },
- {
- name: 'states',
- label: 'jqui_group_value',
- indexFrom: 1,
- indexTo: 'count',
- hidden: (data: Record): boolean => !!data.percents,
- fields: [
- {
- name: 'value',
- type: 'text',
- label: 'jqui_value',
- default: '0',
- },
- {
- name: 'test',
- type: 'checkbox',
- label: 'jqui_test',
- onChange: (
- field: RxWidgetInfoAttributesField,
- data: Record,
- changeData: (newData: Record) => void,
- _socket: LegacyConnection,
- index?: number,
- ): Promise => {
- if (data[(field as RxWidgetInfoAttributesFieldCheckbox).name]) {
- let changed = false;
- // deactivate all other tests
- for (let i = 1; i <= data.count; i++) {
- if (i !== index) {
- if (data[`test${i}`]) {
- changed = true;
- data[`test${i}`] = false;
- }
- }
- }
- changed && changeData(data);
- }
- return Promise.resolve();
- },
- hidden: (data, index) =>
- data.type === 'slider' ||
- data[`value${index}`] === '' ||
- data[`value${index}`] === null ||
- data[`value${index}`] === undefined,
- },
- {
- name: 'onlyIcon',
- type: 'checkbox',
- label: 'jqui_only_icon',
- },
- {
- name: 'text',
- default: I18n.t('Value'),
- type: 'text',
- label: 'jqui_text',
- hidden: (data, index) =>
- !!data[`onlyIcon${index}`] ||
- data[`value${index}`] === '' ||
- data[`value${index}`] === null ||
- data[`value${index}`] === undefined,
- },
- {
- name: 'color',
- type: 'color',
- label: 'color',
- hidden: (data, index) =>
- data.type === 'slider' ||
- data[`value${index}`] === '' ||
- data[`value${index}`] === null ||
- data[`value${index}`] === undefined,
- },
- {
- name: 'activeColor',
- type: 'color',
- label: 'jqui_active_color',
- hidden: (data, index) =>
- data.type === 'slider' ||
- data[`value${index}`] === '' ||
- data[`value${index}`] === null ||
- data[`value${index}`] === undefined,
- },
- {
- name: 'image',
- label: 'jqui_image',
- type: 'image',
- hidden: (data, index) =>
- data.type === 'slider' ||
- !!data.icon ||
- data[`value${index}`] === '' ||
- data[`value${index}`] === null ||
- data[`value${index}`] === undefined,
- },
- {
- name: 'icon',
- label: 'jqui_icon',
- type: 'icon64',
- hidden: (data, index) =>
- data.type === 'slider' ||
- !!data.image ||
- data[`value${index}`] === '' ||
- data[`value${index}`] === null ||
- data[`value${index}`] === undefined,
- },
- {
- name: 'tooltip',
- label: 'jqui_tooltip',
- type: 'text',
- hidden: (data, index) =>
- data.type === 'slider' ||
- data[`value${index}`] === '' ||
- data[`value${index}`] === null ||
- data[`value${index}`] === undefined,
- },
- ],
- },
- ],
- visDefaultStyle: {
- width: 300,
- height: 45,
- },
- };
- }
-
- async componentDidMount(): Promise {
- super.componentDidMount();
-
- // convert old tplJquiRadioSteps data to JquiState data
- if (
- this.props.tpl === 'tplJquiRadioSteps' &&
- this.state.data &&
- this.props.context.onWidgetsChanged &&
- this.state.data.count === undefined
- ) {
- const data = deepClone(this.state.data);
-
- data.count = 5;
- const min = parseFloat(data.min || 0);
- const max = parseFloat(data.max || 100);
-
- data.value1 = min;
- data.text1 = I18n.t('jqui_off');
- data['g_states-1'] = true;
-
- data.value5 = max;
- data.text5 = '100%';
- data['g_states-5'] = true;
-
- data.value2 = (max - min) * 0.25 + min;
- data.text2 = '25%';
- data['g_states-2'] = true;
-
- data.value3 = (max - min) * 0.5 + min;
- data.text3 = '50%';
- data['g_states-3'] = true;
-
- data.value4 = (max - min) * 0.75 + min;
- data.text4 = '75%';
- data['g_states-4'] = true;
-
- data.min = null;
- data.max = null;
-
- setTimeout(
- () =>
- this.props.context.onWidgetsChanged([
- {
- wid: this.props.id,
- view: this.props.view,
- data,
- },
- ]),
- 100,
- );
- }
-
- // convert old tplJquiRadioList data to JquiState data
- if (
- (this.props.tpl === 'tplJquiRadioList' || this.props.tpl === 'tplJquiSelectList') &&
- this.state.data &&
- this.state.data.values &&
- this.state.data.texts &&
- this.props.context.onWidgetsChanged
- ) {
- // convert
- const values = this.state.data.values.split(';');
- const texts = this.state.data.texts.split(';');
- const data = deepClone(this.state.data);
- data.values = null;
- data.texts = null;
- data.count = values.length;
- for (let i = 1; i <= values.length; i++) {
- data[`value${i}`] = values[i - 1];
- data[`text${i}`] = texts[i - 1];
- data[`g_states-${i}`] = true;
- }
- data.type = this.props.tpl === 'tplJquiRadioList' ? 'radio' : 'select';
- if (this.props.context.onWidgetsChanged) {
- setTimeout(
- () =>
- this.props.context.onWidgetsChanged([
- {
- wid: this.props.id,
- view: this.props.view,
- data,
- },
- ]),
- 100,
- );
- }
- }
-
- if (this.state.rxData.oid && this.state.rxData.oid !== 'nothing_selected') {
- try {
- const state = await this.props.context.socket.getState(this.state.rxData.oid);
- this.onStateUpdated(this.state.rxData.oid, state);
- } catch (error) {
- console.error(`Cannot get state ${this.state.rxData.oid}: ${error}`);
- }
- }
- }
-
- componentWillUnmount(): void {
- super.componentWillUnmount();
- if (this.controlTimeout) {
- clearTimeout(this.controlTimeout);
- this.controlTimeout = null;
- }
- }
-
- static findField(
- widgetInfo: RxWidgetInfo,
- name: string,
- ): Writeable | null {
- return VisRxWidget.findField(widgetInfo, name) as unknown as Writeable;
- }
-
- // eslint-disable-next-line class-methods-use-this
- getWidgetInfo(): RxWidgetInfo {
- return JQuiState.getWidgetInfo();
- }
-
- onStateUpdated(id: string, state: ioBroker.State): void {
- if (id === this.state.rxData.oid && state) {
- const value = state.val === null || state.val === undefined ? '' : state.val;
-
- if (this.state.value !== value.toString()) {
- this.setState({ value: value.toString() });
- }
- }
- }
-
- getControlOid(): string {
- if (this.state.rxData.click_id && this.state.rxData.click_id !== 'nothing_selected') {
- return this.state.rxData.click_id;
- }
- if (this.state.rxData.oid && this.state.rxData.oid !== 'nothing_selected') {
- return this.state.rxData.oid;
- }
- return '';
- }
-
- onClick(indexOrValue: string | number, immediately?: boolean): void {
- if (this.state.rxData.readOnly || this.props.editMode) {
- return;
- }
-
- if (this.state.rxData.type === 'slider') {
- if (this.controlTimeout) {
- clearTimeout(this.controlTimeout);
- }
- this.controlTimeout = setTimeout(
- () => {
- this.controlTimeout = null;
- const oid = this.getControlOid();
- if (oid) {
- this.props.context.setValue(oid, parseFloat(indexOrValue as string));
- }
- },
- immediately ? 0 : parseInt(this.state.rxData.timeout as unknown as string, 10) || 300,
- );
- this.setState({ value: indexOrValue });
- } else {
- const oid = this.getControlOid();
- if (oid) {
- if (typeof this.state.object === 'object' && this.state.object?.common.type === 'number') {
- this.props.context.setValue(
- oid,
- parseFloat(this.state.rxData[`value${indexOrValue as number}`] as string),
- );
- } else {
- this.props.context.setValue(oid, this.state.rxData[`value${indexOrValue as number}`]);
- }
- }
- this.setState({ value: this.state.rxData[`value${indexOrValue as number}`] });
- }
- }
-
- getSelectedIndex(value?: string | number | boolean): number {
- if (value === undefined) {
- value = this.state.value;
- }
-
- if (this.props.editMode) {
- for (let i = 1; i <= this.state.rxData.count; i++) {
- if ((this.state.rxData as unknown as Record)[`test${i}`]) {
- return i;
- }
- }
- }
- for (let i = 1; i <= this.state.rxData.count; i++) {
- if ((this.state.rxData as unknown as Record)[`value${i}`] === value) {
- return i;
- }
- }
- return 0;
- }
-
- renderIcon(i: number, selectedIndex: number): React.JSX.Element | null {
- let color: string;
- const rxData = this.state.rxData as unknown as Record;
- let icon: string = rxData[`icon${i}`] || rxData[`image${i}`];
- if (icon && rxData[`color${i}`]) {
- color = rxData[`color${i}`];
- if (i === selectedIndex && rxData[`activeColor${i}`]) {
- color = rxData[`activeColor${i}`];
- }
- }
-
- if (icon) {
- if (icon.startsWith('_PRJ_NAME/')) {
- icon = icon.replace(
- '_PRJ_NAME/',
- `../${this.props.context.adapterName}.${this.props.context.instance}/${this.props.context.projectName}/`,
- );
- }
- const style: React.CSSProperties = { color };
- style.width = 'auto';
- style.height = 24;
-
- return (
-
- );
- }
- return null;
- }
-
- renderText(i: number, selectedIndex: number): React.JSX.Element | null {
- const rxData = this.state.rxData as unknown as Record;
- if (rxData[`onlyIcon${i}`]) {
- return null;
- }
- let text = rxData[`text${i}`];
- let color = rxData[`color${i}`];
- if (i === selectedIndex && rxData[`activeColor${i}`]) {
- color = rxData[`activeColor${i}`];
- }
-
- text = text || rxData[`value${i}`];
-
- return {text};
- }
-
- renderButton(i: number, selectedIndex: number, buttonStyle?: React.CSSProperties): React.JSX.Element | null {
- const rxData = this.state.rxData as unknown as Record;
- const icon = this.renderIcon(i, selectedIndex);
- const text = this.renderText(i, selectedIndex);
-
- // Button
- const button = (
-
- );
-
- if (rxData[`tooltip${i}`]) {
- return (
-
- {button}
-
- );
- }
-
- return button;
- }
-
- renderRadio(i: number, selectedIndex: number, buttonStyle?: React.CSSProperties): React.JSX.Element {
- const rxData = this.state.rxData as unknown as Record;
- const icon = this.renderIcon(i, selectedIndex);
- let text = this.renderText(i, selectedIndex);
-
- if (icon && text) {
- text = (
-
- {icon}
- {text}
-
- );
- }
-
- // Button
- const button = (
- this.onClick(i)}
- checked={selectedIndex === i}
- />
- }
- labelPlacement="end"
- label={text || icon}
- />
- );
-
- if (rxData[`tooltip${i}`]) {
- return (
-
- {button}
-
- );
- }
- return button;
- }
-
- renderMenuItem(i: number, selectedIndex: number, buttonStyle?: React.CSSProperties): React.JSX.Element {
- const rxData = this.state.rxData as unknown as Record;
- const icon = this.renderIcon(i, selectedIndex);
- let text = this.renderText(i, selectedIndex);
-
- if (icon && text) {
- text = (
-
- {icon}
- {text}
-
- );
- }
-
- // Button
- return (
-
- );
- }
-
- renderWidgetBody(props: RxRenderWidgetProps): React.JSX.Element {
- super.renderWidgetBody(props);
- const selectedIndex = this.getSelectedIndex();
- const rxData = this.state.rxData as unknown as Record;
-
- if ((this.state.object as ioBroker.StateObject)?._id !== this.state.rxData.oid && this.state.object !== false) {
- Object.assign(this.state, { object: false });
- setTimeout(async () => {
- if (this.state.rxData.oid && this.state.rxData.oid !== 'nothing_selected') {
- const obj = await this.props.context.socket.getObject(this.state.rxData.oid);
- if (obj?.common?.type) {
- this.setState({
- object: {
- _id: obj._id,
- common: { type: obj.common.type } as ioBroker.StateCommon,
- type: 'state',
- native: {},
- },
- });
- return;
- }
- }
- this.setState({
- object: {
- _id: this.state.rxData.oid,
- common: { type: 'string' } as ioBroker.StateCommon,
- type: 'state',
- native: {},
- },
- });
- }, 0);
- }
-
- const buttonStyle: React.CSSProperties = {};
- // apply style from the element
- Object.keys(this.state.rxStyle).forEach(attr => {
- const value = rxData[attr];
- if (value !== null && value !== undefined && VisRxWidget.POSSIBLE_MUI_STYLES.includes(attr)) {
- attr = attr.replace(/(-\w)/g, text => text[1].toUpperCase());
- (buttonStyle as unknown as Record)[attr] = value;
- }
- });
- buttonStyle.minWidth = 'unset';
- if (buttonStyle.borderWidth) {
- buttonStyle.borderWidth = VisBaseWidget.correctStylePxValue(buttonStyle.borderWidth);
- }
- if (buttonStyle.fontSize) {
- buttonStyle.fontSize = VisBaseWidget.correctStylePxValue(buttonStyle.fontSize);
- }
-
- let content;
- if (
- (!this.state.rxData.count ||
- (this.state.rxData.count === 1 && !rxData.text0 && !rxData.icon0 && !rxData.image0)) &&
- (!this.state.rxData.oid || this.state.rxData.oid === 'nothing_selected')
- ) {
- content = (
-
- );
- } else if (!this.state.rxData.count) {
- content = (
-
- );
- } else if (this.state.rxData.type === 'radio') {
- const buttons = [];
- for (let i = 1; i <= this.state.rxData.count; i++) {
- buttons.push(this.renderRadio(i, selectedIndex, buttonStyle));
- }
-
- content = {buttons};
- } else if (this.state.rxData.type === 'select') {
- const buttons = [];
- for (let i = 1; i <= this.state.rxData.count; i++) {
- buttons.push(this.renderMenuItem(i, selectedIndex, buttonStyle));
- }
-
- let variant: 'standard' | 'filled' | 'outlined' = 'standard';
- if (this.state.rxData.variant === 'contained') {
- variant = 'filled';
- } else if (this.state.rxData.variant === 'outlined') {
- variant = 'outlined';
- }
-
- if (this.state.rxData.open) {
- content = {buttons}
;
- } else {
- content = (
-
- );
- }
- } else if (this.state.rxData.type === 'slider') {
- props.style.overflow = 'visible';
- const marks = [];
- for (let i = 1; i <= this.state.rxData.count; i++) {
- marks.push({
- value: parseFloat(rxData[`value${i}`]) || 0,
- label: rxData[`text${i}`] || 0,
- });
- }
-
- content = (
- this.onClick(value, true)}
- onChange={(_e, value: number) => this.onClick(value)}
- />
- );
- } else {
- const buttons = [];
- for (let i = 1; i <= this.state.rxData.count; i++) {
- buttons.push(this.renderButton(i, selectedIndex, buttonStyle));
- }
-
- content = (
-
- {buttons}
-
- );
- }
-
- if (this.state.rxData.widgetTitle) {
- content = (
-
- {this.state.rxData.type === 'select' ? (
- {this.state.rxData.widgetTitle}
- ) : (
-
- {this.state.rxData.widgetTitle}
-
- )}
- {content}
-
- );
- }
-
- return {content}
;
- }
-}
-
-export default JQuiState;
+/**
+ * ioBroker.vis-2
+ * https://github.com/ioBroker/ioBroker.vis-2
+ *
+ * Copyright (c) 2023-2025 Denis Haev https://github.com/GermanBluefox,
+ * Creative Common Attribution-NonCommercial (CC BY-NC)
+ *
+ * http://creativecommons.org/licenses/by-nc/4.0/
+ *
+ * Short content:
+ * Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
+ * Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for noncommercial purposes.
+ * (Free for non-commercial use).
+ */
+
+import React from 'react';
+
+import {
+ Button,
+ Tooltip,
+ ButtonGroup,
+ Radio,
+ RadioGroup,
+ FormControlLabel,
+ MenuItem,
+ Select,
+ FormControl,
+ InputLabel,
+ FormLabel,
+ Slider,
+ List,
+} from '@mui/material';
+
+import { I18n, Icon, type LegacyConnection } from '@iobroker/adapter-react-v5';
+
+import VisBaseWidget from '@/Vis/visBaseWidget';
+import { deepClone } from '@/Utils/utils';
+
+import VisRxWidget, { type VisRxWidgetState } from '../../visRxWidget';
+import BulkEditor from './BulkEditor';
+import type {
+ RxRenderWidgetProps,
+ RxWidgetInfo,
+ RxWidgetInfoAttributesField,
+ RxWidgetInfoAttributesFieldCheckbox,
+ RxWidgetInfoCustomComponentProperties,
+ VisBaseWidgetProps,
+ WidgetData,
+ Writeable,
+} from '@iobroker/types-vis-2';
+
+interface BulkEditorData {
+ variant?: 'outlined' | 'contained';
+ type: 'select' | 'radio';
+ oid: string;
+ count: number;
+ [colors: `color${number}`]: string;
+ [values: `value${number}`]: string | number;
+ [values: `text${number}`]: string;
+ [values: `icon${number}`]: string | null;
+ [values: `g_states-${number}`]: boolean;
+ [values: `image${number}`]: string;
+ [values: `activeColor${number}`]: string;
+ [values: `tooltip${number}`]: string;
+}
+
+type RxData = {
+ oid: string;
+ count: number;
+
+ type: 'button' | 'select' | 'radio' | 'slider';
+ readOnly: boolean;
+ click_id: string;
+ variant: 'contained' | 'outlined' | 'text' | 'standard';
+ orientation: 'horizontal' | 'vertical';
+ widgetTitle: string;
+ timeout: number;
+ open: boolean;
+
+ [key: `value${number}`]: string | number;
+ [key: `color${number}`]: string;
+ [key: `text${number}`]: string;
+ [key: `icon${number}`]: string | null;
+ [key: `g_states-${number}`]: boolean;
+ [key: `image${number}`]: string;
+ [key: `activeColor${number}`]: string;
+ [key: `tooltip${number}`]: string;
+
+ [key: `onlyIcon${number}`]: boolean;
+ [key: `test${number}`]: boolean;
+};
+
+interface JQuiStateState extends VisRxWidgetState {
+ value: string | number | boolean;
+ object: ioBroker.StateObject | null | false;
+}
+
+class JQuiState extends VisRxWidget
{
+ private controlTimeout: ReturnType | null = null;
+
+ constructor(props: VisBaseWidgetProps) {
+ super(props);
+ Object.assign(this.state, {
+ value: '',
+ object: null,
+ });
+ }
+
+ static getWidgetInfo(): RxWidgetInfo {
+ return {
+ id: 'tplJquiButtonState',
+ visSet: 'jqui',
+ visName: 'States control',
+ visWidgetLabel: 'jqui_states_control',
+ visPrev: 'widgets/jqui/img/Prev_ButtonState.png',
+ visOrder: 14,
+ visAttrs: [
+ {
+ name: 'common',
+ fields: [
+ {
+ name: 'type',
+ label: 'jqui_type',
+ type: 'select',
+ noTranslation: true,
+ default: 'button',
+ options: ['button', 'select', 'radio', 'slider'],
+ },
+ {
+ name: 'oid',
+ type: 'id',
+ onChange: async (
+ _field: RxWidgetInfoAttributesField,
+ data: RxData,
+ changeData: (newData: RxData) => void,
+ socket: LegacyConnection,
+ ): Promise => {
+ if (data.oid) {
+ // unknown bug by compilation
+ if (await (BulkEditor.generateFields as any)(data, socket)) {
+ changeData(data);
+ }
+ }
+ },
+ },
+ {
+ name: 'readOnly',
+ type: 'checkbox',
+ },
+ {
+ name: 'click_id',
+ type: 'id',
+ noSubscribe: true,
+ hidden: (data: Record): boolean => !!data.readOnly,
+ },
+ {
+ name: 'count',
+ type: 'slider',
+ min: 0,
+ default: 1,
+ max: 10,
+ hidden: (data: Record): boolean => !!data.percents,
+ },
+ {
+ type: 'custom',
+ component: (
+ _field: RxWidgetInfoAttributesField,
+ data: WidgetData,
+ onDataChange: (newData: WidgetData) => void,
+ props: RxWidgetInfoCustomComponentProperties,
+ ) => (
+
+ ),
+ },
+ {
+ name: 'variant',
+ label: 'jqui_variant',
+ type: 'select',
+ noTranslation: true,
+ options: ['contained', 'outlined', 'text', 'standard'],
+ default: 'contained',
+ hidden: (data: Record): boolean =>
+ data.type !== 'button' && data.type !== 'select',
+ },
+ {
+ name: 'orientation',
+ label: 'orientation',
+ type: 'select',
+ options: ['horizontal', 'vertical'],
+ default: 'horizontal',
+ hidden: (data: Record): boolean =>
+ data.type !== 'button' && data.type !== 'slider',
+ },
+ {
+ name: 'widgetTitle',
+ label: 'jqui_name',
+ type: 'text',
+ },
+ {
+ name: 'timeout',
+ label: 'jqui_set_timeout',
+ type: 'number',
+ hidden: (data: Record): boolean => data.type !== 'slider',
+ },
+ {
+ name: 'open',
+ label: 'jqui_open',
+ type: 'checkbox',
+ hidden: (data: Record): boolean => data.type !== 'select',
+ },
+ ],
+ },
+ {
+ name: 'states',
+ label: 'jqui_group_value',
+ indexFrom: 1,
+ indexTo: 'count',
+ hidden: (data: Record): boolean => !!data.percents,
+ fields: [
+ {
+ name: 'value',
+ type: 'text',
+ label: 'jqui_value',
+ default: '0',
+ },
+ {
+ name: 'test',
+ type: 'checkbox',
+ label: 'jqui_test',
+ onChange: (
+ field: RxWidgetInfoAttributesField,
+ data: Record,
+ changeData: (newData: Record) => void,
+ _socket: LegacyConnection,
+ index?: number,
+ ): Promise => {
+ if (data[(field as RxWidgetInfoAttributesFieldCheckbox).name]) {
+ let changed = false;
+ // deactivate all other tests
+ for (let i = 1; i <= data.count; i++) {
+ if (i !== index) {
+ if (data[`test${i}`]) {
+ changed = true;
+ data[`test${i}`] = false;
+ }
+ }
+ }
+ changed && changeData(data);
+ }
+ return Promise.resolve();
+ },
+ hidden: (data, index) =>
+ data.type === 'slider' ||
+ data[`value${index}`] === '' ||
+ data[`value${index}`] === null ||
+ data[`value${index}`] === undefined,
+ },
+ {
+ name: 'onlyIcon',
+ type: 'checkbox',
+ label: 'jqui_only_icon',
+ },
+ {
+ name: 'text',
+ default: I18n.t('Value'),
+ type: 'text',
+ label: 'jqui_text',
+ hidden: (data, index) =>
+ !!data[`onlyIcon${index}`] ||
+ data[`value${index}`] === '' ||
+ data[`value${index}`] === null ||
+ data[`value${index}`] === undefined,
+ },
+ {
+ name: 'color',
+ type: 'color',
+ label: 'color',
+ hidden: (data, index) =>
+ data.type === 'slider' ||
+ data[`value${index}`] === '' ||
+ data[`value${index}`] === null ||
+ data[`value${index}`] === undefined,
+ },
+ {
+ name: 'activeColor',
+ type: 'color',
+ label: 'jqui_active_color',
+ hidden: (data, index) =>
+ data.type === 'slider' ||
+ data[`value${index}`] === '' ||
+ data[`value${index}`] === null ||
+ data[`value${index}`] === undefined,
+ },
+ {
+ name: 'image',
+ label: 'jqui_image',
+ type: 'image',
+ hidden: (data, index) =>
+ data.type === 'slider' ||
+ !!data.icon ||
+ data[`value${index}`] === '' ||
+ data[`value${index}`] === null ||
+ data[`value${index}`] === undefined,
+ },
+ {
+ name: 'icon',
+ label: 'jqui_icon',
+ type: 'icon64',
+ hidden: (data, index) =>
+ data.type === 'slider' ||
+ !!data.image ||
+ data[`value${index}`] === '' ||
+ data[`value${index}`] === null ||
+ data[`value${index}`] === undefined,
+ },
+ {
+ name: 'tooltip',
+ label: 'jqui_tooltip',
+ type: 'text',
+ hidden: (data, index) =>
+ data.type === 'slider' ||
+ data[`value${index}`] === '' ||
+ data[`value${index}`] === null ||
+ data[`value${index}`] === undefined,
+ },
+ ],
+ },
+ ],
+ visDefaultStyle: {
+ width: 300,
+ height: 45,
+ },
+ };
+ }
+
+ async componentDidMount(): Promise {
+ super.componentDidMount();
+
+ // convert old tplJquiRadioSteps data to JquiState data
+ if (
+ this.props.tpl === 'tplJquiRadioSteps' &&
+ this.state.data &&
+ this.props.context.onWidgetsChanged &&
+ this.state.data.count === undefined
+ ) {
+ const data = deepClone(this.state.data);
+
+ data.count = 5;
+ const min = parseFloat(data.min || 0);
+ const max = parseFloat(data.max || 100);
+
+ data.value1 = min;
+ data.text1 = I18n.t('jqui_off');
+ data['g_states-1'] = true;
+
+ data.value5 = max;
+ data.text5 = '100%';
+ data['g_states-5'] = true;
+
+ data.value2 = (max - min) * 0.25 + min;
+ data.text2 = '25%';
+ data['g_states-2'] = true;
+
+ data.value3 = (max - min) * 0.5 + min;
+ data.text3 = '50%';
+ data['g_states-3'] = true;
+
+ data.value4 = (max - min) * 0.75 + min;
+ data.text4 = '75%';
+ data['g_states-4'] = true;
+
+ data.min = null;
+ data.max = null;
+
+ setTimeout(
+ () =>
+ this.props.context.onWidgetsChanged([
+ {
+ wid: this.props.id,
+ view: this.props.view,
+ data,
+ },
+ ]),
+ 100,
+ );
+ }
+
+ // convert old tplJquiRadioList data to JquiState data
+ if (
+ (this.props.tpl === 'tplJquiRadioList' || this.props.tpl === 'tplJquiSelectList') &&
+ this.state.data &&
+ this.state.data.values &&
+ this.state.data.texts &&
+ this.props.context.onWidgetsChanged
+ ) {
+ // convert
+ const values = this.state.data.values.split(';');
+ const texts = this.state.data.texts.split(';');
+ const data = deepClone(this.state.data);
+ data.values = null;
+ data.texts = null;
+ data.count = values.length;
+ for (let i = 1; i <= values.length; i++) {
+ data[`value${i}`] = values[i - 1];
+ data[`text${i}`] = texts[i - 1];
+ data[`g_states-${i}`] = true;
+ }
+ data.type = this.props.tpl === 'tplJquiRadioList' ? 'radio' : 'select';
+ if (this.props.context.onWidgetsChanged) {
+ setTimeout(
+ () =>
+ this.props.context.onWidgetsChanged([
+ {
+ wid: this.props.id,
+ view: this.props.view,
+ data,
+ },
+ ]),
+ 100,
+ );
+ }
+ }
+
+ if (this.state.rxData.oid && this.state.rxData.oid !== 'nothing_selected') {
+ try {
+ const state = await this.props.context.socket.getState(this.state.rxData.oid);
+ this.onStateUpdated(this.state.rxData.oid, state);
+ } catch (error) {
+ console.error(`Cannot get state ${this.state.rxData.oid}: ${error}`);
+ }
+ }
+ }
+
+ componentWillUnmount(): void {
+ super.componentWillUnmount();
+ if (this.controlTimeout) {
+ clearTimeout(this.controlTimeout);
+ this.controlTimeout = null;
+ }
+ }
+
+ static findField