@fayz-ai/plugin-forms 0.1.5 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/config.d.ts +4 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/data/supabase.d.ts.map +1 -1
- package/dist/data/tables.d.ts +7 -0
- package/dist/data/tables.d.ts.map +1 -0
- package/dist/index.cjs +49 -32
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +52 -35
- package/dist/index.js.map +1 -1
- package/dist/migrations/index.d.ts +8 -0
- package/dist/migrations/index.d.ts.map +1 -0
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/views/CustomFormsSettingsTab.d.ts +1 -3
- package/dist/views/CustomFormsSettingsTab.d.ts.map +1 -1
- package/package.json +10 -6
- package/src/config.ts +5 -1
- package/src/data/supabase.ts +20 -19
- package/src/data/tables.ts +7 -0
- package/src/index.ts +22 -4
- package/src/migrations/000_plg_rename.sql +21 -0
- package/src/migrations/001_frm_base.sql +92 -56
- package/src/migrations/002_document_archetype.sql +130 -42
- package/src/migrations/index.ts +433 -0
- package/src/types.ts +4 -4
- package/src/views/CustomFormsSettingsTab.tsx +2 -19
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAUnD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAA;AAyCxD,YAAY,EAAE,wBAAwB,EAAE,CAAA;AACxC,OAAO,EAAE,4BAA4B,EAAE,KAAK,kBAAkB,EAAE,KAAK,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AAEnH,wBAAgB,uBAAuB,CAAC,OAAO,CAAC,EAAE,wBAAwB,GAAG,cAAc,CA6J1F"}
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
import { FormRenderer } from './chunk-32I43T37.js';
|
|
2
2
|
import React2, { useState, useCallback, useRef, useEffect } from 'react';
|
|
3
3
|
import { registerTranslations, createSafeDataProvider, useTranslation, getSupabaseClientOptional, getActiveTenantId } from '@fayz-ai/core';
|
|
4
|
+
import { PluginSettingsPanel } from '@fayz-ai/saas';
|
|
4
5
|
import { create } from 'zustand';
|
|
5
|
-
import { FileText, Image, Paperclip,
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
6
|
+
import { FileText, Image, Paperclip, Search, Plus, Pencil, Trash2, ArrowLeft, Loader2, Save, ChevronDown, Upload, Eye } from 'lucide-react';
|
|
7
|
+
import { Input, Button, Card, CardContent, Badge, useSaveBar, Dropdown, DropdownTrigger, DropdownContent, DropdownSeparator, DropdownLabel, DropdownItem } from '@fayz-ai/ui';
|
|
8
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
9
|
+
|
|
10
|
+
// src/data/tables.ts
|
|
11
|
+
var T = {
|
|
12
|
+
documents: "plg_forms_documents",
|
|
13
|
+
templates: "plg_forms_templates",
|
|
14
|
+
documentFiles: "plg_forms_document_files",
|
|
15
|
+
categories: "plg_forms_categories"
|
|
16
|
+
};
|
|
8
17
|
|
|
9
18
|
// src/data/mock.ts
|
|
10
19
|
function uuid() {
|
|
@@ -254,7 +263,7 @@ function createSupabaseFormsProvider() {
|
|
|
254
263
|
// ── Templates ──────────────────────────────────────────
|
|
255
264
|
async getTemplates(query) {
|
|
256
265
|
const db = getClient();
|
|
257
|
-
let qb = db.from(
|
|
266
|
+
let qb = db.from(T.templates).select("*", { count: "exact" }).eq("tenant_id", getTenantId()).eq("is_current", true).eq("is_deleted", false);
|
|
258
267
|
if (query.category) qb = qb.eq("category", query.category);
|
|
259
268
|
if (query.search) qb = qb.ilike("name", `%${query.search}%`);
|
|
260
269
|
const page = query.page ?? 1;
|
|
@@ -266,14 +275,14 @@ function createSupabaseFormsProvider() {
|
|
|
266
275
|
},
|
|
267
276
|
async getTemplateById(id) {
|
|
268
277
|
const db = getClient();
|
|
269
|
-
const { data, error } = await db.from(
|
|
278
|
+
const { data, error } = await db.from(T.templates).select("*").eq("id", id).eq("is_deleted", false).single();
|
|
270
279
|
if (error || !data) return null;
|
|
271
280
|
return mapTemplate(data);
|
|
272
281
|
},
|
|
273
282
|
async createTemplate(input) {
|
|
274
283
|
const db = getClient();
|
|
275
284
|
const tenantId = getTenantId();
|
|
276
|
-
const { data, error } = await db.from(
|
|
285
|
+
const { data, error } = await db.from(T.templates).insert({
|
|
277
286
|
tenant_id: tenantId,
|
|
278
287
|
name: input.name,
|
|
279
288
|
description: input.description,
|
|
@@ -289,12 +298,12 @@ function createSupabaseFormsProvider() {
|
|
|
289
298
|
async updateTemplate(id, input) {
|
|
290
299
|
const db = getClient();
|
|
291
300
|
const tenantId = getTenantId();
|
|
292
|
-
const { count } = await db.from(
|
|
301
|
+
const { count } = await db.from(T.documents).select("document_id", { count: "exact", head: true }).eq("template_id", id);
|
|
293
302
|
const hasDocuments = (count ?? 0) > 0;
|
|
294
303
|
if (hasDocuments && input.schema) {
|
|
295
304
|
const existing = await this.getTemplateById(id);
|
|
296
305
|
if (!existing) throw new Error("Template not found");
|
|
297
|
-
const { data: newRow, error: insertError } = await db.from(
|
|
306
|
+
const { data: newRow, error: insertError } = await db.from(T.templates).insert({
|
|
298
307
|
tenant_id: tenantId,
|
|
299
308
|
name: input.name ?? existing.name,
|
|
300
309
|
description: input.description ?? existing.description,
|
|
@@ -309,7 +318,7 @@ function createSupabaseFormsProvider() {
|
|
|
309
318
|
parent_id: existing.parentId ?? existing.id
|
|
310
319
|
}).select().single();
|
|
311
320
|
if (insertError) throw new Error(insertError.message);
|
|
312
|
-
await db.from(
|
|
321
|
+
await db.from(T.templates).update({ is_current: false, updated_at: (/* @__PURE__ */ new Date()).toISOString() }).eq("id", id);
|
|
313
322
|
return mapTemplate(newRow);
|
|
314
323
|
}
|
|
315
324
|
const updates = { updated_at: (/* @__PURE__ */ new Date()).toISOString() };
|
|
@@ -321,16 +330,16 @@ function createSupabaseFormsProvider() {
|
|
|
321
330
|
if (input.tags !== void 0) updates.tags = input.tags;
|
|
322
331
|
if (input.metadata !== void 0) updates.metadata = input.metadata;
|
|
323
332
|
if (input.isActive !== void 0) updates.is_active = input.isActive;
|
|
324
|
-
const { data, error } = await db.from(
|
|
333
|
+
const { data, error } = await db.from(T.templates).update(updates).eq("id", id).select().single();
|
|
325
334
|
if (error) throw new Error(error.message);
|
|
326
335
|
return mapTemplate(data);
|
|
327
336
|
},
|
|
328
337
|
async deleteTemplate(id) {
|
|
329
338
|
const db = getClient();
|
|
330
|
-
const { error } = await db.from(
|
|
339
|
+
const { error } = await db.from(T.templates).update({ is_deleted: true, updated_at: (/* @__PURE__ */ new Date()).toISOString() }).eq("id", id);
|
|
331
340
|
if (error) throw new Error(error.message);
|
|
332
341
|
},
|
|
333
|
-
// ── Documents (
|
|
342
|
+
// ── Documents (public.documents + plg_forms_documents extension) ──
|
|
334
343
|
async getDocuments(query) {
|
|
335
344
|
const db = getClient();
|
|
336
345
|
let qb = db.from("v_documents").select("*", { count: "exact" }).eq("tenant_id", getTenantId()).eq("is_active", true);
|
|
@@ -357,7 +366,7 @@ function createSupabaseFormsProvider() {
|
|
|
357
366
|
async createDocument(input) {
|
|
358
367
|
const tenantId = getTenantId();
|
|
359
368
|
const isForm = !!input.templateId;
|
|
360
|
-
const { data: coreDoc, error: coreError } = await getClient().from("
|
|
369
|
+
const { data: coreDoc, error: coreError } = await getClient().from("documents").insert({
|
|
361
370
|
tenant_id: tenantId,
|
|
362
371
|
kind: input.kind ?? (isForm ? "form" : "attachment"),
|
|
363
372
|
person_id: input.personId,
|
|
@@ -372,14 +381,14 @@ function createSupabaseFormsProvider() {
|
|
|
372
381
|
if (coreError) throw new Error(coreError.message);
|
|
373
382
|
if (isForm && input.templateId) {
|
|
374
383
|
const db = getClient();
|
|
375
|
-
const { error: extError } = await db.from(
|
|
384
|
+
const { error: extError } = await db.from(T.documents).insert({
|
|
376
385
|
document_id: coreDoc.id,
|
|
377
386
|
tenant_id: tenantId,
|
|
378
387
|
template_id: input.templateId,
|
|
379
388
|
data: input.data ?? {}
|
|
380
389
|
});
|
|
381
390
|
if (extError) {
|
|
382
|
-
await getClient().from("
|
|
391
|
+
await getClient().from("documents").delete().eq("id", coreDoc.id);
|
|
383
392
|
throw new Error(extError.message);
|
|
384
393
|
}
|
|
385
394
|
}
|
|
@@ -392,23 +401,23 @@ function createSupabaseFormsProvider() {
|
|
|
392
401
|
if (input.status !== void 0) coreUpdates.status = input.status;
|
|
393
402
|
if (input.title !== void 0) coreUpdates.title = input.title;
|
|
394
403
|
if (input.notes !== void 0) coreUpdates.notes = input.notes;
|
|
395
|
-
const { error: coreError } = await getClient().from("
|
|
404
|
+
const { error: coreError } = await getClient().from("documents").update(coreUpdates).eq("id", id);
|
|
396
405
|
if (coreError) throw new Error(coreError.message);
|
|
397
406
|
if (input.data !== void 0) {
|
|
398
407
|
const db = getClient();
|
|
399
|
-
await db.from(
|
|
408
|
+
await db.from(T.documents).update({ data: input.data, updated_at: now2 }).eq("document_id", id);
|
|
400
409
|
}
|
|
401
410
|
const doc = await this.getDocumentById(id);
|
|
402
411
|
return doc;
|
|
403
412
|
},
|
|
404
413
|
async deleteDocument(id) {
|
|
405
|
-
const { error } = await getClient().from("
|
|
414
|
+
const { error } = await getClient().from("documents").update({ is_active: false, updated_at: (/* @__PURE__ */ new Date()).toISOString() }).eq("id", id);
|
|
406
415
|
if (error) throw new Error(error.message);
|
|
407
416
|
},
|
|
408
417
|
// ── Files ──────────────────────────────────────────────
|
|
409
418
|
async getDocumentFiles(documentId) {
|
|
410
419
|
const db = getClient();
|
|
411
|
-
const { data, error } = await db.from(
|
|
420
|
+
const { data, error } = await db.from(T.documentFiles).select("*").eq("document_id", documentId).order("sort_order");
|
|
412
421
|
if (error) throw new Error(error.message);
|
|
413
422
|
return (data ?? []).map(mapFile);
|
|
414
423
|
},
|
|
@@ -420,7 +429,7 @@ function createSupabaseFormsProvider() {
|
|
|
420
429
|
const { error: uploadError } = await db.storage.from("documents").upload(storagePath, file, { contentType: file.type });
|
|
421
430
|
if (uploadError) throw new Error(uploadError.message);
|
|
422
431
|
const { data: urlData } = db.storage.from("documents").getPublicUrl(storagePath);
|
|
423
|
-
const { data, error } = await db.from(
|
|
432
|
+
const { data, error } = await db.from(T.documentFiles).insert({
|
|
424
433
|
tenant_id: tenantId,
|
|
425
434
|
document_id: documentId,
|
|
426
435
|
field_key: fieldKey,
|
|
@@ -434,7 +443,7 @@ function createSupabaseFormsProvider() {
|
|
|
434
443
|
},
|
|
435
444
|
async deleteFile(fileId) {
|
|
436
445
|
const db = getClient();
|
|
437
|
-
const { error } = await db.from(
|
|
446
|
+
const { error } = await db.from(T.documentFiles).delete().eq("id", fileId);
|
|
438
447
|
if (error) throw new Error(error.message);
|
|
439
448
|
}
|
|
440
449
|
};
|
|
@@ -694,6 +703,7 @@ var customFormsLocales = {
|
|
|
694
703
|
var DEFAULT_LABELS = {
|
|
695
704
|
pageTitle: "Custom Forms",
|
|
696
705
|
settingsLabel: "Forms & Documents",
|
|
706
|
+
settingsSubtitle: "Create and manage custom forms for your business",
|
|
697
707
|
templates: "Templates",
|
|
698
708
|
documents: "Documents",
|
|
699
709
|
newTemplate: "New Template",
|
|
@@ -815,8 +825,7 @@ function TemplateListView({ store, config, onEdit, onNew }) {
|
|
|
815
825
|
] }) }, i)) })
|
|
816
826
|
] });
|
|
817
827
|
}
|
|
818
|
-
function CustomFormsSettingsTab({ config, provider, store
|
|
819
|
-
const t = useTranslation();
|
|
828
|
+
function CustomFormsSettingsTab({ config, provider, store }) {
|
|
820
829
|
const [builderTemplateId, setBuilderTemplateId] = useState(null);
|
|
821
830
|
const handleNew = useCallback(() => {
|
|
822
831
|
setBuilderTemplateId("__new__");
|
|
@@ -840,7 +849,7 @@ function CustomFormsSettingsTab({ config, provider, store, registries }) {
|
|
|
840
849
|
}
|
|
841
850
|
checkHash();
|
|
842
851
|
}, []);
|
|
843
|
-
|
|
852
|
+
return builderTemplateId ? /* @__PURE__ */ jsx(
|
|
844
853
|
BuilderWrapper,
|
|
845
854
|
{
|
|
846
855
|
templateId: builderTemplateId === "__new__" ? void 0 : builderTemplateId,
|
|
@@ -858,13 +867,6 @@ function CustomFormsSettingsTab({ config, provider, store, registries }) {
|
|
|
858
867
|
onNew: handleNew
|
|
859
868
|
}
|
|
860
869
|
);
|
|
861
|
-
return /* @__PURE__ */ jsxs("div", { style: { padding: "24px" }, children: [
|
|
862
|
-
/* @__PURE__ */ jsxs("div", { style: { marginBottom: "16px" }, children: [
|
|
863
|
-
/* @__PURE__ */ jsx("h1", { style: { fontSize: "20px", fontWeight: 600, margin: 0 }, children: t("customForms.settingsTitle") }),
|
|
864
|
-
/* @__PURE__ */ jsx("p", { style: { color: "var(--muted-foreground, #6b7280)", margin: "4px 0 0", fontSize: "14px" }, children: t("customForms.settingsSubtitle") })
|
|
865
|
-
] }),
|
|
866
|
-
templatesContent
|
|
867
|
-
] });
|
|
868
870
|
}
|
|
869
871
|
function BuilderWrapper({
|
|
870
872
|
templateId,
|
|
@@ -1499,7 +1501,7 @@ function createCustomFormsPlugin(options) {
|
|
|
1499
1501
|
{ key: "isActive", label: "Active", type: "boolean", showInTable: true, defaultValue: true, inlineToggle: true }
|
|
1500
1502
|
],
|
|
1501
1503
|
data: {
|
|
1502
|
-
table:
|
|
1504
|
+
table: T.categories,
|
|
1503
1505
|
tenantScoped: true
|
|
1504
1506
|
}
|
|
1505
1507
|
},
|
|
@@ -1514,8 +1516,23 @@ function createCustomFormsPlugin(options) {
|
|
|
1514
1516
|
]
|
|
1515
1517
|
}
|
|
1516
1518
|
];
|
|
1517
|
-
const
|
|
1518
|
-
SettingsComponent
|
|
1519
|
+
const registries = [...formRegistries, ...options?.settingsRegistries ?? []];
|
|
1520
|
+
const SettingsComponent = () => React2.createElement(PluginSettingsPanel, {
|
|
1521
|
+
title: config.labels.settingsLabel,
|
|
1522
|
+
subtitle: config.labels.settingsSubtitle,
|
|
1523
|
+
customTabs: [
|
|
1524
|
+
{
|
|
1525
|
+
id: "forms",
|
|
1526
|
+
label: config.labels.pageTitle,
|
|
1527
|
+
icon: "FileText",
|
|
1528
|
+
content: React2.createElement(CustomFormsSettingsTab, { config, provider, store })
|
|
1529
|
+
}
|
|
1530
|
+
],
|
|
1531
|
+
registries,
|
|
1532
|
+
routeBase: "/settings/custom_forms",
|
|
1533
|
+
hostPluginId: "custom_forms"
|
|
1534
|
+
});
|
|
1535
|
+
SettingsComponent.displayName = "CustomFormsSettingsPanel";
|
|
1519
1536
|
const PersonDocumentsWidget2 = (props) => React2.createElement(PersonDocumentsWidget, { ...props, config, provider, store });
|
|
1520
1537
|
PersonDocumentsWidget2.displayName = "PersonDocumentsWidget";
|
|
1521
1538
|
return {
|
|
@@ -1549,7 +1566,7 @@ function createCustomFormsPlugin(options) {
|
|
|
1549
1566
|
order: 0
|
|
1550
1567
|
}
|
|
1551
1568
|
],
|
|
1552
|
-
registries
|
|
1569
|
+
registries,
|
|
1553
1570
|
aiTools: [
|
|
1554
1571
|
{
|
|
1555
1572
|
id: "custom_forms.list-templates",
|