krona-front/dist/assets/FieldBuilder-Bb70wc90.js

1 line
No EOL
17 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,l as r,r as i,s as a,t as o}from"./useToast-CS8pZhce.js";import{n as s,r as c,t as l}from"./fieldTypesMeta-BFbkZTaX.js";import{t as u}from"./eye-CkF1gwUX.js";import{t as d}from"./lock-BiWUbvPE.js";import{t as f}from"./pen-D8SS70u3.js";import{B as p,C as m,H as h,a as g,et as _,n as v,tt as y,u as b,y as x}from"./index-CyHCRa3Z.js";var S={name:`grip-vertical`,size:24,node:[[`circle`,{cx:`9`,cy:`12`,r:`1`,key:`1vctgf`}],[`circle`,{cx:`9`,cy:`5`,r:`1`,key:`hp0tcf`}],[`circle`,{cx:`9`,cy:`19`,r:`1`,key:`fkjjf6`}],[`circle`,{cx:`15`,cy:`12`,r:`1`,key:`1tmaij`}],[`circle`,{cx:`15`,cy:`5`,r:`1`,key:`19l28e`}],[`circle`,{cx:`15`,cy:`19`,r:`1`,key:`f4zoj3`}]]};S.node;var C=r(S),w=t(e(),1);function T(e,t,n){if(t===n||t<0||n<0||t>=e.length||n>=e.length)return e;let r=Array.from(e),[i]=r.splice(t,1);return r.splice(n,0,i),r}function E(e,t,n,r){if(e.key===`ArrowUp`&&(e.altKey||e.ctrlKey||e.metaKey)){if(e.preventDefault(),t>0)return r(t,t-1),!0}else if(e.key===`ArrowDown`&&(e.altKey||e.ctrlKey||e.metaKey)){if(e.preventDefault(),t<n-1)return r(t,t+1),!0}else if(e.key===`Home`&&(e.altKey||e.ctrlKey||e.metaKey)){if(e.preventDefault(),t>0)return r(t,0),!0}else if(e.key===`End`&&(e.altKey||e.ctrlKey||e.metaKey)&&(e.preventDefault(),t<n-1))return r(t,n-1),!0;return!1}var D=a(),O=()=>{let{entityCode:e}=y(),t=_(),{currentEntity:r,addField:a,updateField:S,deleteField:O,updateEntity:k}=h(e),{showToast:A}=o(),[j,M]=(0,w.useState)(``),[N,P]=(0,w.useState)(!1),[F,I]=(0,w.useState)(null),[L,R]=(0,w.useState)(`edit`),z={label:``,key:``,type:`text`,description:``,placeholder:``,defaultValue:``,required:!1,unique:!1,readOnly:!1,hidden:!1,searchable:!0,filterable:!0,sortable:!0,options:[{label:`Вариант 1`,value:`opt_1`,color:`#2F684C`},{label:`Вариант 2`,value:`opt_2`,color:`#B78335`}],validation:{min:void 0,max:void 0,minLength:void 0,maxLength:void 0,pattern:``},conditionalVisibility:{fieldKey:``,operator:`eq`,value:``},permissions:{viewRoles:[`*`],editRoles:[`*`]}},[B,V]=(0,w.useState)(z),H=(0,w.useMemo)(()=>r?.fields||[],[r]),U=(0,w.useMemo)(()=>{if(!j.trim())return H;let e=j.toLowerCase();return H.filter(t=>t.label.toLowerCase().includes(e)||t.key.toLowerCase().includes(e)||t.type.toLowerCase().includes(e))},[H,j]),W=()=>{I(null),V({...z,key:`custom_${Date.now().toString(36)}`}),P(!0)},G=e=>{I(e.id),V({...e,options:e.options?[...e.options]:z.options,validation:{...e.validation||z.validation},conditionalVisibility:{...e.conditionalVisibility||z.conditionalVisibility},permissions:{...e.permissions||z.permissions}}),P(!0)},K=async()=>{if(!B.label||!B.key||!e){A({type:`error`,title:`Укажите название и системный код поля`});return}try{F?(await S(e,F,B),A({type:`success`,title:`Поле «${B.label}» обновлено`})):(await a(e,B),A({type:`success`,title:`Поле «${B.label}» добавлено`})),P(!1)}catch(e){A({type:`error`,title:`Ошибка сохранения поля`,message:e instanceof Error?e.message:String(e)})}},q=async t=>{if(e){if(t.system){A({type:`error`,title:`Защита инвариантов платформы`,message:`Системное поле «${t.label}» (${t.key}) является обязательным для целостности схемы и не может быть удалено.`});return}if(confirm(`Удалить поле «${t.label}» (${t.key})?`))try{await O(e,t.id),A({type:`success`,title:`Поле «${t.label}» удалено`})}catch(e){A({type:`error`,title:`Ошибка удаления поля`,message:e instanceof Error?e.message:String(e)})}}},J=async(t,n)=>{if(!e||!r)return;let i=T(H,t,n);await k(e,{fields:i})},Y=()=>{let e={label:`Новый вариант ${(B.options?.length||0)+1}`,value:`opt_${Date.now().toString(36)}`,color:`#527286`};V(t=>({...t,options:[...t.options||[],e]}))},X=(e,t)=>{V(n=>{let r=[...n.options||[]];return r[e]={...r[e],...t},{...n,options:r}})},Z=e=>{V(t=>({...t,options:(t.options||[]).filter((t,n)=>n!==e)}))},Q=c(B.type||`text`);return(0,D.jsxs)(`div`,{className:`space-y-4 animate-fade-in`,children:[(0,D.jsxs)(`div`,{className:`flex flex-col sm:flex-row sm:items-center justify-between gap-3 p-4 bg-krona-surface border border-krona-border rounded-xl shadow-krona-soft`,children:[(0,D.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,D.jsxs)(n,{variant:`ghost`,size:`sm`,onClick:()=>t(`/settings/entities`),className:`p-1.5`,children:[(0,D.jsx)(p,{className:`w-4 h-4 mr-1`}),`Каталог`]}),(0,D.jsxs)(`div`,{children:[(0,D.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,D.jsxs)(`h1`,{className:`text-base font-bold text-krona-primary`,children:[`Поля сущности: `,r?.name||e]}),(0,D.jsx)(i,{variant:`neutral`,size:`sm`,children:(0,D.jsx)(`code`,{children:e})})]}),(0,D.jsx)(`p`,{className:`text-xs text-krona-secondary`,children:`Управление атрибутами, типами данных, правилами валидации и опциями выбора`})]})]}),(0,D.jsx)(`div`,{className:`flex items-center gap-2`,children:(0,D.jsxs)(n,{variant:`primary`,size:`sm`,onClick:W,children:[(0,D.jsx)(m,{className:`w-4 h-4 mr-1.5`}),`Добавить поле`]})})]}),(0,D.jsxs)(`div`,{className:`flex items-center justify-between gap-3 p-3 bg-krona-surface border border-krona-border rounded-xl`,children:[(0,D.jsx)(`div`,{className:`relative w-72`,children:(0,D.jsx)(g,{value:j,onChange:e=>M(e.target.value),placeholder:`Поиск по названию или коду...`,icon:(0,D.jsx)(x,{className:`w-3.5 h-3.5`})})}),(0,D.jsxs)(`div`,{className:`text-xs text-krona-secondary`,children:[`Всего полей: `,(0,D.jsx)(`strong`,{className:`text-krona-primary`,children:H.length}),` (из них`,` `,H.filter(e=>e.system).length,` системных)`]})]}),(0,D.jsx)(`div`,{className:`bg-krona-surface border border-krona-border rounded-xl shadow-krona-soft overflow-hidden`,children:(0,D.jsx)(`div`,{className:`divide-y divide-krona-border/60`,children:U.map((e,t)=>{let r=c(e.type),a=r.icon;return(0,D.jsxs)(`div`,{tabIndex:0,onKeyDown:e=>E(e,t,H.length,J),className:`flex items-center justify-between p-3 hover:bg-krona-workspace/50 transition-colors group`,children:[(0,D.jsxs)(`div`,{className:`flex items-center gap-3 min-w-0`,children:[(0,D.jsx)(`div`,{className:`text-krona-secondary hover:text-krona-primary cursor-grab active:cursor-grabbing p-1`,title:`Alt + Стрелки для перемещения с клавиатуры`,children:(0,D.jsx)(C,{className:`w-4 h-4 opacity-40 group-hover:opacity-100`})}),(0,D.jsx)(`div`,{className:`w-7 h-7 rounded-md bg-krona-workspace flex items-center justify-center text-krona-primary border border-krona-border/60 shrink-0`,children:(0,D.jsx)(a,{className:`w-3.5 h-3.5 text-krona-green`})}),(0,D.jsxs)(`div`,{className:`min-w-0`,children:[(0,D.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,D.jsx)(`span`,{className:`text-sm font-medium text-krona-primary truncate`,children:e.label}),e.required&&(0,D.jsx)(`span`,{className:`text-xs text-krona-danger font-bold`,title:`Обязательное поле`,children:`*`})]}),(0,D.jsxs)(`div`,{className:`flex items-center gap-2 text-xs font-mono text-krona-secondary`,children:[(0,D.jsx)(`span`,{children:e.key}),e.description&&(0,D.jsxs)(D.Fragment,{children:[(0,D.jsx)(`span`,{children:`•`}),(0,D.jsx)(`span`,{className:`font-sans text-[11px] truncate max-w-xs`,children:e.description})]})]})]})]}),(0,D.jsxs)(`div`,{className:`flex items-center gap-3 shrink-0`,children:[(0,D.jsx)(i,{variant:`neutral`,size:`sm`,className:`hidden sm:inline-flex`,children:r.label}),e.system?(0,D.jsxs)(i,{variant:`neutral`,size:`sm`,children:[(0,D.jsx)(d,{className:`w-2.5 h-2.5 mr-1`}),`System`]}):(0,D.jsx)(i,{variant:`gold`,size:`sm`,children:`Custom`}),(0,D.jsxs)(`div`,{className:`flex items-center gap-1 opacity-80 group-hover:opacity-100`,children:[(0,D.jsx)(n,{variant:`ghost`,size:`icon`,onClick:()=>G(e),title:`Редактировать поле`,children:(0,D.jsx)(f,{className:`w-3.5 h-3.5`})}),!e.system&&(0,D.jsx)(n,{variant:`ghost`,size:`icon`,onClick:()=>q(e),className:`text-krona-danger hover:bg-krona-danger/10`,title:`Удалить поле`,children:(0,D.jsx)(b,{className:`w-3.5 h-3.5`})})]})]})]},e.id)})})}),(0,D.jsx)(v,{isOpen:N,onClose:()=>P(!1),title:F?`Редактирование поля: ${B.label}`:`Добавление нового поля`,subtitle:`Сущность: ${r?.name||e}`,width:`lg`,children:(0,D.jsxs)(`div`,{className:`space-y-5 pb-6`,children:[(0,D.jsxs)(`div`,{className:`p-3 bg-krona-workspace rounded-xl border border-krona-border/80 space-y-2`,children:[(0,D.jsxs)(`div`,{className:`flex items-center justify-between text-xs text-krona-secondary`,children:[(0,D.jsxs)(`span`,{className:`font-semibold text-krona-primary flex items-center gap-1.5`,children:[(0,D.jsx)(u,{className:`w-3.5 h-3.5 text-krona-gold`}),`Интерактивное превью поля`]}),(0,D.jsx)(`div`,{className:`flex gap-1`,children:[`edit`,`readonly`,`create`].map(e=>(0,D.jsx)(`button`,{onClick:()=>R(e),className:`px-2 py-0.5 rounded text-[10px] font-medium uppercase ${L===e?`bg-krona-green text-white`:`bg-krona-surface text-krona-secondary`}`,children:e},e))})]}),(0,D.jsxs)(`div`,{className:`p-3 bg-krona-surface border border-krona-border rounded-lg`,children:[(0,D.jsxs)(`label`,{className:`text-xs font-semibold text-krona-primary block mb-1`,children:[B.label||`Название поля`,B.required&&(0,D.jsx)(`span`,{className:`text-krona-danger ml-1`,children:`*`})]}),L===`readonly`?(0,D.jsx)(`div`,{className:`text-xs text-krona-secondary font-mono bg-krona-workspace p-2 rounded`,children:B.defaultValue?String(B.defaultValue):`— (значение не заполнено)`}):Q.supportsOptions?(0,D.jsx)(`select`,{className:`w-full bg-krona-surface border border-krona-border rounded-md px-3 py-1.5 text-xs text-krona-primary`,children:B.options?.map(e=>(0,D.jsx)(`option`,{value:e.value,children:e.label},e.value))}):(0,D.jsx)(`input`,{type:B.type===`integer`||B.type===`number`?`number`:`text`,placeholder:B.placeholder||`Введите значение...`,className:`w-full bg-krona-surface border border-krona-border rounded-md px-3 py-1.5 text-xs text-krona-primary focus:outline-none focus:border-krona-green`,defaultValue:String(B.defaultValue||``)}),B.description&&(0,D.jsx)(`p`,{className:`text-[11px] text-krona-secondary mt-1`,children:B.description})]})]}),(0,D.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,D.jsx)(`label`,{className:`text-xs font-semibold text-krona-primary`,children:`Тип данных поля (все 39+ типов из спецификации) *`}),(0,D.jsx)(`select`,{value:B.type,onChange:e=>{let t=e.target.value,n=c(t);V(e=>({...e,type:t,defaultValue:n.defaultValue}))},disabled:!!F&&B.system,className:`w-full bg-krona-surface text-krona-primary border border-krona-border rounded-md px-3 py-2 text-xs focus:outline-none focus:border-krona-green`,children:s.map(e=>(0,D.jsx)(`optgroup`,{label:e.label,children:l.filter(t=>t.category===e.id).map(e=>(0,D.jsxs)(`option`,{value:e.type,children:[e.label,` (`,e.type,`)`]},e.type))},e.id))}),(0,D.jsx)(`p`,{className:`text-[11px] text-krona-secondary`,children:Q.description})]}),(0,D.jsxs)(`div`,{className:`grid grid-cols-1 sm:grid-cols-2 gap-3`,children:[(0,D.jsx)(g,{label:`Отображаемое название (Label) *`,value:B.label,onChange:e=>V(t=>({...t,label:e.target.value})),placeholder:`Например: Номер договора`,required:!0}),(0,D.jsx)(g,{label:`Системный код (API Name) *`,value:B.key,onChange:e=>V(t=>({...t,key:e.target.value.toLowerCase().replace(/[^a-z0-9_]/g,``)})),placeholder:`contract_number`,disabled:!!F&&B.system,helperText:B.system?`Системный инвариант (неизменяемый)`:void 0,required:!0})]}),(0,D.jsxs)(`div`,{className:`grid grid-cols-1 sm:grid-cols-2 gap-3`,children:[(0,D.jsx)(g,{label:`Подсказка (Placeholder)`,value:B.placeholder||``,onChange:e=>V(t=>({...t,placeholder:e.target.value})),placeholder:`Подсказка внутри поля`}),(0,D.jsx)(g,{label:`Значение по умолчанию`,value:String(B.defaultValue||``),onChange:e=>V(t=>({...t,defaultValue:e.target.value})),placeholder:`Значение по умолчанию`})]}),(0,D.jsx)(g,{label:`Описание для пользователя (Tooltip / Helper)`,value:B.description||``,onChange:e=>V(t=>({...t,description:e.target.value})),placeholder:`Пояснение к заполнению поля`}),(0,D.jsxs)(`div`,{className:`space-y-2 p-3.5 bg-krona-workspace rounded-xl border border-krona-border/60`,children:[(0,D.jsx)(`h4`,{className:`text-xs font-bold text-krona-primary uppercase tracking-wider mb-2`,children:`Флаги поведения поля`}),(0,D.jsxs)(`div`,{className:`grid grid-cols-2 sm:grid-cols-3 gap-2 text-xs`,children:[(0,D.jsxs)(`label`,{className:`flex items-center gap-2 cursor-pointer`,children:[(0,D.jsx)(`input`,{type:`checkbox`,checked:B.required||!1,onChange:e=>V(t=>({...t,required:e.target.checked}))}),`Обязательное`]}),(0,D.jsxs)(`label`,{className:`flex items-center gap-2 cursor-pointer`,children:[(0,D.jsx)(`input`,{type:`checkbox`,checked:B.unique||!1,onChange:e=>V(t=>({...t,unique:e.target.checked}))}),`Уникальное`]}),(0,D.jsxs)(`label`,{className:`flex items-center gap-2 cursor-pointer`,children:[(0,D.jsx)(`input`,{type:`checkbox`,checked:B.readOnly||!1,onChange:e=>V(t=>({...t,readOnly:e.target.checked}))}),`Только чтение`]}),(0,D.jsxs)(`label`,{className:`flex items-center gap-2 cursor-pointer`,children:[(0,D.jsx)(`input`,{type:`checkbox`,checked:B.searchable!==!1,onChange:e=>V(t=>({...t,searchable:e.target.checked}))}),`Полнотекстовый поиск`]}),(0,D.jsxs)(`label`,{className:`flex items-center gap-2 cursor-pointer`,children:[(0,D.jsx)(`input`,{type:`checkbox`,checked:B.filterable!==!1,onChange:e=>V(t=>({...t,filterable:e.target.checked}))}),`Фильтрация в списках`]}),(0,D.jsxs)(`label`,{className:`flex items-center gap-2 cursor-pointer`,children:[(0,D.jsx)(`input`,{type:`checkbox`,checked:B.sortable!==!1,onChange:e=>V(t=>({...t,sortable:e.target.checked}))}),`Сортировка`]})]})]}),Q.supportsOptions&&(0,D.jsxs)(`div`,{className:`space-y-3 p-3.5 bg-krona-workspace rounded-xl border border-krona-border/60`,children:[(0,D.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,D.jsx)(`h4`,{className:`text-xs font-bold text-krona-primary uppercase tracking-wider`,children:`Варианты выбора (Options Editor)`}),(0,D.jsxs)(n,{variant:`secondary`,size:`sm`,onClick:Y,children:[(0,D.jsx)(m,{className:`w-3.5 h-3.5 mr-1`}),`Добавить вариант`]})]}),(0,D.jsx)(`div`,{className:`space-y-2`,children:B.options?.map((e,t)=>(0,D.jsxs)(`div`,{className:`flex items-center gap-2 bg-krona-surface p-2 rounded border border-krona-border`,children:[(0,D.jsx)(g,{value:e.label,onChange:e=>X(t,{label:e.target.value}),placeholder:`Подпись варианта`,className:`text-xs py-1`}),(0,D.jsx)(g,{value:e.value,onChange:e=>X(t,{value:e.target.value}),placeholder:`Код значения`,className:`text-xs py-1 w-32 font-mono`}),(0,D.jsx)(`input`,{type:`color`,value:e.color||`#2F684C`,onChange:e=>X(t,{color:e.target.value}),className:`w-7 h-7 rounded border border-krona-border cursor-pointer p-0 shrink-0`,title:`Цвет бейджа`}),(0,D.jsx)(`button`,{type:`button`,onClick:()=>Z(t),className:`p-1 text-krona-danger hover:bg-krona-danger/10 rounded`,children:(0,D.jsx)(b,{className:`w-3.5 h-3.5`})})]},t))})]}),(0,D.jsxs)(`div`,{className:`space-y-2 p-3.5 bg-krona-workspace rounded-xl border border-krona-border/60`,children:[(0,D.jsx)(`h4`,{className:`text-xs font-bold text-krona-primary uppercase tracking-wider mb-2`,children:`Правила валидации (Validation Rules)`}),(0,D.jsxs)(`div`,{className:`grid grid-cols-2 gap-3`,children:[(0,D.jsx)(g,{label:`Мин. значение / длина`,type:`number`,value:B.validation?.min??B.validation?.minLength??``,onChange:e=>V(t=>({...t,validation:{...t.validation,min:Number(e.target.value)}}))}),(0,D.jsx)(g,{label:`Макс. значение / длина`,type:`number`,value:B.validation?.max??B.validation?.maxLength??``,onChange:e=>V(t=>({...t,validation:{...t.validation,max:Number(e.target.value)}}))})]}),(0,D.jsx)(g,{label:`RegEx паттерн проверки`,value:B.validation?.pattern||``,onChange:e=>V(t=>({...t,validation:{...t.validation,pattern:e.target.value}})),placeholder:`^[A-Z0-9_-]+$`,className:`font-mono text-xs`})]}),(0,D.jsxs)(`div`,{className:`flex justify-end gap-2 pt-4 border-t border-krona-border/60`,children:[(0,D.jsx)(n,{variant:`outline`,size:`md`,onClick:()=>P(!1),children:`Отмена`}),(0,D.jsx)(n,{variant:`primary`,size:`md`,onClick:K,children:`Сохранить поле`})]})]})})]})};export{O as FieldBuilder,O as default};