import { addResizeObserver, AppsState, DataExtensionState, DefaultPermissionsConfig, ExtendedFields, Fqdn, fqdnToString, TaskState, WixPatternsContainer, WixPatternsError, } from '@wix/bex-core'; import { SidePanelsState } from '../SidePanelsState'; import { action, computed, makeObservable, observable } from 'mobx'; import type * as CustomFieldsWidgetLazyContent from '../../components/CustomFieldsWidget/CustomFieldsWidgetLazyContent'; import { cairoErrorInLoadingAComponent, cairoTryAgainClicked, loadEnd, loadStart, } from '@wix/bex-core/bi'; import { CustomFieldsAllNamespacesFormState } from './CustomFieldsAllNamespacesFormState'; import { CustomFieldsPanelState } from './CustomFieldsPanelState'; import { dataExtensionFieldsSourceFrom } from '../../components/DataExtension/dataExtensionFieldsSource'; import { createDataExtensionFieldActionsMenu } from '../../components/DataExtension/dataExtensionFieldActions'; export interface CustomFieldsWidgetStateParams { readonly container: WixPatternsContainer; readonly fqdn: Fqdn; readonly filterable?: boolean; readonly containsPii?: boolean; readonly extendedFields?: ExtendedFields; readonly defaultPermissions?: DefaultPermissionsConfig; readonly enableArchive?: boolean; } export type CustomFieldsWidgetSize = 'default' | 'small'; export class CustomFieldsWidgetState { readonly container; readonly dataExtension; readonly initTask = new TaskState(); _extendedFields: ExtendedFields | null | undefined = null; _formState: CustomFieldsAllNamespacesFormState | null = null; _size: CustomFieldsWidgetSize; _widgetContentRef: { current: HTMLDivElement | null } = { current: null, }; readonly panels; readonly reportBi; readonly fqdn; _customFieldsLazyComponents: | typeof CustomFieldsWidgetLazyContent | undefined = undefined; readonly apps; readonly customFieldsPanel; constructor({ container, fqdn, filterable, containsPii, defaultPermissions, extendedFields, enableArchive, }: CustomFieldsWidgetStateParams) { this.container = container; this.fqdn = fqdn; this._extendedFields = extendedFields; this._size = 'default'; this.panels = new SidePanelsState({ panelGroupName: fqdnToString(fqdn), container, }); this.reportBi = container.createBILogger({ componentType: 'CustomFieldsWidget', ...fqdn, }); this.dataExtension = new DataExtensionState({ container, fqdn, closeSidePanel: this.panels.closeSidePanel, filterable, containsPii, defaultPermissions, enableArchive, }); this.apps = new AppsState({ container, dataExtension: this.dataExtension, }); this.customFieldsPanel = new CustomFieldsPanelState({ fieldsSource: dataExtensionFieldsSourceFrom({ dataExtension: this.dataExtension, reportBi: this.reportBi, }), container, reportBi: this.reportBi, closeSidePanel: this.panels.closeSidePanel, createFieldActionsMenu: createDataExtensionFieldActionsMenu( this.dataExtension, ), }); makeObservable(this, { hasWritePermissions: computed, widgetSize: computed, setWidgetContentRef: action, isLoading: computed, isError: computed, _size: observable.ref, _widgetContentRef: observable.ref, _extendedFields: observable.ref, _adjustWidgetSize: action.bound, retry: action.bound, }); } get _userFieldsNamespace() { return this.dataExtension.dataExtensionService.userFieldsNamespace; } _appLoadingStart() { const startTime = performance.now(); const commonBiParams = this._commonDynamicBiParams(); this.reportBi( loadStart({ ...commonBiParams, }), ); return () => { this.reportBi( loadEnd({ ...commonBiParams, loadingTime: Math.round(performance.now() - startTime), }), ); }; } init({ appLoaded }: { appLoaded?: () => void }) { const { initTask, dataExtension, container, apps } = this; const disposers = [dataExtension.init(), apps.init()]; initTask.runOnce(async () => { dataExtension.initTask.runOnce(); apps.initTask.runOnce(); const [lazyComponents] = await Promise.all([ import( /* webpackChunkName: "CustomFieldsWidgetLazyContent" */ '../../components/CustomFieldsWidget/CustomFieldsWidgetLazyContent' ).catch((err) => { throw new WixPatternsError({ errorCode: 'LoadCustomFieldsWidgetLazyContentFailed', originalException: err, }); }), dataExtension.initTask.status.promise?.catch((err) => { throw new WixPatternsError({ errorCode: 'InitCustomFieldsDataExtensionFailed', originalException: err, }); }), container.initTask.status.promise?.catch((err) => { throw new WixPatternsError({ errorCode: 'InitCustomFieldsWidgetContainerFailed', originalException: err, }); }), apps.initTask.status.promise?.catch(() => null), ]).catch((error) => { this.container.internalMonitor.reportError({ error, }); this.reportBi( cairoErrorInLoadingAComponent({ errorType: error instanceof WixPatternsError ? error.name : undefined, }), ); throw error; }); this._customFieldsLazyComponents = lazyComponents; appLoaded?.(); }); return () => { disposers.forEach((d) => d?.()); }; } getNamespaceFormSchemaAndData(namespace: string) { const { dataExtension, _extendedFields } = this; const { schema, fields } = dataExtension.getSchemaAndFieldsByNamespace(namespace); return { fields, schema, extendedFieldsDataMap: _extendedFields?.namespaces?.[namespace], }; } initContent() { const disposers = [ addResizeObserver( this._widgetContentRef.current, this._adjustWidgetSize.bind(this), ), ]; this._adjustWidgetSize(); return () => { disposers.forEach((d) => d?.()); }; } _commonDynamicBiParams() { return { url: window.location.href, route: window.location.pathname, }; } retry() { this.reportBi( cairoTryAgainClicked({ actionName: 'Load custom fields', loaction: 'Custom fields widget', }), ); this.initTask.runOnce(); } get isDirty() { return !!this._formState?.isDirty; } get widgetSize() { return this._size; } get isLoading() { const { status } = this.initTask; return status.isIdle || status.isLoading; } get ActionButtonsComponent() { return this._customFieldsLazyComponents?.ActionButtons; } get CustomFieldsWidgetContent() { return this._customFieldsLazyComponents?.CustomFieldsWidgetContent; } get WixPatternsModalsContainer() { return this._customFieldsLazyComponents?.WixPatternsModalsContainer; } get CustomFieldModal() { return this._customFieldsLazyComponents?.CustomFieldModal; } get ArchiveFieldModal() { return this._customFieldsLazyComponents?.ArchiveFieldModal; } setWidgetContentRef(ref: HTMLDivElement | null) { this._widgetContentRef.current = ref; } _adjustWidgetSize() { if (this._widgetContentRef.current) { const element = this._widgetContentRef.current; if (element.clientWidth < 842) { this._size = 'small'; } else { this._size = 'default'; } } } get isError() { return this.initTask.status.isError; } async validate(): Promise<{ isValid: boolean; extendedFields?: ExtendedFields; values?: ExtendedFields; }> { const data = this._formState?.validate(); if (!data) { return { isValid: true, }; } if (data?.isValid) { const extendedFields = data.extendedFields; return { isValid: true, extendedFields, values: extendedFields, }; } return { isValid: false }; } get hasWritePermissions() { return this.dataExtension.hasWritePermissions; } }