/* eslint-disable react-refresh/only-export-components */ import $ from 'jquery'; import React from 'react'; import ReactDOM from 'react-dom/client'; import Notification from 'vj/components/notification'; import { i18n, tpl } from 'vj/utils'; import DomainSelectAutoComplete from '../autocomplete/components/DomainSelectAutoComplete'; import UserSelectAutoComplete from '../autocomplete/components/UserSelectAutoComplete'; import DomDialog, { DialogOptions } from './DomDialog'; export class Dialog { options: DialogOptions; $dom: JQuery; domDialogInstance: DomDialog; constructor(options: Partial = {}) { this.options = { classes: '', $body: null, $action: null, ...options, }; const box: React.CSSProperties = {}; if (options.width) box.width = box.maxWidth = options.width; if (options.height) box.height = box.maxHeight = options.height; this.$dom = $(tpl(
, )); this.$dom.on('click', '[data-action]', this.handleActionButton.bind(this)); this.$dom.on('vjDomDialogShow', this.beforeShow.bind(this)); this.$dom.on('vjDomDialogHidden', this.afterHide.bind(this)); this.$dom.find('.dialog__body').append(this.options.$body); this.$dom.find('.dialog__action').append(this.options.$action); this.domDialogInstance = new DomDialog(this.$dom, this.options); } beforeShow() { this.$dom.appendTo('body'); } afterHide() { this.$dom.detach(); } open() { return this.domDialogInstance.show(); } close() { return this.domDialogInstance.hide(); } handleActionButton(ev) { this.domDialogInstance.dispatchAction($(ev.currentTarget).attr('data-action')); } } export default Dialog; const buttonOk = tpl``; const buttonCancel = tpl``; const buttonYes = tpl``; const buttonNo = tpl``; export class InfoDialog extends Dialog { constructor(options: Partial = {}) { super({ $action: buttonOk, cancelByClickingBack: true, cancelByEsc: true, ...options, }); } } export class ActionDialog extends Dialog { constructor(options: Partial = {}) { super({ $action: [buttonCancel, buttonOk].join('\n'), cancelByClickingBack: true, cancelByEsc: true, ...options, }); } clear() { this.$dom.find('input').val(''); return this; } } export class ConfirmDialog extends Dialog { constructor(options: Partial = {}) { let buttons = []; if (options.canCancel) { buttons = [buttonCancel, buttonNo, buttonYes]; } else { buttons = [buttonNo, buttonYes]; } super({ $action: buttons.join('\n'), cancelByClickingBack: options.canCancel, cancelByEsc: options.canCancel, ...options, }); } } export interface Field { type: 'text' | 'textarea' | 'checkbox' | 'user' | 'userId' | 'username' | 'domain'; options?: string[] | Record; placeholder?: string; label?: string; autofocus?: boolean; required?: boolean; default?: string; columns?: number; rows?: number; multi?: boolean; } type Result> = { [K in keyof R]: R[K]['type'] extends ('text' | 'password' | 'username' | 'domain' | 'textarea') ? string : R[K]['type'] extends 'checkbox' ? boolean : R[K]['type'] extends 'userId' ? number : R[K]['type'] extends 'user' ? any : never; }; interface PromptOptions { cancelByClickingBack: boolean; cancelByEsc: boolean; } export async function prompt>(title: string, fields: R, options?: PromptOptions): Promise> { let valueCache: Result = {} as any; const defaultValues = Object.fromEntries(Object.entries(fields) .map(([name, field]: [T, Field]) => { let firstOption = ''; if (field.options) { if (Array.isArray(field.options)) firstOption = field.options[0]; else firstOption = Object.keys(field.options)[0]; } return [name, field.default || firstOption || '']; })) as Result; const layout: [string, Field][][] = []; let pending: [string, Field][] = []; for (const [name, field] of Object.entries(fields) as [T, Field][]) { pending.push([name, field]); if ((field.columns || -12) < 0) { layout.push(pending); pending = []; } } if (pending.length > 0) layout.push(pending); const Component = () => { const [values, setValues] = React.useState(defaultValues); const [selected, setSelected] = React.useState>>({}); const refs = React.useRef>>>({}); React.useEffect(() => { valueCache = values; }, [values]); return

{title}

{layout.map((i) =>
{i.map(([name, field]: [string, Field]) =>
{field.type === 'textarea' &&