1 line
No EOL
16 KiB
JavaScript
1 line
No EOL
16 KiB
JavaScript
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}; |