Действия с записями

Метод, вызываемый после публикации черновика записи

Точка расширения UEAfterPublishRecord позволяет вызывать функции после публикации черновика записи.

Описание UEAfterPublishRecord:

export type UEAfterPublishRecord<T extends IRecordEntity> = UeModuleBase & {
    default: {
        fn: (dataCardStore: AbstractCardStore<T>) => void;
        resolver: (dataCardStore: AbstractCardStore<T>) => boolean;
    };
}

Пример UEAfterPublishRecord: дополнительное сообщение, если настроен процесс согласования при публикации записи.

function afterPublish () {
    Dialog.showMessage(i18n.t('module.workflow>dataCardAfterPublish>message'));
}

export const afterPublishRecordUe: UEAfterPublishRecord<any> = {
    'default': {
        type: UEList.AfterPublishRecord,
        moduleId: 'afterPublishWorkflow',
        active: true,
        system: false,
        fn: afterPublish,
        resolver: (store: AbstractCardStore<any>) => {
            return store.draftStore?.selectedDraft?.state.getValue() === 'DELAYED_BY_WORKFLOW';
        },
        meta: {}
    }
};

Метод, вызываемый после публикации c ошибкой

Точка расширения UEAfterPublishRecordFailure позволяет вызывать функции после публикации черновика записи с ошибкой.

Описание UEAfterPublishRecordFailure:

export type UEAfterPublishRecordFailure<T extends IRecordEntity> = UeModuleBase & {
    default: {
        fn: (dataCardStore: AbstractCardStore<T>, errors: ServerDetailsError[]) => void;
        resolver: (dataCardStore: AbstractCardStore<T>, errors: ServerDetailsError[]) => boolean;
    };
}

Клонирование записи

Точка расширения UECloneRecord предназначена для добавления фрагмента к запросу на клонирование записи, а также для вывода в окне настроек клонирования интерфейса (для изменения передаваемых во фрагменте параметров).

Используемые типы:

interface ICloneInnerStore<T extends keyof UniverseUE.ICloneAtomicPayload> {
    /*
    * Возвращаемый фрагмент запроса на клонирование и ключ, под которым он будет добавлен в запрос, должны быть
    * глобально объявлены в пространстве имен UniverseUE
    */
    payloadContent: {
        key: T;
        content: UniverseUE.ICloneAtomicPayload[T];
    };

    /*
    * Возвращает true, если нужно запретить подтверждение клонирования записи
    */
    readonly hasErrors: boolean;
}

/*
* Передаваемые в компонент параметров пропсы
*/
interface ICloneRecordParametersProps {
    store: CloneStore;
}

type UECloneRecordResolver = (cloneStore: CloneStore) => boolean;

type UECloneRecordMeta = {
    /*
    * @param key - передается meta.key текущего User Exit
    */
    getStore: (cloneStore: CloneStore, key: string) => ICloneInnerStore;
    key: string;
};

export type UECloneRecord = UeModuleBase<UECloneRecordResolver, UECloneRecordMeta> & {
    component: ComponentType<ICloneRecordParametersProps>;
};

Пример UECloneRecord:

const CLONE_RECORD_ADDITIONAL_PAYLOAD_KEY = 'clone_record_additional_fragment_v1' as const;

interface ICloneRecordAdditionalPayload {
    cleanUnique: boolean;
}

declare global {
    namespace UniverseUE {
        export interface ICloneAtomicPayload {
            [CLONE_RECORD_ADDITIONAL_PAYLOAD_KEY]: ICloneRecordAdditionalPayload;
        }
    }
}

class CloneRecordAdditionalFragmentStore implements ICloneInnerStore {
    @observable
    cleanUnique: boolean;

    @action
    setCleanUnique (cleanUnique: boolean) {
        this.cleanUnique = cleanUnique;
    }

    get payloadContent () {
        return {
            key: CLONE_RECORD_ADDITIONAL_PAYLOAD_KEY,
            content: {
                cleanUnique: this.cleanUnique
            }
        }
    }

    get hasErrors () {
        return false;
    }

}

@observer
class CloneRecordUserExit extends React.Component<ICloneRecordParametersProps> {
    get store () {
        return this.props.store.getStore(CLONE_RECORD_ADDITIONAL_PAYLOAD_KEY) as CloneRecordAdditionalFragmentStore;
    }

    override render () {
        const {store} = this;

        return (
            <CardPanel
                internal={true}
                title={'Дополнительные параметры клонирования'}>
                <Field.Checkbox
                    label={'Очистить уникальные значения?'}
                    defaultChecked={store.cleanUnique}
                    onChange={(name, value) => store.setCleanUnique(value)}
                />
            </CardPanel>
        );
    }
}

ueModuleManager.addModule('CloneRecord', {
    active: true,
    component: CloneRecordUserExit,
    meta: {
        key: CLONE_RECORD_ADDITIONAL_PAYLOAD_KEY,
        getStore: () => {
            return new CloneRecordAdditionalFragmentStore();
        }
    },
    moduleId: CLONE_RECORD_ADDITIONAL_PAYLOAD_KEY,
    resolver: (cloneStore: CloneStore) => {
        const dataRecordInnerStore = cloneStore.dataCardStore.getInnerStore('data-record-additional-store');

        return dataRecordInnerStore !== undefined;
    },
    system: false
});
Модальное окно клонирования записи

Рисунок 1 - Модальное окно клонирования записи

Добавление доп. вкладки в модель типов активов/справочников

Точка расширения UEMetaModelTab предназначена для добавления вкладок в модели типов активов/справочников.

Можно расширять существующую модель через CustomProperties или показывать дополнительную информацию по связанным сущностям.

Описание UEMetaModelTab:

type TabDisabledConfig = {
    isDisabled: boolean;
    disableReasons?: string[];
}

export type UEMetaModelTab = UeModuleBase & {
    default: {
        component: ComponentType<{
            attributesStore: AttributesStore;
            metaModel: IMetaModel;
            draftId?: DraftId;
        }>; // Компонент для рендеринга, если выбрана текущая вкладка
        meta: {
            name: string; // Ключ вкладки
            getDisplayName: () => string; // Заголовок вкладки
            getTabDisabledConfig?: (metaModel: IMetaModel) => TabDisabledConfig; // Функция проверки отключения вкладки и получения причин отключения
        };
        resolver: (metaModel: IMetaModel) => boolean;
    };
}

Пример UEMetaModelTab: вкладка "Внешний вид".

export const metaModelTabs: UEMetaModelTab[] = [
    {
        'default': {
            type: UEList.MetaModelTab,
            moduleId: 'dataCardLayoutTab',
            active: true,
            system: false,
            meta: {
                name: 'layout',
                getDisplayName: () => {
                    return i18n.t('module.meta-se>layoutTab');
                },
                getTabDisabledConfig: (metaModel: IMetaModel) => {
                    const hasPhantomAttribute = metaModel.getAttributes()
                        .some((attribute) => {
                            return attribute.getPhantom();
                        });

                    return {
                        isDisabled: hasPhantomAttribute,
                        disableReasons: [
                            i18n.t('module.meta-se>tabDisableReason')
                        ]
                    };
                }
            },
            resolver: (metaModel: IMetaModel) => {
                return metaModel ? (MetaDataTypeGuards.isEntity(metaModel) || MetaDataTypeGuards.isLookupEntity(metaModel)) : false;
            },
            component: EntityLayoutTab
        }
    }
];