krona-front/dist/assets/EntityCatalog-CEDNI60l.js

1 line
No EOL
16 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import{f as e,h as t,i as n,r,s as i,t as a}from"./useToast-CS8pZhce.js";import{t as o}from"./panels-top-left-BomsDlf9.js";import{t as s}from"./table-_fqSCPRE.js";import{$ as c,A as l,I as u,a as d,dt as f,h as p,j as m,p as h,r as g,s as _,t as v,u as y,w as b,y as x}from"./index-CT8iDYYK.js";var S=t(e(),1),C=i(),w=()=>{let e=f(),{entities:t,loading:i,createEntity:w,deleteEntity:T}=c(),{showToast:E}=a(),[D,O]=(0,S.useState)(``),[k,A]=(0,S.useState)(`all`),[j,M]=(0,S.useState)(!1),[N,P]=(0,S.useState)(!1),[F,I]=(0,S.useState)({name:``,pluralName:``,code:``,description:``,category:`custom`,primaryFieldKey:`name`,autonumberingEnabled:!1,autonumberFormat:`DOC-{YYYY}-{0000}`}),[L,R]=(0,S.useState)(null),z=(0,S.useMemo)(()=>t.filter(e=>{let t=e.name.toLowerCase().includes(D.toLowerCase())||e.code.toLowerCase().includes(D.toLowerCase())||e.description&&e.description.toLowerCase().includes(D.toLowerCase()),n=k===`all`||k===`system`&&e.isSystem||k===`custom`&&!e.isSystem||e.category===k;return t&&n}),[t,D,k]),B=(0,S.useMemo)(()=>{let e=t.length,n=t.filter(e=>e.isSystem).length;return{total:e,system:n,custom:e-n,totalFields:t.reduce((e,t)=>e+(t.fields?.length||0),0)}},[t]),V=e=>{let t={а:`a`,б:`b`,в:`v`,г:`g`,д:`d`,е:`e`,ё:`yo`,ж:`zh`,з:`z`,и:`i`,й:`y`,к:`k`,л:`l`,м:`m`,н:`n`,о:`o`,п:`p`,р:`r`,с:`s`,т:`t`,у:`u`,ф:`f`,х:`kh`,ц:`ts`,ч:`ch`,ш:`sh`,щ:`shch`,ъ:``,ы:`y`,ь:``,э:`e`,ю:`yu`,я:`ya`};return e.toLowerCase().split(``).map(e=>t[e]||e).join(``).replace(/[^a-z0-9_]/g,`_`).replace(/_{2,}/g,`_`).replace(/^_|_$/g,``)},H=e=>{let t=V(e);I(n=>({...n,name:e,pluralName:n.pluralName||`${e}ы`,code:N?n.code:t}))};return(0,C.jsxs)(`div`,{className:`space-y-5 animate-fade-in`,children:[(0,C.jsxs)(`div`,{className:`flex flex-col sm:flex-row sm:items-center justify-between gap-4 p-5 bg-krona-surface border border-krona-border rounded-xl shadow-krona-soft`,children:[(0,C.jsxs)(`div`,{children:[(0,C.jsxs)(`div`,{className:`flex items-center gap-2 mb-1`,children:[(0,C.jsx)(m,{className:`w-5 h-5 text-krona-green`}),(0,C.jsx)(`h1`,{className:`text-base font-bold text-krona-primary`,children:`Configuration Engine: Каталог сущностей`}),(0,C.jsx)(v,{level:`pilot1`,size:`sm`})]}),(0,C.jsx)(`p`,{className:`text-xs text-krona-secondary max-w-2xl`,children:`Центральный конструктор моделей данных: создание системных и пользовательских сущностей, настройка 39+ типов полей, визуальный drag-and-drop редактор форм, карточек и сохранённых представлений.`})]}),(0,C.jsxs)(n,{variant:`primary`,size:`md`,"data-testid":`create-entity-btn`,onClick:()=>M(!0),className:`shrink-0`,children:[(0,C.jsx)(b,{className:`w-4 h-4 mr-1.5`}),`Создать сущность`]})]}),(0,C.jsxs)(`div`,{className:`grid grid-cols-2 md:grid-cols-4 gap-3`,children:[(0,C.jsxs)(`div`,{className:`p-3.5 bg-krona-surface border border-krona-border rounded-xl`,children:[(0,C.jsx)(`span`,{className:`text-xs text-krona-secondary`,children:`Всего сущностей`}),(0,C.jsx)(`p`,{className:`text-xl font-bold text-krona-primary mt-1`,children:B.total})]}),(0,C.jsxs)(`div`,{className:`p-3.5 bg-krona-surface border border-krona-border rounded-xl`,children:[(0,C.jsx)(`span`,{className:`text-xs text-krona-secondary`,children:`Системных сущностей`}),(0,C.jsx)(`p`,{className:`text-xl font-bold text-krona-green mt-1`,children:B.system})]}),(0,C.jsxs)(`div`,{className:`p-3.5 bg-krona-surface border border-krona-border rounded-xl`,children:[(0,C.jsx)(`span`,{className:`text-xs text-krona-secondary`,children:`Пользовательских (Custom)`}),(0,C.jsx)(`p`,{className:`text-xl font-bold text-krona-gold mt-1`,children:B.custom})]}),(0,C.jsxs)(`div`,{className:`p-3.5 bg-krona-surface border border-krona-border rounded-xl`,children:[(0,C.jsx)(`span`,{className:`text-xs text-krona-secondary`,children:`Активных полей`}),(0,C.jsx)(`p`,{className:`text-xl font-bold text-krona-primary mt-1`,children:B.totalFields})]})]}),(0,C.jsxs)(`div`,{className:`flex flex-col sm:flex-row sm:items-center justify-between gap-3 p-3.5 bg-krona-surface border border-krona-border rounded-xl`,children:[(0,C.jsx)(`div`,{className:`relative w-full sm:w-80`,children:(0,C.jsx)(d,{value:D,onChange:e=>O(e.target.value),placeholder:`Поиск по названию или коду...`,icon:(0,C.jsx)(x,{className:`w-4 h-4`})})}),(0,C.jsx)(`div`,{className:`flex flex-wrap gap-1.5`,children:[{id:`all`,label:`Все сущности`},{id:`system`,label:`Системные`},{id:`custom`,label:`Пользовательские`},{id:`crm`,label:`CRM`},{id:`commerce`,label:`Коммерция`},{id:`inventory`,label:`Склад`},{id:`finance`,label:`Финансы`}].map(e=>(0,C.jsx)(`button`,{onClick:()=>A(e.id),className:`px-3 py-1.5 rounded-lg text-xs font-medium transition-colors cursor-pointer ${k===e.id?`bg-krona-green text-white shadow-sm`:`bg-krona-surface-muted text-krona-secondary hover:text-krona-primary`}`,children:e.label},e.id))})]}),(0,C.jsx)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4`,children:z.map(t=>{let i=t.fields?.length||0;return(0,C.jsxs)(`div`,{className:`bg-krona-surface border border-krona-border rounded-xl p-4 shadow-krona-soft hover:border-krona-border-strong transition-all flex flex-col justify-between group`,children:[(0,C.jsxs)(`div`,{children:[(0,C.jsxs)(`div`,{className:`flex items-start justify-between gap-2 mb-2`,children:[(0,C.jsxs)(`div`,{className:`flex items-center gap-2.5`,children:[(0,C.jsx)(`div`,{className:`w-8 h-8 rounded-lg bg-krona-workspace flex items-center justify-center text-krona-primary border border-krona-border/60`,children:(0,C.jsx)(m,{className:`w-4 h-4 text-krona-green`})}),(0,C.jsxs)(`div`,{children:[(0,C.jsx)(`h3`,{className:`text-sm font-semibold text-krona-primary leading-tight`,children:t.name}),(0,C.jsx)(`p`,{className:`text-[11px] font-mono text-krona-secondary`,children:t.code})]})]}),(0,C.jsx)(`div`,{className:`flex items-center gap-1.5`,children:t.isSystem?(0,C.jsxs)(r,{variant:`neutral`,size:`sm`,children:[(0,C.jsx)(l,{className:`w-2.5 h-2.5 mr-1`}),`System`]}):(0,C.jsxs)(r,{variant:`gold`,size:`sm`,children:[(0,C.jsx)(h,{className:`w-2.5 h-2.5 mr-1`}),`Custom`]})})]}),(0,C.jsx)(`p`,{className:`text-xs text-krona-secondary line-clamp-2 min-h-[32px] mb-3`,children:t.description||`Пользовательская сущность бизнес-платформы Krona`}),(0,C.jsxs)(`div`,{className:`flex items-center gap-2 py-2 border-t border-b border-krona-border/60 text-xs text-krona-secondary mb-3`,children:[(0,C.jsxs)(`span`,{children:[`Полей: `,(0,C.jsx)(`strong`,{className:`text-krona-primary font-semibold`,children:i})]}),(0,C.jsx)(`span`,{children:`•`}),(0,C.jsxs)(`span`,{children:[`Категория: `,(0,C.jsx)(`strong`,{className:`text-krona-primary font-semibold capitalize`,children:t.category})]})]})]}),(0,C.jsxs)(`div`,{className:`space-y-2`,children:[(0,C.jsxs)(`div`,{className:`grid grid-cols-5 gap-1`,children:[(0,C.jsxs)(n,{variant:`primary`,size:`sm`,className:`text-[11px] px-1 py-1.5`,"data-testid":`open-entity-${t.code}-btn`,onClick:()=>e(`/entities/${t.code}`),title:`Перейти к записям сущности`,children:[(0,C.jsx)(m,{className:`w-3 h-3 mr-0.5`}),`Записи`]}),(0,C.jsxs)(n,{variant:`outline`,size:`sm`,className:`text-[11px] px-1 py-1.5`,onClick:()=>e(`/settings/entities/${t.code}/fields`),title:`Конструктор полей`,children:[(0,C.jsx)(p,{className:`w-3 h-3 mr-1 text-krona-green`}),`Поля`]}),(0,C.jsxs)(n,{variant:`outline`,size:`sm`,className:`text-[11px] px-1 py-1.5`,onClick:()=>e(`/settings/entities/${t.code}/forms`),title:`Конструктор форм`,children:[(0,C.jsx)(o,{className:`w-3 h-3 mr-1 text-krona-gold`}),`Формы`]}),(0,C.jsxs)(n,{variant:`outline`,size:`sm`,className:`text-[11px] px-1 py-1.5`,onClick:()=>e(`/settings/entities/${t.code}/card`),title:`Конструктор карточки`,children:[(0,C.jsx)(u,{className:`w-3 h-3 mr-1 text-krona-info`}),`Карточка`]}),(0,C.jsxs)(n,{variant:`outline`,size:`sm`,className:`text-[11px] px-1 py-1.5`,onClick:()=>e(`/settings/entities/${t.code}/views`),title:`Конструктор списков и представлений`,children:[(0,C.jsx)(s,{className:`w-3 h-3 mr-1 text-krona-primary`}),`Списки`]})]}),!t.isSystem&&(0,C.jsx)(`div`,{className:`flex justify-end pt-1`,children:(0,C.jsxs)(`button`,{type:`button`,onClick:()=>R(t),className:`text-[11px] text-krona-danger hover:text-krona-danger/80 flex items-center gap-1 font-medium cursor-pointer`,children:[(0,C.jsx)(y,{className:`w-3 h-3`}),`Удалить сущность`]})})]})]},t.code)})}),z.length===0&&!i&&(0,C.jsxs)(`div`,{className:`text-center py-12 p-6 bg-krona-surface border border-dashed border-krona-border rounded-xl`,children:[(0,C.jsx)(m,{className:`w-8 h-8 text-krona-secondary mx-auto mb-2 opacity-50`}),(0,C.jsx)(`h3`,{className:`text-sm font-semibold text-krona-primary mb-1`,children:`Сущности не найдены`}),(0,C.jsxs)(`p`,{className:`text-xs text-krona-secondary mb-4`,children:[`По вашему запросу «`,D,`» ничего не найдено.`]}),(0,C.jsx)(n,{variant:`secondary`,size:`sm`,onClick:()=>O(``),children:`Сбросить фильтр`})]}),(0,C.jsx)(g,{isOpen:j,onClose:()=>M(!1),title:`Создание новой сущности`,subtitle:`Задайте базовые параметры и системный API-идентификатор`,maxWidth:`lg`,closeOnBackdropClick:!1,children:(0,C.jsxs)(`form`,{onSubmit:async e=>{if(e.preventDefault(),!F.name||!F.code){E({type:`error`,title:`Заполните обязательные поля: название и код`});return}let n=F.code.trim().toLowerCase();if(t.some(e=>e.code===n)){E({type:`error`,title:`Сущность с таким системным кодом уже существует`});return}try{let e=[{id:`f_${n}_name`,key:F.primaryFieldKey||`name`,label:`Наименование`,type:`text`,required:!0,system:!0,searchable:!0,sortable:!0},{id:`f_${n}_status`,key:`status`,label:`Статус`,type:`status`,required:!1,system:!0,options:[{label:`Новый`,value:`new`,color:`neutral`},{label:`В работе`,value:`in_progress`,color:`warning`},{label:`Завершён`,value:`completed`,color:`green`}]}];await w({code:n,name:F.name.trim(),pluralName:F.pluralName.trim()||`${F.name}ы`,description:F.description.trim(),category:F.category,isSystem:!1,maturity:`target_prototype`,primaryFieldKey:F.primaryFieldKey||`name`,autonumberingEnabled:F.autonumberingEnabled,autonumberFormat:F.autonumberFormat,fields:e,defaultView:`table`}),E({type:`success`,title:`Сущность «${F.name}» создана`,message:`Теперь вы можете добавить пользовательские поля, настроить формы и списки.`}),M(!1),P(!1),I({name:``,pluralName:``,code:``,description:``,category:`custom`,primaryFieldKey:`name`,autonumberingEnabled:!1,autonumberFormat:`DOC-{YYYY}-{0000}`})}catch(e){E({type:`error`,title:`Ошибка создания сущности`,message:e instanceof Error?e.message:String(e)})}},className:`space-y-4`,children:[(0,C.jsxs)(`div`,{className:`grid grid-cols-1 sm:grid-cols-2 gap-3`,children:[(0,C.jsx)(d,{label:`Наименование (ед. число) *`,placeholder:`Например: Договор`,"data-testid":`new-entity-name-input`,value:F.name,onChange:e=>H(e.target.value),required:!0}),(0,C.jsx)(d,{label:`Наименование (мн. число) *`,placeholder:`Например: Договоры`,"data-testid":`new-entity-plural-input`,value:F.pluralName,onChange:e=>I(t=>({...t,pluralName:e.target.value})),required:!0})]}),(0,C.jsxs)(`div`,{className:`grid grid-cols-1 sm:grid-cols-2 gap-3`,children:[(0,C.jsx)(d,{label:`Системный код (API Name) *`,placeholder:`contract`,"data-testid":`new-entity-code-input`,value:F.code,onChange:e=>{P(!0),I(t=>({...t,code:e.target.value.toLowerCase().replace(/[^a-z0-9_]/g,``)}))},helperText:`Используется в URL, API и индексах (только a-z, 0-9, _)`,required:!0}),(0,C.jsxs)(`div`,{className:`flex flex-col gap-1.5 text-left`,children:[(0,C.jsx)(`label`,{className:`text-xs font-medium text-krona-secondary select-none`,children:`Категория`}),(0,C.jsxs)(`select`,{className:`w-full bg-krona-surface text-krona-primary border border-krona-border rounded-md px-3 py-2 text-sm focus:outline-none focus:border-krona-green`,value:F.category,onChange:e=>I(t=>({...t,category:e.target.value})),children:[(0,C.jsx)(`option`,{value:`custom`,children:`Пользовательская (Custom)`}),(0,C.jsx)(`option`,{value:`crm`,children:`CRM & Продажи`}),(0,C.jsx)(`option`,{value:`commerce`,children:`Коммерция`}),(0,C.jsx)(`option`,{value:`inventory`,children:`Склад & Запасы`}),(0,C.jsx)(`option`,{value:`finance`,children:`Финансы`}),(0,C.jsx)(`option`,{value:`operations`,children:`Операции`})]})]})]}),(0,C.jsx)(d,{label:`Описание назначения сущности`,placeholder:`Для каких бизнес-процессов предназначена сущность...`,value:F.description,onChange:e=>I(t=>({...t,description:e.target.value}))}),(0,C.jsxs)(`div`,{className:`p-3.5 bg-krona-workspace rounded-lg border border-krona-border/60 space-y-3`,children:[(0,C.jsxs)(`label`,{className:`flex items-center gap-2 cursor-pointer text-xs font-semibold text-krona-primary`,children:[(0,C.jsx)(`input`,{type:`checkbox`,checked:F.autonumberingEnabled,onChange:e=>I(t=>({...t,autonumberingEnabled:e.target.checked})),className:`rounded text-krona-green`}),`Включить автоматическую нумерацию записей`]}),F.autonumberingEnabled&&(0,C.jsx)(d,{label:`Шаблон нумератора`,value:F.autonumberFormat,onChange:e=>I(t=>({...t,autonumberFormat:e.target.value})),helperText:`Теги: {YYYY} - год, {MM} - месяц, {0000} - порядковый номер`})]}),(0,C.jsxs)(`div`,{className:`flex justify-end gap-2.5 pt-3 border-t border-krona-border/60`,children:[(0,C.jsx)(n,{variant:`outline`,size:`md`,type:`button`,onClick:()=>M(!1),children:`Отмена`}),(0,C.jsx)(n,{variant:`primary`,size:`md`,type:`submit`,"data-testid":`submit-create-entity-btn`,children:`Создать и перейти к полям`})]})]})}),(0,C.jsx)(g,{isOpen:!!L,onClose:()=>R(null),title:`Подтверждение удаления сущности`,subtitle:`Вы собираетесь удалить пользовательскую сущность «${L?.name}»`,maxWidth:`md`,children:(0,C.jsxs)(`div`,{className:`space-y-4`,children:[(0,C.jsxs)(`div`,{className:`p-4 bg-krona-danger/10 border border-krona-danger/30 rounded-lg text-xs text-krona-danger flex items-start gap-3`,children:[(0,C.jsx)(_,{className:`w-5 h-5 shrink-0 mt-0.5`}),(0,C.jsxs)(`div`,{children:[(0,C.jsx)(`p`,{className:`font-semibold mb-1`,children:`Внимание! Проверка зависимостей (Dependency Impact)`}),(0,C.jsxs)(`p`,{children:[`Будут удалены все связанные определения полей (`,L?.fields?.length||0,` шт.), сохраненные формы, представления списков и записи из базы данных.`]})]})]}),(0,C.jsxs)(`div`,{className:`p-3 bg-krona-workspace rounded-lg text-xs text-krona-secondary space-y-1`,children:[(0,C.jsxs)(`p`,{children:[`Код сущности: `,(0,C.jsx)(`code`,{className:`font-mono text-krona-primary`,children:L?.code})]}),(0,C.jsxs)(`p`,{children:[`Категория: `,(0,C.jsx)(`span`,{className:`text-krona-primary`,children:L?.category})]})]}),(0,C.jsxs)(`div`,{className:`flex justify-end gap-2.5 pt-3 border-t border-krona-border/60`,children:[(0,C.jsx)(n,{variant:`outline`,size:`md`,onClick:()=>R(null),children:`Отмена`}),(0,C.jsx)(n,{variant:`danger`,size:`md`,onClick:async()=>{if(L){if(L.isSystem){E({type:`error`,title:`Нельзя удалить системную сущность платформы`});return}try{await T(L.code),E({type:`success`,title:`Сущность «${L.name}» удалена`}),R(null)}catch(e){E({type:`error`,title:`Ошибка удаления сущности`,message:e instanceof Error?e.message:String(e)})}}},children:`Да, удалить сущность`})]})]})})]})};export{w as EntityCatalog,w as default};