@stndrds/schema 0.1.0-alpha.61 → 0.1.0-alpha.63
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/dist/{chunk-W7A7AQUF.js → chunk-KMAKDHCL.js} +158 -93
- package/dist/{chunk-533TTNPT.mjs → chunk-MUJVBSBL.mjs} +158 -93
- package/dist/index.d.mts +147 -95
- package/dist/index.d.ts +147 -95
- package/dist/index.js +43 -14
- package/dist/index.mjs +38 -9
- package/dist/{runtime-Cx6QJ4QV.d.ts → runtime-7G9tZJYC.d.ts} +72 -37
- package/dist/{runtime-D0XMDY1D.d.mts → runtime-C4U2ppAk.d.mts} +72 -37
- package/dist/runtime.d.mts +1 -1
- package/dist/runtime.d.ts +1 -1
- package/dist/runtime.js +2 -2
- package/dist/runtime.mjs +1 -1
- package/package.json +2 -2
|
@@ -7083,6 +7083,15 @@ var BaseTableTabConfig = class {
|
|
|
7083
7083
|
this.tabData.allowCreate = true;
|
|
7084
7084
|
return this;
|
|
7085
7085
|
}
|
|
7086
|
+
/**
|
|
7087
|
+
* Set creation behavior when clicking "+"
|
|
7088
|
+
* @param mode - "redirect" (navigate to detail), "inline" (empty row), or "modal" (stacked modal)
|
|
7089
|
+
* @example .createMode("inline") or .createMode("modal")
|
|
7090
|
+
*/
|
|
7091
|
+
createMode(mode) {
|
|
7092
|
+
this.tabData.createMode = mode;
|
|
7093
|
+
return this;
|
|
7094
|
+
}
|
|
7086
7095
|
/**
|
|
7087
7096
|
* Allow inline editing
|
|
7088
7097
|
*/
|
|
@@ -7688,8 +7697,6 @@ var ListViewBuilder = class {
|
|
|
7688
7697
|
this.data = {
|
|
7689
7698
|
name,
|
|
7690
7699
|
label,
|
|
7691
|
-
layout: "table",
|
|
7692
|
-
columns: [],
|
|
7693
7700
|
tabs: []
|
|
7694
7701
|
};
|
|
7695
7702
|
}
|
|
@@ -7730,82 +7737,21 @@ var ListViewBuilder = class {
|
|
|
7730
7737
|
return this;
|
|
7731
7738
|
}
|
|
7732
7739
|
/**
|
|
7733
|
-
* Set
|
|
7734
|
-
|
|
7735
|
-
table() {
|
|
7736
|
-
this.data.layout = "table";
|
|
7737
|
-
return this;
|
|
7738
|
-
}
|
|
7739
|
-
/**
|
|
7740
|
-
* Set the layout to kanban and specify the grouping attribute
|
|
7741
|
-
* @param groupByAttribute - Attribute to group by (must be a select/status type)
|
|
7742
|
-
*/
|
|
7743
|
-
kanban(groupByAttribute) {
|
|
7744
|
-
this.data.layout = "kanban";
|
|
7745
|
-
this.data.groupByAttribute = groupByAttribute;
|
|
7746
|
-
return this;
|
|
7747
|
-
}
|
|
7748
|
-
/**
|
|
7749
|
-
* Set columns to display
|
|
7750
|
-
* @example .columns("name", "email", "status", "createdAt")
|
|
7751
|
-
*/
|
|
7752
|
-
columns(...names) {
|
|
7753
|
-
this.data.columns = names;
|
|
7754
|
-
return this;
|
|
7755
|
-
}
|
|
7756
|
-
/**
|
|
7757
|
-
* Set width for a specific column in pixels
|
|
7758
|
-
* @example .columnWidth("email", 200)
|
|
7740
|
+
* Set base filters applied to ALL tabs (scoping, tenant, etc.)
|
|
7741
|
+
* @example .baseFilter({ combinator: "and", rules: [{ attribute: "tenant", operator: "is", value: "acme" }] })
|
|
7759
7742
|
*/
|
|
7760
|
-
|
|
7761
|
-
if (!this.data.columnSizing) {
|
|
7762
|
-
this.data.columnSizing = {};
|
|
7763
|
-
}
|
|
7764
|
-
this.data.columnSizing[columnName] = width;
|
|
7765
|
-
return this;
|
|
7766
|
-
}
|
|
7767
|
-
/**
|
|
7768
|
-
* Set widths for multiple columns
|
|
7769
|
-
* @example .columnWidths({ email: 200, name: 300, status: 100 })
|
|
7770
|
-
*/
|
|
7771
|
-
columnWidths(widths) {
|
|
7772
|
-
this.data.columnSizing = { ...this.data.columnSizing, ...widths };
|
|
7773
|
-
return this;
|
|
7774
|
-
}
|
|
7775
|
-
/**
|
|
7776
|
-
* Set default filters
|
|
7777
|
-
* @example .filter({ combinator: "and", rules: [{ attribute: "status", operator: "is", value: "active" }] })
|
|
7778
|
-
*/
|
|
7779
|
-
filter(filters) {
|
|
7743
|
+
baseFilter(filters) {
|
|
7780
7744
|
this.data.defaultFilters = filters;
|
|
7781
7745
|
return this;
|
|
7782
7746
|
}
|
|
7783
7747
|
/**
|
|
7784
|
-
* Add a
|
|
7785
|
-
*
|
|
7786
|
-
*/
|
|
7787
|
-
sort(attribute, direction = "asc") {
|
|
7788
|
-
if (!this.data.defaultSorts) {
|
|
7789
|
-
this.data.defaultSorts = [];
|
|
7790
|
-
}
|
|
7791
|
-
this.data.defaultSorts.push({ attribute, direction });
|
|
7792
|
-
return this;
|
|
7793
|
-
}
|
|
7794
|
-
/**
|
|
7795
|
-
* Set multiple sort rules
|
|
7796
|
-
* @example .sorts([{ attribute: "lastName", direction: "asc" }, { attribute: "firstName", direction: "asc" }])
|
|
7797
|
-
*/
|
|
7798
|
-
sorts(rules) {
|
|
7799
|
-
this.data.defaultSorts = rules;
|
|
7800
|
-
return this;
|
|
7801
|
-
}
|
|
7802
|
-
/**
|
|
7803
|
-
* Add an internal tab (filter preset)
|
|
7804
|
-
* Returns a TabConfigBuilder for chaining tab configuration
|
|
7748
|
+
* Add a tab with its own full configuration (layout, columns, filters, sorts, groupBy)
|
|
7749
|
+
* Returns a ListViewTabConfigBuilder for chaining tab configuration
|
|
7805
7750
|
* @example
|
|
7806
7751
|
* ```typescript
|
|
7807
|
-
* .tab("all", "All Contacts").
|
|
7808
|
-
* .tab("active", "Active").
|
|
7752
|
+
* .tab("all", "All Contacts").columns("name", "email").default()
|
|
7753
|
+
* .tab("active", "Active").columns("name", "email").filter({ ... })
|
|
7754
|
+
* .tab("pipeline", "Pipeline").kanban("stage").columns("name", "amount")
|
|
7809
7755
|
* ```
|
|
7810
7756
|
*/
|
|
7811
7757
|
tab(id, label) {
|
|
@@ -7825,13 +7771,8 @@ var ListViewBuilder = class {
|
|
|
7825
7771
|
if (!this.data.object) {
|
|
7826
7772
|
throw new Error("[ListViewBuilder] for() is required - specify the target object");
|
|
7827
7773
|
}
|
|
7828
|
-
if (this.data.
|
|
7829
|
-
throw new Error("[ListViewBuilder]
|
|
7830
|
-
}
|
|
7831
|
-
if (this.data.layout === "kanban" && !this.data.groupByAttribute) {
|
|
7832
|
-
throw new Error(
|
|
7833
|
-
"[ListViewBuilder] kanban() requires a groupByAttribute - specify the attribute to group by"
|
|
7834
|
-
);
|
|
7774
|
+
if (this.data.tabs.length === 0) {
|
|
7775
|
+
throw new Error("[ListViewBuilder] At least one tab is required");
|
|
7835
7776
|
}
|
|
7836
7777
|
const tabIds = /* @__PURE__ */ new Set();
|
|
7837
7778
|
for (const tab of this.data.tabs) {
|
|
@@ -7844,28 +7785,39 @@ var ListViewBuilder = class {
|
|
|
7844
7785
|
if (defaultTabs.length > 1) {
|
|
7845
7786
|
throw new Error("[ListViewBuilder] Only one tab can be marked as default");
|
|
7846
7787
|
}
|
|
7788
|
+
for (const tab of this.data.tabs) {
|
|
7789
|
+
if (tab.columns.length === 0) {
|
|
7790
|
+
throw new Error(`[ListViewBuilder] Tab "${tab.id}" must have at least one column`);
|
|
7791
|
+
}
|
|
7792
|
+
if (tab.layout === "kanban" && !tab.groupByAttribute) {
|
|
7793
|
+
throw new Error(`[ListViewBuilder] Kanban tab "${tab.id}" requires a groupByAttribute`);
|
|
7794
|
+
}
|
|
7795
|
+
}
|
|
7847
7796
|
const config = {
|
|
7848
|
-
layout: this.data.layout,
|
|
7849
|
-
columns: this.data.columns,
|
|
7850
|
-
columnSizing: this.data.columnSizing,
|
|
7851
7797
|
defaultFilters: this.data.defaultFilters ? {
|
|
7852
7798
|
id: _chunkNEVERCM3js.generateId.call(void 0, ),
|
|
7853
7799
|
combinator: this.data.defaultFilters.combinator,
|
|
7854
7800
|
rules: this.data.defaultFilters.rules
|
|
7855
7801
|
} : void 0,
|
|
7856
|
-
|
|
7857
|
-
groupByAttribute: this.data.groupByAttribute,
|
|
7858
|
-
tabs: this.data.tabs.length > 0 ? this.data.tabs.map((tab) => ({
|
|
7802
|
+
tabs: this.data.tabs.map((tab) => ({
|
|
7859
7803
|
id: tab.id,
|
|
7860
7804
|
label: tab.label,
|
|
7861
7805
|
icon: tab.icon,
|
|
7806
|
+
default: tab.default,
|
|
7807
|
+
layout: tab.layout,
|
|
7808
|
+
columns: tab.columns,
|
|
7809
|
+
columnSizing: tab.columnSizing,
|
|
7862
7810
|
filters: tab.filters ? {
|
|
7863
7811
|
id: _chunkNEVERCM3js.generateId.call(void 0, ),
|
|
7864
7812
|
combinator: tab.filters.combinator,
|
|
7865
7813
|
rules: tab.filters.rules
|
|
7866
7814
|
} : void 0,
|
|
7867
|
-
|
|
7868
|
-
|
|
7815
|
+
sorts: tab.sorts,
|
|
7816
|
+
groupByAttribute: tab.groupByAttribute,
|
|
7817
|
+
cardUserAttribute: tab.cardUserAttribute,
|
|
7818
|
+
cardDateAttribute: tab.cardDateAttribute,
|
|
7819
|
+
createMode: tab.createMode
|
|
7820
|
+
}))
|
|
7869
7821
|
};
|
|
7870
7822
|
return {
|
|
7871
7823
|
name: this.data.name,
|
|
@@ -7900,7 +7852,12 @@ var ListViewTabConfigBuilder = class _ListViewTabConfigBuilder {
|
|
|
7900
7852
|
/** @internal */
|
|
7901
7853
|
constructor(view2, id, label) {
|
|
7902
7854
|
this.view = view2;
|
|
7903
|
-
this.tabData = {
|
|
7855
|
+
this.tabData = {
|
|
7856
|
+
id,
|
|
7857
|
+
label,
|
|
7858
|
+
layout: "table",
|
|
7859
|
+
columns: []
|
|
7860
|
+
};
|
|
7904
7861
|
}
|
|
7905
7862
|
/**
|
|
7906
7863
|
* Set tab icon
|
|
@@ -7910,7 +7867,74 @@ var ListViewTabConfigBuilder = class _ListViewTabConfigBuilder {
|
|
|
7910
7867
|
return this;
|
|
7911
7868
|
}
|
|
7912
7869
|
/**
|
|
7913
|
-
*
|
|
7870
|
+
* Mark this tab as the default tab
|
|
7871
|
+
*/
|
|
7872
|
+
default() {
|
|
7873
|
+
this.tabData.default = true;
|
|
7874
|
+
return this;
|
|
7875
|
+
}
|
|
7876
|
+
/**
|
|
7877
|
+
* Set the layout to table (default)
|
|
7878
|
+
*/
|
|
7879
|
+
table() {
|
|
7880
|
+
this.tabData.layout = "table";
|
|
7881
|
+
return this;
|
|
7882
|
+
}
|
|
7883
|
+
/**
|
|
7884
|
+
* Set the layout to kanban and specify the grouping attribute
|
|
7885
|
+
* @param groupByAttribute - Attribute to group by (must be a select/status type)
|
|
7886
|
+
*/
|
|
7887
|
+
kanban(groupByAttribute) {
|
|
7888
|
+
this.tabData.layout = "kanban";
|
|
7889
|
+
this.tabData.groupByAttribute = groupByAttribute;
|
|
7890
|
+
return this;
|
|
7891
|
+
}
|
|
7892
|
+
/**
|
|
7893
|
+
* Set the user attribute to display on kanban cards (bottom-left)
|
|
7894
|
+
* @param attributeName - Name of a user-type attribute
|
|
7895
|
+
*/
|
|
7896
|
+
cardUserAttribute(attributeName) {
|
|
7897
|
+
this.tabData.cardUserAttribute = attributeName;
|
|
7898
|
+
return this;
|
|
7899
|
+
}
|
|
7900
|
+
/**
|
|
7901
|
+
* Set the date attribute to display on kanban cards (bottom-right)
|
|
7902
|
+
* @param attributeName - Name of a date-type attribute
|
|
7903
|
+
*/
|
|
7904
|
+
cardDateAttribute(attributeName) {
|
|
7905
|
+
this.tabData.cardDateAttribute = attributeName;
|
|
7906
|
+
return this;
|
|
7907
|
+
}
|
|
7908
|
+
/**
|
|
7909
|
+
* Set creation behavior when clicking "+"
|
|
7910
|
+
* @param mode - "redirect" (navigate to detail), "inline" (empty row), or "modal" (stacked modal)
|
|
7911
|
+
* @example .createMode("inline") or .createMode("modal")
|
|
7912
|
+
*/
|
|
7913
|
+
createMode(mode) {
|
|
7914
|
+
this.tabData.createMode = mode;
|
|
7915
|
+
return this;
|
|
7916
|
+
}
|
|
7917
|
+
/**
|
|
7918
|
+
* Set columns to display
|
|
7919
|
+
* @example .columns("name", "email", "status", "createdAt")
|
|
7920
|
+
*/
|
|
7921
|
+
columns(...names) {
|
|
7922
|
+
this.tabData.columns = names;
|
|
7923
|
+
return this;
|
|
7924
|
+
}
|
|
7925
|
+
/**
|
|
7926
|
+
* Set width for a specific column in pixels
|
|
7927
|
+
* @example .columnWidth("email", 200)
|
|
7928
|
+
*/
|
|
7929
|
+
columnWidth(columnName, width) {
|
|
7930
|
+
if (!this.tabData.columnSizing) {
|
|
7931
|
+
this.tabData.columnSizing = {};
|
|
7932
|
+
}
|
|
7933
|
+
this.tabData.columnSizing[columnName] = width;
|
|
7934
|
+
return this;
|
|
7935
|
+
}
|
|
7936
|
+
/**
|
|
7937
|
+
* Set filters for this tab
|
|
7914
7938
|
* @example .filter({ combinator: "and", rules: [{ attribute: "status", operator: "is", value: "active" }] })
|
|
7915
7939
|
*/
|
|
7916
7940
|
filter(filters) {
|
|
@@ -7918,10 +7942,22 @@ var ListViewTabConfigBuilder = class _ListViewTabConfigBuilder {
|
|
|
7918
7942
|
return this;
|
|
7919
7943
|
}
|
|
7920
7944
|
/**
|
|
7921
|
-
*
|
|
7945
|
+
* Add a single sort rule
|
|
7946
|
+
* @example .sort("lastName", "asc")
|
|
7922
7947
|
*/
|
|
7923
|
-
|
|
7924
|
-
this.tabData.
|
|
7948
|
+
sort(attribute, direction = "asc") {
|
|
7949
|
+
if (!this.tabData.sorts) {
|
|
7950
|
+
this.tabData.sorts = [];
|
|
7951
|
+
}
|
|
7952
|
+
this.tabData.sorts.push({ attribute, direction });
|
|
7953
|
+
return this;
|
|
7954
|
+
}
|
|
7955
|
+
/**
|
|
7956
|
+
* Set multiple sort rules
|
|
7957
|
+
* @example .sorts([{ attribute: "lastName", direction: "asc" }, { attribute: "firstName", direction: "asc" }])
|
|
7958
|
+
*/
|
|
7959
|
+
sorts(rules) {
|
|
7960
|
+
this.tabData.sorts = rules;
|
|
7925
7961
|
return this;
|
|
7926
7962
|
}
|
|
7927
7963
|
/**
|
|
@@ -11969,6 +12005,28 @@ var RecordService = class extends BaseService {
|
|
|
11969
12005
|
});
|
|
11970
12006
|
}
|
|
11971
12007
|
}
|
|
12008
|
+
/**
|
|
12009
|
+
* Delete multiple records (soft delete).
|
|
12010
|
+
* Each record goes through the full deleteRecord pipeline (permissions, policies, hooks, audit).
|
|
12011
|
+
*
|
|
12012
|
+
* @returns Summary with successfully deleted IDs and any errors encountered
|
|
12013
|
+
*/
|
|
12014
|
+
async bulkDeleteRecords(recordIds, options) {
|
|
12015
|
+
const deleted = [];
|
|
12016
|
+
const errors = [];
|
|
12017
|
+
for (const id of recordIds) {
|
|
12018
|
+
try {
|
|
12019
|
+
await this.deleteRecord(id, options);
|
|
12020
|
+
deleted.push(id);
|
|
12021
|
+
} catch (err) {
|
|
12022
|
+
errors.push({
|
|
12023
|
+
id,
|
|
12024
|
+
error: err instanceof Error ? err.message : String(err)
|
|
12025
|
+
});
|
|
12026
|
+
}
|
|
12027
|
+
}
|
|
12028
|
+
return { deleted, errors };
|
|
12029
|
+
}
|
|
11972
12030
|
/**
|
|
11973
12031
|
* Permanently delete a record (hard delete)
|
|
11974
12032
|
*/
|
|
@@ -17241,8 +17299,15 @@ var ViewService = class extends BaseService {
|
|
|
17241
17299
|
);
|
|
17242
17300
|
const columns = visibleAttrs.sort((a, b) => (_nullishCoalesce(a.order, () => ( 999))) - (_nullishCoalesce(b.order, () => ( 999)))).slice(0, 5).map((attr) => attr.name);
|
|
17243
17301
|
const config = {
|
|
17244
|
-
|
|
17245
|
-
|
|
17302
|
+
tabs: [
|
|
17303
|
+
{
|
|
17304
|
+
id: "all",
|
|
17305
|
+
label: "All",
|
|
17306
|
+
default: true,
|
|
17307
|
+
layout: "table",
|
|
17308
|
+
columns
|
|
17309
|
+
}
|
|
17310
|
+
]
|
|
17246
17311
|
};
|
|
17247
17312
|
return {
|
|
17248
17313
|
name: "default",
|
|
@@ -7083,6 +7083,15 @@ var BaseTableTabConfig = class {
|
|
|
7083
7083
|
this.tabData.allowCreate = true;
|
|
7084
7084
|
return this;
|
|
7085
7085
|
}
|
|
7086
|
+
/**
|
|
7087
|
+
* Set creation behavior when clicking "+"
|
|
7088
|
+
* @param mode - "redirect" (navigate to detail), "inline" (empty row), or "modal" (stacked modal)
|
|
7089
|
+
* @example .createMode("inline") or .createMode("modal")
|
|
7090
|
+
*/
|
|
7091
|
+
createMode(mode) {
|
|
7092
|
+
this.tabData.createMode = mode;
|
|
7093
|
+
return this;
|
|
7094
|
+
}
|
|
7086
7095
|
/**
|
|
7087
7096
|
* Allow inline editing
|
|
7088
7097
|
*/
|
|
@@ -7688,8 +7697,6 @@ var ListViewBuilder = class {
|
|
|
7688
7697
|
this.data = {
|
|
7689
7698
|
name,
|
|
7690
7699
|
label,
|
|
7691
|
-
layout: "table",
|
|
7692
|
-
columns: [],
|
|
7693
7700
|
tabs: []
|
|
7694
7701
|
};
|
|
7695
7702
|
}
|
|
@@ -7730,82 +7737,21 @@ var ListViewBuilder = class {
|
|
|
7730
7737
|
return this;
|
|
7731
7738
|
}
|
|
7732
7739
|
/**
|
|
7733
|
-
* Set
|
|
7734
|
-
|
|
7735
|
-
table() {
|
|
7736
|
-
this.data.layout = "table";
|
|
7737
|
-
return this;
|
|
7738
|
-
}
|
|
7739
|
-
/**
|
|
7740
|
-
* Set the layout to kanban and specify the grouping attribute
|
|
7741
|
-
* @param groupByAttribute - Attribute to group by (must be a select/status type)
|
|
7742
|
-
*/
|
|
7743
|
-
kanban(groupByAttribute) {
|
|
7744
|
-
this.data.layout = "kanban";
|
|
7745
|
-
this.data.groupByAttribute = groupByAttribute;
|
|
7746
|
-
return this;
|
|
7747
|
-
}
|
|
7748
|
-
/**
|
|
7749
|
-
* Set columns to display
|
|
7750
|
-
* @example .columns("name", "email", "status", "createdAt")
|
|
7751
|
-
*/
|
|
7752
|
-
columns(...names) {
|
|
7753
|
-
this.data.columns = names;
|
|
7754
|
-
return this;
|
|
7755
|
-
}
|
|
7756
|
-
/**
|
|
7757
|
-
* Set width for a specific column in pixels
|
|
7758
|
-
* @example .columnWidth("email", 200)
|
|
7740
|
+
* Set base filters applied to ALL tabs (scoping, tenant, etc.)
|
|
7741
|
+
* @example .baseFilter({ combinator: "and", rules: [{ attribute: "tenant", operator: "is", value: "acme" }] })
|
|
7759
7742
|
*/
|
|
7760
|
-
|
|
7761
|
-
if (!this.data.columnSizing) {
|
|
7762
|
-
this.data.columnSizing = {};
|
|
7763
|
-
}
|
|
7764
|
-
this.data.columnSizing[columnName] = width;
|
|
7765
|
-
return this;
|
|
7766
|
-
}
|
|
7767
|
-
/**
|
|
7768
|
-
* Set widths for multiple columns
|
|
7769
|
-
* @example .columnWidths({ email: 200, name: 300, status: 100 })
|
|
7770
|
-
*/
|
|
7771
|
-
columnWidths(widths) {
|
|
7772
|
-
this.data.columnSizing = { ...this.data.columnSizing, ...widths };
|
|
7773
|
-
return this;
|
|
7774
|
-
}
|
|
7775
|
-
/**
|
|
7776
|
-
* Set default filters
|
|
7777
|
-
* @example .filter({ combinator: "and", rules: [{ attribute: "status", operator: "is", value: "active" }] })
|
|
7778
|
-
*/
|
|
7779
|
-
filter(filters) {
|
|
7743
|
+
baseFilter(filters) {
|
|
7780
7744
|
this.data.defaultFilters = filters;
|
|
7781
7745
|
return this;
|
|
7782
7746
|
}
|
|
7783
7747
|
/**
|
|
7784
|
-
* Add a
|
|
7785
|
-
*
|
|
7786
|
-
*/
|
|
7787
|
-
sort(attribute, direction = "asc") {
|
|
7788
|
-
if (!this.data.defaultSorts) {
|
|
7789
|
-
this.data.defaultSorts = [];
|
|
7790
|
-
}
|
|
7791
|
-
this.data.defaultSorts.push({ attribute, direction });
|
|
7792
|
-
return this;
|
|
7793
|
-
}
|
|
7794
|
-
/**
|
|
7795
|
-
* Set multiple sort rules
|
|
7796
|
-
* @example .sorts([{ attribute: "lastName", direction: "asc" }, { attribute: "firstName", direction: "asc" }])
|
|
7797
|
-
*/
|
|
7798
|
-
sorts(rules) {
|
|
7799
|
-
this.data.defaultSorts = rules;
|
|
7800
|
-
return this;
|
|
7801
|
-
}
|
|
7802
|
-
/**
|
|
7803
|
-
* Add an internal tab (filter preset)
|
|
7804
|
-
* Returns a TabConfigBuilder for chaining tab configuration
|
|
7748
|
+
* Add a tab with its own full configuration (layout, columns, filters, sorts, groupBy)
|
|
7749
|
+
* Returns a ListViewTabConfigBuilder for chaining tab configuration
|
|
7805
7750
|
* @example
|
|
7806
7751
|
* ```typescript
|
|
7807
|
-
* .tab("all", "All Contacts").
|
|
7808
|
-
* .tab("active", "Active").
|
|
7752
|
+
* .tab("all", "All Contacts").columns("name", "email").default()
|
|
7753
|
+
* .tab("active", "Active").columns("name", "email").filter({ ... })
|
|
7754
|
+
* .tab("pipeline", "Pipeline").kanban("stage").columns("name", "amount")
|
|
7809
7755
|
* ```
|
|
7810
7756
|
*/
|
|
7811
7757
|
tab(id, label) {
|
|
@@ -7825,13 +7771,8 @@ var ListViewBuilder = class {
|
|
|
7825
7771
|
if (!this.data.object) {
|
|
7826
7772
|
throw new Error("[ListViewBuilder] for() is required - specify the target object");
|
|
7827
7773
|
}
|
|
7828
|
-
if (this.data.
|
|
7829
|
-
throw new Error("[ListViewBuilder]
|
|
7830
|
-
}
|
|
7831
|
-
if (this.data.layout === "kanban" && !this.data.groupByAttribute) {
|
|
7832
|
-
throw new Error(
|
|
7833
|
-
"[ListViewBuilder] kanban() requires a groupByAttribute - specify the attribute to group by"
|
|
7834
|
-
);
|
|
7774
|
+
if (this.data.tabs.length === 0) {
|
|
7775
|
+
throw new Error("[ListViewBuilder] At least one tab is required");
|
|
7835
7776
|
}
|
|
7836
7777
|
const tabIds = /* @__PURE__ */ new Set();
|
|
7837
7778
|
for (const tab of this.data.tabs) {
|
|
@@ -7844,28 +7785,39 @@ var ListViewBuilder = class {
|
|
|
7844
7785
|
if (defaultTabs.length > 1) {
|
|
7845
7786
|
throw new Error("[ListViewBuilder] Only one tab can be marked as default");
|
|
7846
7787
|
}
|
|
7788
|
+
for (const tab of this.data.tabs) {
|
|
7789
|
+
if (tab.columns.length === 0) {
|
|
7790
|
+
throw new Error(`[ListViewBuilder] Tab "${tab.id}" must have at least one column`);
|
|
7791
|
+
}
|
|
7792
|
+
if (tab.layout === "kanban" && !tab.groupByAttribute) {
|
|
7793
|
+
throw new Error(`[ListViewBuilder] Kanban tab "${tab.id}" requires a groupByAttribute`);
|
|
7794
|
+
}
|
|
7795
|
+
}
|
|
7847
7796
|
const config = {
|
|
7848
|
-
layout: this.data.layout,
|
|
7849
|
-
columns: this.data.columns,
|
|
7850
|
-
columnSizing: this.data.columnSizing,
|
|
7851
7797
|
defaultFilters: this.data.defaultFilters ? {
|
|
7852
7798
|
id: generateId(),
|
|
7853
7799
|
combinator: this.data.defaultFilters.combinator,
|
|
7854
7800
|
rules: this.data.defaultFilters.rules
|
|
7855
7801
|
} : void 0,
|
|
7856
|
-
|
|
7857
|
-
groupByAttribute: this.data.groupByAttribute,
|
|
7858
|
-
tabs: this.data.tabs.length > 0 ? this.data.tabs.map((tab) => ({
|
|
7802
|
+
tabs: this.data.tabs.map((tab) => ({
|
|
7859
7803
|
id: tab.id,
|
|
7860
7804
|
label: tab.label,
|
|
7861
7805
|
icon: tab.icon,
|
|
7806
|
+
default: tab.default,
|
|
7807
|
+
layout: tab.layout,
|
|
7808
|
+
columns: tab.columns,
|
|
7809
|
+
columnSizing: tab.columnSizing,
|
|
7862
7810
|
filters: tab.filters ? {
|
|
7863
7811
|
id: generateId(),
|
|
7864
7812
|
combinator: tab.filters.combinator,
|
|
7865
7813
|
rules: tab.filters.rules
|
|
7866
7814
|
} : void 0,
|
|
7867
|
-
|
|
7868
|
-
|
|
7815
|
+
sorts: tab.sorts,
|
|
7816
|
+
groupByAttribute: tab.groupByAttribute,
|
|
7817
|
+
cardUserAttribute: tab.cardUserAttribute,
|
|
7818
|
+
cardDateAttribute: tab.cardDateAttribute,
|
|
7819
|
+
createMode: tab.createMode
|
|
7820
|
+
}))
|
|
7869
7821
|
};
|
|
7870
7822
|
return {
|
|
7871
7823
|
name: this.data.name,
|
|
@@ -7900,7 +7852,12 @@ var ListViewTabConfigBuilder = class _ListViewTabConfigBuilder {
|
|
|
7900
7852
|
/** @internal */
|
|
7901
7853
|
constructor(view2, id, label) {
|
|
7902
7854
|
this.view = view2;
|
|
7903
|
-
this.tabData = {
|
|
7855
|
+
this.tabData = {
|
|
7856
|
+
id,
|
|
7857
|
+
label,
|
|
7858
|
+
layout: "table",
|
|
7859
|
+
columns: []
|
|
7860
|
+
};
|
|
7904
7861
|
}
|
|
7905
7862
|
/**
|
|
7906
7863
|
* Set tab icon
|
|
@@ -7910,7 +7867,74 @@ var ListViewTabConfigBuilder = class _ListViewTabConfigBuilder {
|
|
|
7910
7867
|
return this;
|
|
7911
7868
|
}
|
|
7912
7869
|
/**
|
|
7913
|
-
*
|
|
7870
|
+
* Mark this tab as the default tab
|
|
7871
|
+
*/
|
|
7872
|
+
default() {
|
|
7873
|
+
this.tabData.default = true;
|
|
7874
|
+
return this;
|
|
7875
|
+
}
|
|
7876
|
+
/**
|
|
7877
|
+
* Set the layout to table (default)
|
|
7878
|
+
*/
|
|
7879
|
+
table() {
|
|
7880
|
+
this.tabData.layout = "table";
|
|
7881
|
+
return this;
|
|
7882
|
+
}
|
|
7883
|
+
/**
|
|
7884
|
+
* Set the layout to kanban and specify the grouping attribute
|
|
7885
|
+
* @param groupByAttribute - Attribute to group by (must be a select/status type)
|
|
7886
|
+
*/
|
|
7887
|
+
kanban(groupByAttribute) {
|
|
7888
|
+
this.tabData.layout = "kanban";
|
|
7889
|
+
this.tabData.groupByAttribute = groupByAttribute;
|
|
7890
|
+
return this;
|
|
7891
|
+
}
|
|
7892
|
+
/**
|
|
7893
|
+
* Set the user attribute to display on kanban cards (bottom-left)
|
|
7894
|
+
* @param attributeName - Name of a user-type attribute
|
|
7895
|
+
*/
|
|
7896
|
+
cardUserAttribute(attributeName) {
|
|
7897
|
+
this.tabData.cardUserAttribute = attributeName;
|
|
7898
|
+
return this;
|
|
7899
|
+
}
|
|
7900
|
+
/**
|
|
7901
|
+
* Set the date attribute to display on kanban cards (bottom-right)
|
|
7902
|
+
* @param attributeName - Name of a date-type attribute
|
|
7903
|
+
*/
|
|
7904
|
+
cardDateAttribute(attributeName) {
|
|
7905
|
+
this.tabData.cardDateAttribute = attributeName;
|
|
7906
|
+
return this;
|
|
7907
|
+
}
|
|
7908
|
+
/**
|
|
7909
|
+
* Set creation behavior when clicking "+"
|
|
7910
|
+
* @param mode - "redirect" (navigate to detail), "inline" (empty row), or "modal" (stacked modal)
|
|
7911
|
+
* @example .createMode("inline") or .createMode("modal")
|
|
7912
|
+
*/
|
|
7913
|
+
createMode(mode) {
|
|
7914
|
+
this.tabData.createMode = mode;
|
|
7915
|
+
return this;
|
|
7916
|
+
}
|
|
7917
|
+
/**
|
|
7918
|
+
* Set columns to display
|
|
7919
|
+
* @example .columns("name", "email", "status", "createdAt")
|
|
7920
|
+
*/
|
|
7921
|
+
columns(...names) {
|
|
7922
|
+
this.tabData.columns = names;
|
|
7923
|
+
return this;
|
|
7924
|
+
}
|
|
7925
|
+
/**
|
|
7926
|
+
* Set width for a specific column in pixels
|
|
7927
|
+
* @example .columnWidth("email", 200)
|
|
7928
|
+
*/
|
|
7929
|
+
columnWidth(columnName, width) {
|
|
7930
|
+
if (!this.tabData.columnSizing) {
|
|
7931
|
+
this.tabData.columnSizing = {};
|
|
7932
|
+
}
|
|
7933
|
+
this.tabData.columnSizing[columnName] = width;
|
|
7934
|
+
return this;
|
|
7935
|
+
}
|
|
7936
|
+
/**
|
|
7937
|
+
* Set filters for this tab
|
|
7914
7938
|
* @example .filter({ combinator: "and", rules: [{ attribute: "status", operator: "is", value: "active" }] })
|
|
7915
7939
|
*/
|
|
7916
7940
|
filter(filters) {
|
|
@@ -7918,10 +7942,22 @@ var ListViewTabConfigBuilder = class _ListViewTabConfigBuilder {
|
|
|
7918
7942
|
return this;
|
|
7919
7943
|
}
|
|
7920
7944
|
/**
|
|
7921
|
-
*
|
|
7945
|
+
* Add a single sort rule
|
|
7946
|
+
* @example .sort("lastName", "asc")
|
|
7922
7947
|
*/
|
|
7923
|
-
|
|
7924
|
-
this.tabData.
|
|
7948
|
+
sort(attribute, direction = "asc") {
|
|
7949
|
+
if (!this.tabData.sorts) {
|
|
7950
|
+
this.tabData.sorts = [];
|
|
7951
|
+
}
|
|
7952
|
+
this.tabData.sorts.push({ attribute, direction });
|
|
7953
|
+
return this;
|
|
7954
|
+
}
|
|
7955
|
+
/**
|
|
7956
|
+
* Set multiple sort rules
|
|
7957
|
+
* @example .sorts([{ attribute: "lastName", direction: "asc" }, { attribute: "firstName", direction: "asc" }])
|
|
7958
|
+
*/
|
|
7959
|
+
sorts(rules) {
|
|
7960
|
+
this.tabData.sorts = rules;
|
|
7925
7961
|
return this;
|
|
7926
7962
|
}
|
|
7927
7963
|
/**
|
|
@@ -11969,6 +12005,28 @@ var RecordService = class extends BaseService {
|
|
|
11969
12005
|
});
|
|
11970
12006
|
}
|
|
11971
12007
|
}
|
|
12008
|
+
/**
|
|
12009
|
+
* Delete multiple records (soft delete).
|
|
12010
|
+
* Each record goes through the full deleteRecord pipeline (permissions, policies, hooks, audit).
|
|
12011
|
+
*
|
|
12012
|
+
* @returns Summary with successfully deleted IDs and any errors encountered
|
|
12013
|
+
*/
|
|
12014
|
+
async bulkDeleteRecords(recordIds, options) {
|
|
12015
|
+
const deleted = [];
|
|
12016
|
+
const errors = [];
|
|
12017
|
+
for (const id of recordIds) {
|
|
12018
|
+
try {
|
|
12019
|
+
await this.deleteRecord(id, options);
|
|
12020
|
+
deleted.push(id);
|
|
12021
|
+
} catch (err) {
|
|
12022
|
+
errors.push({
|
|
12023
|
+
id,
|
|
12024
|
+
error: err instanceof Error ? err.message : String(err)
|
|
12025
|
+
});
|
|
12026
|
+
}
|
|
12027
|
+
}
|
|
12028
|
+
return { deleted, errors };
|
|
12029
|
+
}
|
|
11972
12030
|
/**
|
|
11973
12031
|
* Permanently delete a record (hard delete)
|
|
11974
12032
|
*/
|
|
@@ -17241,8 +17299,15 @@ var ViewService = class extends BaseService {
|
|
|
17241
17299
|
);
|
|
17242
17300
|
const columns = visibleAttrs.sort((a, b) => (a.order ?? 999) - (b.order ?? 999)).slice(0, 5).map((attr) => attr.name);
|
|
17243
17301
|
const config = {
|
|
17244
|
-
|
|
17245
|
-
|
|
17302
|
+
tabs: [
|
|
17303
|
+
{
|
|
17304
|
+
id: "all",
|
|
17305
|
+
label: "All",
|
|
17306
|
+
default: true,
|
|
17307
|
+
layout: "table",
|
|
17308
|
+
columns
|
|
17309
|
+
}
|
|
17310
|
+
]
|
|
17246
17311
|
};
|
|
17247
17312
|
return {
|
|
17248
17313
|
name: "default",
|