krona-front/dist/assets/ViewBuilder-g2KlOj5c.js

2 lines
No EOL
19 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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{l as s}from"./indexedDb-DZ-aRPMs.js";import{t as c}from"./arrow-up-down--M136cK3.js";import{t as l}from"./download-ByGeM7La.js";import{t as u}from"./eye-CkF1gwUX.js";import{t as d}from"./save-D8euL60I.js";import{t as f}from"./table-_fqSCPRE.js";import{B as p,C as m,H as h,Y as g,a as _,et as v,r as y,tt as b,u as x}from"./index-CyHCRa3Z.js";import{t as S}from"./currency-DdDs82F5.js";var C={name:`columns-2`,size:24,node:[[`rect`,{width:`18`,height:`18`,x:`3`,y:`3`,rx:`2`,key:`afitv7`}],[`path`,{d:`M12 3v18`,key:`108xh3`}]],aliases:[`columns`]};C.node;var w=r(C),T={name:`funnel`,size:24,node:[[`path`,{d:`M10 20a1 1 0 0 0 .553.895l2 1A1 1 0 0 0 14 21v-7a2 2 0 0 1 .517-1.341L21.74 4.67A1 1 0 0 0 21 3H3a1 1 0 0 0-.742 1.67l7.225 7.989A2 2 0 0 1 10 14z`,key:`sc7q7i`}]],aliases:[`filter`]};T.node;var E=r(T),D={name:`move-right`,size:24,node:[[`path`,{d:`M18 8L22 12L18 16`,key:`1r0oui`}],[`path`,{d:`M2 12H22`,key:`1m8cig`}]]};D.node;var O=r(D),k={name:`move-left`,size:24,node:[[`path`,{d:`M6 8L2 12L6 16`,key:`kyvwex`}],[`path`,{d:`M2 12H22`,key:`1m8cig`}]]};k.node;var A=r(k),j=t(e(),1);function M({currentView:e,setCurrentView:t,setIsDirty:n,showToast:r}){return{handleToggleColumn:(0,j.useCallback)(i=>{if(!e)return;let a=e.visibleFieldKeys||[],o;if(a.includes(i)){if(a.length<=1){r({type:`error`,title:`В представлении должна быть минимум 1 колонка`});return}o=a.filter(e=>e!==i)}else o=[...a,i];t({...e,visibleFieldKeys:o}),n(!0)},[e,t,n,r]),handleMoveColumn:(0,j.useCallback)((r,i)=>{if(!e)return;let a=[...e.visibleFieldKeys],[o]=a.splice(r,1);a.splice(i,0,o),t({...e,visibleFieldKeys:a}),n(!0)},[e,t,n])}}var N=a(),P=()=>{let{entityCode:e}=b(),t=v(),{currentEntity:r,views:a,saveView:C,deleteView:T}=h(e),{showToast:D}=o(),k=(0,j.useMemo)(()=>r?.fields||[],[r]),P=(0,j.useMemo)(()=>{let e=new Map;return k.forEach(t=>e.set(t.key,t)),e},[k]),[F,I]=(0,j.useState)(``),[L,R]=(0,j.useState)(null),[z,B]=(0,j.useState)(!1),[V,H]=(0,j.useState)(!1),[U,W]=(0,j.useState)(``),[G,K]=(0,j.useState)([]);(0,j.useEffect)(()=>{Promise.resolve().then(()=>{if(r&&r.fields&&r.fields.length!==0){if(!a||a.length===0){if(e){let t={id:`view_${e}_default`,entityCode:e,name:`Все записи`,type:`table`,isDefault:!0,visibleFieldKeys:r.fields.slice(0,6).map(e=>e.key),filters:[],filterConjunction:`AND`,sortBy:`updatedAt`,sortOrder:`desc`};R(t),I(t.id)}return}if(F){let e=a.find(e=>e.id===F);if(e&&!z){let t=e.visibleFieldKeys&&e.visibleFieldKeys.length>0?e.visibleFieldKeys:r.fields.slice(0,6).map(e=>e.key);R({...e,visibleFieldKeys:t})}}else{let e=a.find(e=>e.isDefault)||a[0],t=e.visibleFieldKeys&&e.visibleFieldKeys.length>0?e.visibleFieldKeys:r.fields.slice(0,6).map(e=>e.key);I(e.id),R({...e,visibleFieldKeys:t})}}})},[a,F,e,r,z]);let q=(0,j.useCallback)(async()=>{if(!e)return;let t=await s(e,{pageSize:50});K(t.items)},[e]);(0,j.useEffect)(()=>{Promise.resolve().then(()=>{q()})},[q]);let J=(0,j.useMemo)(()=>{if(!L)return G;let e=[...G];if(L.filters&&L.filters.length>0){let t=L.filterConjunction||`AND`;e=e.filter(e=>{let n=L.filters.map(t=>{let n=e[t.field],r=t.value;switch(t.operator){case`eq`:return String(n??``).toLowerCase()===String(r??``).toLowerCase();case`neq`:return String(n??``).toLowerCase()!==String(r??``).toLowerCase();case`contains`:return String(n??``).toLowerCase().includes(String(r??``).toLowerCase());case`gt`:return Number(n)>Number(r);case`lt`:return Number(n)<Number(r);case`is_empty`:return n==null||n===``;case`is_not_empty`:return n!=null&&n!==``;default:return!0}});return t===`AND`?n.every(Boolean):n.some(Boolean)})}if(L.sortBy){let{sortBy:t,sortOrder:n=`asc`}=L;e.sort((e,r)=>{let i=e[t],a=r[t];if(i===a)return 0;if(i==null)return 1;if(a==null)return-1;let o=i>a?1:-1;return n===`desc`?-o:o})}return e},[G,L]),{handleToggleColumn:Y,handleMoveColumn:X}=M({currentView:L,setCurrentView:R,setIsDirty:B,showToast:D}),Z=()=>{if(!L)return;let e={field:k[0]?.key||`name`,operator:`contains`,value:``};R({...L,filters:[...L.filters||[],e]}),B(!0)},Q=(e,t)=>{if(!L)return;let n=[...L.filters||[]];n[e]={...n[e],...t},R({...L,filters:n}),B(!0)},$=e=>{L&&(R({...L,filters:L.filters.filter((t,n)=>n!==e)}),B(!0))};return(0,N.jsxs)(`div`,{className:`space-y-4 animate-fade-in`,children:[(0,N.jsxs)(`div`,{className:`flex flex-col md:flex-row md:items-center justify-between gap-3 p-4 bg-krona-surface border border-krona-border rounded-xl shadow-krona-soft`,children:[(0,N.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,N.jsxs)(n,{variant:`ghost`,size:`sm`,onClick:()=>t(`/settings/entities`),className:`p-1.5`,children:[(0,N.jsx)(p,{className:`w-4 h-4 mr-1`}),`Каталог`]}),(0,N.jsxs)(`div`,{children:[(0,N.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,N.jsx)(f,{className:`w-4 h-4 text-krona-green`}),(0,N.jsxs)(`h1`,{className:`text-base font-bold text-krona-primary`,children:[`Конструктор представлений: `,r?.name||e]}),z&&(0,N.jsx)(i,{variant:`warning`,size:`sm`,children:`Несохранённые изменения`})]}),(0,N.jsx)(`p`,{className:`text-xs text-krona-secondary`,children:`Настройка колонок таблицы, расширенной фильтрации (AND/OR), сортировки и сохранённых видов`})]})]}),(0,N.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,N.jsxs)(n,{variant:`outline`,size:`sm`,onClick:()=>{if(!L||J.length===0){D({type:`info`,title:`Нет записей для экспорта`});return}let t=L.visibleFieldKeys.map(e=>P.get(e)||{key:e,label:e}),n=``+[t.map(e=>`"${e.label.replace(/"/g,`""`)}"`).join(`,`),...J.map(e=>t.map(t=>{let n=e[t.key];return n==null?`""`:`"${String(n).replace(/"/g,`""`)}"`}).join(`,`))].join(`\r
`),r=new Blob([n],{type:`text/csv;charset=utf-8;`}),i=URL.createObjectURL(r),a=document.createElement(`a`);a.setAttribute(`href`,i),a.setAttribute(`download`,`${e}_export_${new Date().toISOString().slice(0,10)}.csv`),document.body.appendChild(a),a.click(),document.body.removeChild(a),D({type:`success`,title:`Файл CSV успешно сформирован и загружен`})},children:[(0,N.jsx)(l,{className:`w-3.5 h-3.5 mr-1`}),`Экспорт CSV`]}),(0,N.jsxs)(n,{variant:`primary`,size:`sm`,"data-testid":`save-view-btn`,onClick:async()=>{if(L)try{await C(L),B(!1),D({type:`success`,title:`Представление «${L.name}» сохранено`})}catch(e){D({type:`error`,title:`Ошибка сохранения представления`,message:e instanceof Error?e.message:String(e)})}},disabled:!L,children:[(0,N.jsx)(d,{className:`w-3.5 h-3.5 mr-1`}),`Сохранить вид`]})]})]}),(0,N.jsxs)(`div`,{className:`flex items-center justify-between gap-2 p-2 bg-krona-surface border border-krona-border rounded-xl overflow-x-auto`,children:[(0,N.jsxs)(`div`,{className:`flex items-center gap-1`,children:[a.map(e=>(0,N.jsxs)(`button`,{onClick:()=>{I(e.id),R({...e}),B(!1)},className:`px-3 py-1.5 rounded-lg text-xs font-medium cursor-pointer transition-all flex items-center gap-1.5 ${F===e.id?`bg-krona-green text-white shadow-sm`:`bg-krona-workspace text-krona-secondary hover:text-krona-primary`}`,children:[(0,N.jsx)(`span`,{children:e.name}),e.isDefault&&(0,N.jsx)(`span`,{className:`text-[10px] opacity-80`,title:`По умолчанию`,children:`★`})]},e.id)),(0,N.jsxs)(`button`,{onClick:()=>H(!0),className:`px-2.5 py-1.5 rounded-lg text-xs font-medium bg-krona-workspace hover:bg-krona-surface-muted text-krona-secondary hover:text-krona-primary flex items-center gap-1 border border-dashed border-krona-border cursor-pointer`,children:[(0,N.jsx)(m,{className:`w-3 h-3`}),`Создать вид`]})]}),L&&!L.isDefault&&(0,N.jsxs)(`button`,{onClick:async()=>{if(L){if(L.isDefault){D({type:`error`,title:`Нельзя удалить представление по умолчанию`});return}if(confirm(`Удалить сохранённое представление «${L.name}»?`))try{await T(L.id),D({type:`success`,title:`Представление удалено`}),I(``),R(null)}catch(e){D({type:`error`,title:`Ошибка удаления`,message:e instanceof Error?e.message:String(e)})}}},className:`text-xs text-krona-danger hover:underline px-2 py-1 flex items-center gap-1 cursor-pointer`,children:[(0,N.jsx)(x,{className:`w-3.5 h-3.5`}),`Удалить этот вид`]})]}),L&&(0,N.jsxs)(`div`,{className:`grid grid-cols-1 lg:grid-cols-12 gap-4`,children:[(0,N.jsxs)(`div`,{className:`lg:col-span-4 space-y-4`,children:[(0,N.jsxs)(`div`,{className:`p-3.5 bg-krona-surface border border-krona-border rounded-xl space-y-3`,children:[(0,N.jsx)(_,{label:`Название представления`,value:L.name,onChange:e=>{R({...L,name:e.target.value}),B(!0)}}),(0,N.jsxs)(`label`,{className:`flex items-center gap-2 cursor-pointer text-xs font-medium text-krona-primary`,children:[(0,N.jsx)(`input`,{type:`checkbox`,checked:L.isDefault||!1,onChange:e=>{R({...L,isDefault:e.target.checked}),B(!0)},className:`rounded text-krona-green`}),`Представление по умолчанию для всех`]})]}),(0,N.jsxs)(`div`,{className:`p-3.5 bg-krona-surface border border-krona-border rounded-xl space-y-3`,children:[(0,N.jsx)(`div`,{className:`flex items-center justify-between`,children:(0,N.jsxs)(`span`,{className:`text-xs font-bold text-krona-primary uppercase tracking-wider flex items-center gap-1.5`,children:[(0,N.jsx)(w,{className:`w-3.5 h-3.5 text-krona-green`}),`Колонки таблицы (`,L.visibleFieldKeys.length,`)`]})}),(0,N.jsx)(`div`,{className:`space-y-1.5 max-h-56 overflow-y-auto pr-1`,children:L.visibleFieldKeys.map((e,t)=>{let n=P.get(e);return(0,N.jsxs)(`div`,{"data-testid":`column-pill-${e}`,draggable:!0,onDragStart:e=>{e.dataTransfer.setData(`text/plain`,String(t))},onDragOver:e=>e.preventDefault(),onDrop:e=>{e.preventDefault();let n=Number(e.dataTransfer.getData(`text/plain`));!isNaN(n)&&n!==t&&X(n,t)},className:`flex items-center justify-between p-2 rounded bg-krona-workspace text-xs border border-krona-border/60 cursor-grab active:cursor-grabbing`,children:[(0,N.jsx)(`span`,{className:`font-medium text-krona-primary truncate`,children:n?.label||e}),(0,N.jsxs)(`div`,{className:`flex items-center gap-1`,children:[(0,N.jsx)(`button`,{type:`button`,onClick:()=>X(t,t-1),disabled:t===0,className:`p-1 text-krona-secondary hover:text-krona-primary disabled:opacity-20`,title:`Влево`,children:(0,N.jsx)(A,{className:`w-3 h-3`})}),(0,N.jsx)(`button`,{type:`button`,onClick:()=>X(t,t+1),disabled:t===L.visibleFieldKeys.length-1,className:`p-1 text-krona-secondary hover:text-krona-primary disabled:opacity-20`,title:`Вправо`,children:(0,N.jsx)(O,{className:`w-3 h-3`})}),(0,N.jsx)(`button`,{type:`button`,onClick:()=>Y(e),className:`p-1 text-krona-danger hover:bg-krona-danger/10 rounded`,title:`Скрыть колонку`,children:`✕`})]})]},e)})}),(0,N.jsxs)(`div`,{className:`pt-2 border-t border-krona-border/60`,children:[(0,N.jsx)(`span`,{className:`text-[11px] font-semibold text-krona-secondary block mb-1.5`,children:`Доступные поля сущности:`}),(0,N.jsx)(`div`,{className:`space-y-1 max-h-36 overflow-y-auto text-xs`,children:k.map(e=>{let t=L.visibleFieldKeys.includes(e.key);return(0,N.jsxs)(`label`,{className:`flex items-center gap-2 p-1 rounded hover:bg-krona-workspace cursor-pointer`,children:[(0,N.jsx)(`input`,{type:`checkbox`,checked:t,onChange:()=>Y(e.key),className:`rounded text-krona-green`}),(0,N.jsx)(`span`,{className:`truncate text-krona-primary`,children:e.label}),(0,N.jsx)(`span`,{className:`text-[10px] font-mono text-krona-secondary ml-auto`,children:e.key})]},e.key)})})]})]}),(0,N.jsxs)(`div`,{className:`p-3.5 bg-krona-surface border border-krona-border rounded-xl space-y-3`,children:[(0,N.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,N.jsxs)(`span`,{className:`text-xs font-bold text-krona-primary uppercase tracking-wider flex items-center gap-1.5`,children:[(0,N.jsx)(E,{className:`w-3.5 h-3.5 text-krona-gold`}),`Фильтрация (`,L.filters?.length||0,`)`]}),(0,N.jsx)(`div`,{className:`flex items-center gap-1 bg-krona-workspace rounded p-0.5 border border-krona-border`,children:[`AND`,`OR`].map(e=>(0,N.jsx)(`button`,{onClick:()=>{R({...L,filterConjunction:e}),B(!0)},className:`px-2 py-0.5 text-[10px] font-bold rounded ${(L.filterConjunction||`AND`)===e?`bg-krona-green text-white`:`text-krona-secondary`}`,children:e===`AND`?`И`:`ИЛИ`},e))})]}),(0,N.jsx)(`div`,{className:`space-y-2`,children:L.filters?.map((e,t)=>(0,N.jsxs)(`div`,{className:`p-2 bg-krona-workspace rounded-lg border border-krona-border/60 space-y-1.5`,children:[(0,N.jsxs)(`div`,{className:`flex items-center justify-between gap-1`,children:[(0,N.jsx)(`select`,{value:e.field,onChange:e=>Q(t,{field:e.target.value}),className:`bg-krona-surface text-krona-primary border border-krona-border rounded px-2 py-1 text-xs w-full`,children:k.map(e=>(0,N.jsx)(`option`,{value:e.key,children:e.label},e.key))}),(0,N.jsx)(`button`,{type:`button`,onClick:()=>$(t),className:`p-1 text-krona-danger hover:bg-krona-danger/10 rounded`,title:`Удалить фильтр`,children:(0,N.jsx)(x,{className:`w-3.5 h-3.5`})})]}),(0,N.jsxs)(`div`,{className:`grid grid-cols-2 gap-1.5`,children:[(0,N.jsxs)(`select`,{value:e.operator,onChange:e=>Q(t,{operator:e.target.value}),className:`bg-krona-surface text-krona-primary border border-krona-border rounded px-2 py-1 text-xs`,children:[(0,N.jsx)(`option`,{value:`contains`,children:`содержит`}),(0,N.jsx)(`option`,{value:`eq`,children:`равно`}),(0,N.jsx)(`option`,{value:`neq`,children:`не равно`}),(0,N.jsx)(`option`,{value:`gt`,children:`больше (>)`}),(0,N.jsx)(`option`,{value:`lt`,children:`меньше (<)`}),(0,N.jsx)(`option`,{value:`is_empty`,children:`пусто`}),(0,N.jsx)(`option`,{value:`is_not_empty`,children:`не пусто`})]}),e.operator!==`is_empty`&&e.operator!==`is_not_empty`&&(0,N.jsx)(`input`,{type:`text`,placeholder:`Значение...`,value:String(e.value??``),onChange:e=>Q(t,{value:e.target.value}),className:`bg-krona-surface text-krona-primary border border-krona-border rounded px-2 py-1 text-xs`})]})]},t))}),(0,N.jsxs)(n,{variant:`outline`,size:`sm`,className:`w-full text-xs`,onClick:Z,children:[(0,N.jsx)(m,{className:`w-3 h-3 mr-1`}),`Добавить условие`]})]}),(0,N.jsxs)(`div`,{className:`p-3.5 bg-krona-surface border border-krona-border rounded-xl space-y-2`,children:[(0,N.jsxs)(`span`,{className:`text-xs font-bold text-krona-primary uppercase tracking-wider flex items-center gap-1.5`,children:[(0,N.jsx)(c,{className:`w-3.5 h-3.5 text-krona-info`}),`Сортировка`]}),(0,N.jsxs)(`div`,{className:`grid grid-cols-2 gap-2`,children:[(0,N.jsxs)(`select`,{value:L.sortBy||``,onChange:e=>{R({...L,sortBy:e.target.value}),B(!0)},className:`bg-krona-surface text-krona-primary border border-krona-border rounded px-2 py-1.5 text-xs`,children:[(0,N.jsx)(`option`,{value:``,children:`Без сортировки`}),k.map(e=>(0,N.jsx)(`option`,{value:e.key,children:e.label},e.key))]}),(0,N.jsxs)(`select`,{value:L.sortOrder||`asc`,onChange:e=>{R({...L,sortOrder:e.target.value}),B(!0)},className:`bg-krona-surface text-krona-primary border border-krona-border rounded px-2 py-1.5 text-xs`,children:[(0,N.jsx)(`option`,{value:`asc`,children:`По возрастанию (А-Я)`}),(0,N.jsx)(`option`,{value:`desc`,children:`По убыванию (Я-А)`})]})]})]})]}),(0,N.jsx)(`div`,{className:`lg:col-span-8 space-y-3`,children:(0,N.jsxs)(`div`,{className:`p-3.5 bg-krona-surface border border-krona-border rounded-xl shadow-krona-soft space-y-3`,children:[(0,N.jsxs)(`div`,{className:`flex items-center justify-between text-xs`,children:[(0,N.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,N.jsx)(u,{className:`w-4 h-4 text-krona-gold`}),(0,N.jsx)(`span`,{className:`font-semibold text-krona-primary`,children:`Интерактивное превью таблицы данных`})]}),(0,N.jsxs)(`span`,{className:`text-krona-secondary`,children:[`Отображается записей: `,(0,N.jsx)(`strong`,{children:J.length}),` (всего в базе:`,` `,G.length,`)`]})]}),(0,N.jsx)(`div`,{className:`overflow-x-auto border border-krona-border rounded-lg max-h-[550px]`,children:(0,N.jsxs)(`table`,{className:`w-full text-left text-xs border-collapse`,children:[(0,N.jsx)(`thead`,{className:`bg-krona-workspace sticky top-0 border-b border-krona-border`,children:(0,N.jsx)(`tr`,{children:L.visibleFieldKeys.map(e=>{let t=P.get(e);return(0,N.jsx)(`th`,{className:`p-2.5 font-semibold text-krona-primary border-r border-krona-border/60 last:border-r-0 whitespace-nowrap`,children:t?.label||e},e)})})}),(0,N.jsxs)(`tbody`,{className:`divide-y divide-krona-border/60 bg-krona-surface`,children:[J.map(e=>(0,N.jsx)(`tr`,{className:`hover:bg-krona-workspace/50 transition-colors`,children:L.visibleFieldKeys.map(t=>{let n=P.get(t),r=e[t],a=`—`;return r!=null&&r!==``&&(a=n?.type===`money`?typeof r==`number`?S(r):String(r):n?.type===`boolean`?r?`Да`:`Нет`:n?.type===`date`||n?.type===`datetime`?g(String(r)):String(r)),(0,N.jsx)(`td`,{className:`p-2.5 text-krona-secondary truncate max-w-xs border-r border-krona-border/40 last:border-r-0`,children:t===`status`?(0,N.jsx)(i,{variant:`neutral`,size:`sm`,children:a}):(0,N.jsx)(`span`,{className:`text-krona-primary font-medium`,children:a})},t)})},e.id)),J.length===0&&(0,N.jsx)(`tr`,{children:(0,N.jsx)(`td`,{colSpan:L.visibleFieldKeys.length,className:`text-center py-10 text-krona-secondary`,children:`Записи не найдены или отфильтрованы`})})]})]})})]})})]}),(0,N.jsx)(y,{isOpen:V,onClose:()=>H(!1),title:`Новое представление`,subtitle:`Создайте сохранённый вид таблицы с индивидуальными фильтрами и колонками`,maxWidth:`sm`,children:(0,N.jsxs)(`div`,{className:`space-y-4`,children:[(0,N.jsx)(_,{label:`Название представления *`,value:U,onChange:e=>W(e.target.value),placeholder:`Например: Мои активные заявки`,autoFocus:!0}),(0,N.jsxs)(`div`,{className:`flex justify-end gap-2 pt-3 border-t border-krona-border`,children:[(0,N.jsx)(n,{variant:`outline`,size:`sm`,onClick:()=>H(!1),children:`Отмена`}),(0,N.jsx)(n,{variant:`primary`,size:`sm`,onClick:async()=>{if(!U.trim()||!e)return;let t=`view_${Date.now().toString(36)}`,n={id:t,entityCode:e,name:U.trim(),type:`table`,isDefault:!1,visibleFieldKeys:k.slice(0,5).map(e=>e.key),filters:[],filterConjunction:`AND`};try{await C(n),I(t),R(n),H(!1),W(``),D({type:`success`,title:`Представление «${n.name}» создано`})}catch(e){D({type:`error`,title:`Ошибка создания представления`,message:e instanceof Error?e.message:String(e)})}},children:`Создать`})]})]})})]})};export{P as ViewBuilder,P as default};