@contributte/datagrid 0.0.0-20250531-d4580b9

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.
Files changed (39) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +84 -0
  3. package/assets/ajax/index.ts +1 -0
  4. package/assets/ajax/naja.ts +154 -0
  5. package/assets/css/datagrid-all.css +6 -0
  6. package/assets/css/datagrid-full.css +7 -0
  7. package/assets/css/datagrid.css +651 -0
  8. package/assets/css/happy.css +463 -0
  9. package/assets/datagrid-all.ts +1 -0
  10. package/assets/datagrid-full.ts +53 -0
  11. package/assets/datagrid.ts +228 -0
  12. package/assets/index.ts +4 -0
  13. package/assets/integrations/happy.ts +217 -0
  14. package/assets/integrations/index.ts +4 -0
  15. package/assets/integrations/sortable-js.ts +58 -0
  16. package/assets/integrations/tom-select.ts +30 -0
  17. package/assets/integrations/vanilla-datepicker.ts +25 -0
  18. package/assets/plugins/features/autosubmit.ts +87 -0
  19. package/assets/plugins/features/checkboxes.ts +92 -0
  20. package/assets/plugins/features/confirm.ts +28 -0
  21. package/assets/plugins/features/editable.ts +118 -0
  22. package/assets/plugins/features/inline.ts +89 -0
  23. package/assets/plugins/features/item-detail.ts +48 -0
  24. package/assets/plugins/features/treeView.ts +44 -0
  25. package/assets/plugins/index.ts +13 -0
  26. package/assets/plugins/integrations/datepicker.ts +25 -0
  27. package/assets/plugins/integrations/happy.ts +19 -0
  28. package/assets/plugins/integrations/nette-forms.ts +18 -0
  29. package/assets/plugins/integrations/selectpicker.ts +25 -0
  30. package/assets/plugins/integrations/sortable.ts +61 -0
  31. package/assets/types/ajax.d.ts +143 -0
  32. package/assets/types/datagrid.d.ts +31 -0
  33. package/assets/types/index.d.ts +41 -0
  34. package/assets/types/integrations.d.ts +15 -0
  35. package/assets/utils.ts +179 -0
  36. package/dist/datagrid-full.css +1 -0
  37. package/dist/datagrid-full.js +20 -0
  38. package/dist/datagrid-full.js.map +1 -0
  39. package/package.json +55 -0
@@ -0,0 +1,92 @@
1
+ import { DatagridPlugin } from "../../types";
2
+ import { Datagrid } from "../..";
3
+
4
+ export const CheckboxAttribute = "data-check";
5
+
6
+ export class CheckboxPlugin implements DatagridPlugin {
7
+ onDatagridInit(datagrid: Datagrid): boolean {
8
+ let lastCheckbox = null;
9
+
10
+ datagrid.el.addEventListener("click", e => {
11
+ if (!(e.target instanceof HTMLElement)) return;
12
+
13
+ if (e.target.classList.contains("col-checkbox")) {
14
+ lastCheckbox = e.target;
15
+ if (e.shiftKey && lastCheckbox) {
16
+ const currentCheckboxRow = lastCheckbox.closest("tr");
17
+ if (!currentCheckboxRow) return;
18
+
19
+ const lastCheckboxRow = lastCheckbox.closest("tr");
20
+ if (!lastCheckboxRow) return;
21
+
22
+ const lastCheckboxTbody = lastCheckboxRow.closest("tbody");
23
+ if (!lastCheckboxTbody) return;
24
+
25
+ const checkboxesRows = Array.from(lastCheckboxTbody.querySelectorAll<HTMLElement>("tr"));
26
+ const [start, end] = [lastCheckboxRow.rowIndex, currentCheckboxRow.rowIndex].sort();
27
+ const rows = checkboxesRows.slice(start, end + 1);
28
+
29
+ rows.forEach(row => {
30
+ const input = row.querySelector<HTMLInputElement>('.col-checkbox input[type="checkbox"]');
31
+ if (input) {
32
+ input.checked = true;
33
+ }
34
+ });
35
+ }
36
+ }
37
+ });
38
+
39
+ let checkboxes = datagrid.el.querySelectorAll<HTMLInputElement>(`input[data-check='${datagrid.name}']`);
40
+ const select = datagrid.el.querySelector<HTMLSelectElement>("select[name='group_action[group_action]']");
41
+ const actionButtons = document.querySelectorAll<HTMLInputElement | HTMLButtonElement>(
42
+ ".row-group-actions *[type='submit']"
43
+ );
44
+ const counter = document.querySelector<HTMLElement>(".datagrid-selected-rows-count");
45
+
46
+ // Handling a checkbox click + select all checkbox
47
+ checkboxes.forEach(checkEl => {
48
+ checkEl.addEventListener("change", () => {
49
+ // Select all
50
+ const isSelectAll = checkEl.hasAttribute("data-check-all");
51
+ if (isSelectAll) {
52
+ if (datagrid.name !== checkEl.getAttribute("data-check-all")) return;
53
+
54
+ checkboxes.forEach(checkbox => (checkbox.checked = checkEl.checked));
55
+
56
+ // todo: refactor not to repeat this code twice
57
+ actionButtons.forEach(button => (button.disabled = !checkEl.checked));
58
+
59
+ if (select) {
60
+ select.disabled = !checkEl.checked;
61
+ }
62
+
63
+ if (counter) {
64
+ const total = Array.from(checkboxes).filter(c => !c.hasAttribute("data-check-all")).length;
65
+ counter.innerText = `${checkEl.checked ? total : 0}/${total}`;
66
+ }
67
+ return;
68
+ } else {
69
+ const selectAll = datagrid.el.querySelector<HTMLInputElement>(`input[data-check='${datagrid.name}'][data-check-all]`);
70
+ if (selectAll) {
71
+ selectAll.checked = Array.from(checkboxes).filter(c => !c.hasAttribute("data-check-all")).every(c => c.checked);
72
+ }
73
+ }
74
+
75
+ const checkedBoxes = Array.from(checkboxes).filter(checkbox => checkbox.checked && !checkEl.hasAttribute("data-check-all"));
76
+ const hasChecked = checkedBoxes.length >= 1;
77
+
78
+ actionButtons.forEach(button => (button.disabled = !hasChecked));
79
+
80
+ if (select) {
81
+ select.disabled = !hasChecked;
82
+ }
83
+
84
+ if (counter) {
85
+ counter.innerText = `${checkedBoxes.length}/${checkboxes.length}`;
86
+ }
87
+ });
88
+ });
89
+
90
+ return true;
91
+ }
92
+ }
@@ -0,0 +1,28 @@
1
+ import { Datagrid } from "../../datagrid";
2
+ import { DatagridPlugin } from "../../types";
3
+
4
+ export const ConfirmAttribute = "data-datagrid-confirm";
5
+
6
+ export class ConfirmPlugin implements DatagridPlugin {
7
+ onDatagridInit(datagrid: Datagrid): boolean {
8
+ datagrid.el
9
+ .querySelectorAll<HTMLElement>(`[${ConfirmAttribute}]:not(.ajax)`)
10
+ .forEach(confirmEl =>
11
+ confirmEl.addEventListener("click", e => this.confirmEventHandler.bind(datagrid)(e.target as HTMLElement, e))
12
+ );
13
+
14
+ datagrid.ajax.addEventListener("interact", e => this.confirmEventHandler.bind(datagrid)(e.detail.element, e));
15
+
16
+ return true;
17
+ }
18
+
19
+ confirmEventHandler(this: Datagrid, el: HTMLElement, e: Event) {
20
+ const message = el.closest('a')?.getAttribute(ConfirmAttribute)!;
21
+ if (!message) return;
22
+
23
+ if (!window.confirm.bind(window)(message)) {
24
+ e.stopPropagation();
25
+ e.preventDefault();
26
+ }
27
+ }
28
+ }
@@ -0,0 +1,118 @@
1
+ import { DatagridPlugin } from "../../types";
2
+ import { calculateCellLines, isEnter, isEsc } from "../../utils";
3
+ import { Datagrid } from "../..";
4
+
5
+ export const EditableUrlAttribute = "data-datagrid-editable-url";
6
+
7
+ export const EditableTypeAttribute = "data-datagrid-editable-type";
8
+
9
+ export const EditableElementAttribute = "data-datagrid-editable-element";
10
+
11
+ export const EditableValueAttribute = "data-datagrid-editable-value";
12
+
13
+ export const EditableAttrsAttribute = "datagrid-editable-attrs";
14
+
15
+ export class EditablePlugin implements DatagridPlugin {
16
+ onDatagridInit(datagrid: Datagrid): boolean {
17
+ datagrid.el.querySelectorAll<HTMLElement>(`[${EditableUrlAttribute}]`).forEach(cell => {
18
+ if (cell instanceof HTMLAnchorElement || cell.classList.contains("datagrid-inline-edit")) return;
19
+
20
+ if (!cell.classList.contains("editing")) {
21
+ cell.classList.add("editing");
22
+ const originalValue = cell.innerHTML.replace(/<\/?br>/g, "\n");
23
+ const valueToEdit = cell.getAttribute(EditableValueAttribute) ?? originalValue;
24
+
25
+ cell.setAttribute("originalValue", originalValue);
26
+ cell.setAttribute("valueToEdit", valueToEdit);
27
+
28
+ const type = cell.getAttribute(EditableTypeAttribute) ?? "text";
29
+
30
+ let input: HTMLElement;
31
+
32
+ switch (type) {
33
+ case "textarea":
34
+ cell.innerHTML = `<textarea rows="${calculateCellLines(cell)}">${valueToEdit}</textarea>`;
35
+ input = cell.querySelector("textarea")!;
36
+ break;
37
+ case "select":
38
+ input = cell.querySelector(cell.getAttribute(EditableElementAttribute) ?? "")!;
39
+ input
40
+ .querySelectorAll(`option[value='${valueToEdit}']`)
41
+ .forEach(input => input.setAttribute("selected", "true"));
42
+ break;
43
+ default:
44
+ cell.innerHTML = `<input type='${type}' />`;
45
+ input = cell.querySelector("input")!;
46
+ }
47
+
48
+ const attributes = JSON.parse(cell.getAttribute(EditableAttrsAttribute) ?? "{}");
49
+ for (const key in attributes) {
50
+ const value = attributes[key];
51
+ input.setAttribute(key, value);
52
+ }
53
+
54
+ cell.classList.remove("edited");
55
+
56
+ const submitCell = async (el: HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement) => {
57
+ let value = el.value;
58
+ if (value !== valueToEdit) {
59
+ try {
60
+ const response = await datagrid.ajax.request({
61
+ url: cell.getAttribute(EditableUrlAttribute) ?? "",
62
+ method: "POST",
63
+ data: {
64
+ value,
65
+ },
66
+ }) as any;
67
+
68
+ if (type === "select") {
69
+ cell.innerHTML = cell.querySelector(`option[value='${value}']`)?.innerHTML ?? "";
70
+ } else {
71
+ if (response._datagrid_editable_new_value) {
72
+ value = response._datagrid_editable_new_value;
73
+ }
74
+ cell.innerHTML = value;
75
+ }
76
+ cell.classList.add("edited");
77
+ } catch {
78
+ cell.innerHTML = originalValue;
79
+ cell.classList.add("edited-error");
80
+ }
81
+ } else {
82
+ cell.innerHTML = originalValue;
83
+ }
84
+
85
+ cell.classList.remove("editing");
86
+ };
87
+
88
+ cell
89
+ .querySelectorAll<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>(
90
+ "input, textarea, select"
91
+ )
92
+ .forEach(el => {
93
+ el.addEventListener("blur", () => submitCell(el));
94
+ el.addEventListener("keydown", e => {
95
+ if (isEnter(e as KeyboardEvent)) {
96
+ e.stopPropagation();
97
+ e.preventDefault();
98
+ return submitCell(el);
99
+ }
100
+
101
+ if (isEsc(e as KeyboardEvent)) {
102
+ e.stopPropagation();
103
+ e.preventDefault();
104
+ cell.classList.remove("editing");
105
+ cell.innerHTML = originalValue;
106
+ }
107
+ });
108
+
109
+ if (el instanceof HTMLSelectElement) {
110
+ el.addEventListener("change", () => submitCell(el));
111
+ }
112
+ });
113
+ }
114
+ });
115
+
116
+ return true;
117
+ }
118
+ }
@@ -0,0 +1,89 @@
1
+ import { DatagridPlugin } from "../../types";
2
+ import { isEnter } from "../../utils";
3
+ import { Datagrid, Datagrids } from "../..";
4
+
5
+ export class InlinePlugin implements DatagridPlugin {
6
+ onInit(datagrids: Datagrids) {
7
+ }
8
+
9
+ onDatagridInit(datagrid: Datagrid): boolean {
10
+ datagrid.ajax.addEventListener('success', ({ detail: { payload } }) => {
11
+ if (!payload._datagrid_name || payload._datagrid_name !== datagrid.name) return;
12
+
13
+ if (payload._datagrid_inline_edited || payload._datagrid_inline_edit_cancel) {
14
+ const trigger = datagrid.el.querySelector('.datagrid-inline-edit-trigger');
15
+
16
+ if (payload._datagrid_inline_edited) {
17
+ let rows = datagrid.el.querySelectorAll<HTMLTableCellElement>(
18
+ `tr[data-id='${payload._datagrid_inline_edited}'] > td`
19
+ );
20
+
21
+ rows.forEach(row => {
22
+ row.classList.add("edited");
23
+ })
24
+ }
25
+
26
+ trigger?.classList.remove("hidden");
27
+ return;
28
+ }
29
+
30
+ if (payload._datagrid_inline_adding) {
31
+ const row = datagrid.el.querySelector<HTMLElement>(".datagrid-row-inline-add");
32
+ if (row) {
33
+ row.classList.remove("datagrid-row-inline-add-hidden");
34
+ row.querySelector<HTMLInputElement | HTMLTextAreaElement>(
35
+ "input:not([readonly]), textarea:not([readonly])"
36
+ )?.focus();
37
+ }
38
+ }
39
+
40
+ if (payload._datagrid_inline_editing) {
41
+ datagrid.el.querySelector<HTMLElement>(".datagrid-inline-edit-trigger")
42
+ ?.classList.add("hidden");
43
+ }
44
+
45
+ datagrid.el.querySelectorAll<HTMLElement>(".datagrid-inline-edit input").forEach(inputEl => {
46
+ inputEl.addEventListener("keydown", e => {
47
+ if (!isEnter(e)) return;
48
+
49
+ e.stopPropagation();
50
+ e.preventDefault();
51
+
52
+ return inputEl
53
+ .closest("tr")
54
+ ?.querySelector<HTMLElement>(".col-action-inline-edit [name='inline_edit[submit]']")
55
+ ?.click();
56
+ });
57
+ });
58
+
59
+ datagrid.el.querySelectorAll<HTMLElement>(".datagrid-inline-add input").forEach(inputEl => {
60
+ inputEl.addEventListener("keydown", e => {
61
+ if (!isEnter(e)) return;
62
+
63
+ e.stopPropagation();
64
+ e.preventDefault();
65
+
66
+ return inputEl
67
+ .closest("tr")
68
+ ?.querySelector<HTMLElement>(".col-action-inline-edit [name='inline_add[submit]']")
69
+ ?.click();
70
+ });
71
+ });
72
+
73
+ datagrid.el.querySelectorAll<HTMLElement>("[data-datagrid-cancel-inline-add]").forEach(cancel => {
74
+ cancel.addEventListener("mouseup", e => {
75
+ if (e.button === 0) {
76
+ e.stopPropagation();
77
+ e.preventDefault();
78
+ const inlineAdd = cancel.closest<HTMLElement>(".datagrid-row-inline-add");
79
+ if (inlineAdd) {
80
+ inlineAdd.classList.add("datagrid-row-inline-add-hidden");
81
+ }
82
+ }
83
+ });
84
+ });
85
+ })
86
+
87
+ return true;
88
+ }
89
+ }
@@ -0,0 +1,48 @@
1
+ import { Datagrid } from "../..";
2
+ import { DatagridPlugin } from "../../types";
3
+
4
+ export class ItemDetailPlugin implements DatagridPlugin {
5
+ onDatagridInit(datagrid: Datagrid): boolean {
6
+ datagrid.el.querySelectorAll<HTMLElement>("[data-toggle-detail-grid]")
7
+ .forEach((el) => {
8
+ if (el.getAttribute("data-toggle-detail-grid") !== datagrid.name) return;
9
+ const toggleId = el.getAttribute("data-toggle-detail")!;
10
+
11
+
12
+ el.addEventListener("click", (e) => {
13
+ const contentRow = datagrid.el.querySelector<HTMLElement>(
14
+ `.item-detail-${datagrid.name}-id-${toggleId}`
15
+ );
16
+
17
+ const gridRow = el.closest('tr');
18
+
19
+ if (contentRow) {
20
+ // const div = contentRow.querySelector<HTMLDivElement>("td > div");
21
+ // if (div && !el.classList.contains("datagrid--slide-toggle")) {
22
+ // attachSlideToggle(div, el);
23
+ // } TODO: fix
24
+ contentRow.classList.add("datagrid--content-row")
25
+ contentRow.classList.toggle("is-active");
26
+
27
+ }
28
+
29
+ datagrid.ajax.addEventListener("before", (e) => {
30
+ if (e.detail.params.url.includes(`do=${datagrid.name}-getItemDetail`) && e.detail.params.url.includes(`grid-id=${toggleId}`)) {
31
+ e.stopPropagation();
32
+ e.preventDefault();
33
+ }
34
+ })
35
+ })
36
+ });
37
+
38
+ datagrid.ajax.addEventListener("success", ({detail: {payload}}) => {
39
+ if (payload._datagrid_redraw_item_id && payload._datagrid_redraw_item_class) {
40
+ datagrid.el.querySelector<HTMLTableRowElement>(
41
+ `tr[data-id='${payload._datagrid_redraw_item_id}']`
42
+ )?.setAttribute("class", payload._datagrid_redraw_item_class)
43
+ }
44
+ })
45
+
46
+ return true;
47
+ }
48
+ }
@@ -0,0 +1,44 @@
1
+ import { DatagridPlugin } from "../../types";
2
+ import { Datagrid } from "../..";
3
+
4
+ export class TreeViewPlugin implements DatagridPlugin {
5
+ onDatagridInit(datagrid: Datagrid): boolean {
6
+ datagrid.ajax.addEventListener("before", (e) => {
7
+ })
8
+
9
+ datagrid.ajax.addEventListener("success", ({detail: {payload}}) => {
10
+ if (payload._datagrid_tree) {
11
+ const id = payload._datagrid_tree;
12
+ const rowBlock = document.querySelector(`.datagrid-tree-item[data-id="${id}"]`);
13
+ const childrenBlock = document.querySelector(`.datagrid-tree-item[data-id="${id}"] .datagrid-tree-item-children`);
14
+ if (childrenBlock) {
15
+ if (childrenBlock.classList.contains('showed')) {
16
+ childrenBlock.innerHTML = '';
17
+ childrenBlock.classList.remove('showed');
18
+ rowBlock.querySelector(`a.chevron`).style.transform = "rotate(0deg)";
19
+ return;
20
+ }
21
+
22
+ childrenBlock.classList.add('showed');
23
+ rowBlock.querySelector(`a.chevron`).style.transform = "rotate(90deg)";
24
+ const snippets = payload.snippets;
25
+ for (const snippetName in snippets) {
26
+ const snippet = snippets[snippetName];
27
+ const snippetDocEl = new DOMParser().parseFromString(snippet, "text/html")
28
+ .querySelector("[data-id]");
29
+
30
+ const id = snippetDocEl?.getAttribute("data-id") ?? '';
31
+ const hasChildren = snippetDocEl?.hasAttribute("data-has-children") ?? false;
32
+
33
+ const template = `\n<div class="datagrid-tree-item" class='${hasChildren ? 'has-children' : ''}' id="${snippetName}" data-id="${id}">${snippet}</div>`;
34
+
35
+ childrenBlock.innerHTML = template;
36
+ }
37
+ //children_block.addClass('loaded');
38
+ //children_block.slideToggle('fast');
39
+ }
40
+ }
41
+ })
42
+ return true;
43
+ }
44
+ }
@@ -0,0 +1,13 @@
1
+ export * from "./integrations/datepicker";
2
+ export * from "./integrations/happy";
3
+ export * from "./integrations/nette-forms"
4
+ export * from "./integrations/selectpicker";
5
+ export * from "./integrations/sortable";
6
+
7
+ export * from "./features/autosubmit";
8
+ export * from "./features/checkboxes";
9
+ export * from "./features/confirm";
10
+ export * from "./features/editable";
11
+ export * from "./features/inline";
12
+ export * from "./features/item-detail";
13
+ export * from "./features/treeView";
@@ -0,0 +1,25 @@
1
+ import { Datagrid } from "../..";
2
+ import { DatagridPlugin, Datepicker } from "../../types";
3
+
4
+ export class DatepickerPlugin implements DatagridPlugin {
5
+ constructor(private datepicker: Datepicker) {
6
+ }
7
+
8
+ onDatagridInit(datagrid: Datagrid): boolean {
9
+ datagrid.ajax.addEventListener('complete', (event) => {
10
+ this.initDatepicker(datagrid);
11
+ });
12
+
13
+ this.initDatepicker(datagrid);
14
+
15
+ return true;
16
+ }
17
+
18
+ private initDatepicker(datagrid: Datagrid): void {
19
+ const elements = datagrid.el.querySelectorAll<HTMLInputElement>("input[data-provide='datepicker']");
20
+
21
+ if (elements.length >= 1) {
22
+ this.datepicker.initDatepickers(Array.from(elements), datagrid);
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,19 @@
1
+ import { Datagrid } from "../..";
2
+ import { DatagridPlugin } from "../../types";
3
+ import { window } from "../../utils";
4
+ import type { Happy } from "../../integrations";
5
+
6
+ export class HappyPlugin implements DatagridPlugin {
7
+ constructor(private happy?: Happy) {
8
+ }
9
+
10
+ onDatagridInit(datagrid: Datagrid): boolean {
11
+ const happy = this.happy ?? window().happy ?? null;
12
+
13
+ if (happy) {
14
+ happy.init();
15
+ }
16
+
17
+ return true;
18
+ }
19
+ }
@@ -0,0 +1,18 @@
1
+ import { DatagridPlugin, Nette } from "../../types";
2
+ import { Datagrid } from "../..";
3
+ import { window } from "../../utils";
4
+
5
+ export class NetteFormsPlugin implements DatagridPlugin {
6
+ constructor(private nette?: Nette) {
7
+ }
8
+
9
+ onDatagridInit(datagrid: Datagrid): boolean {
10
+ const nette = this.nette ?? window().Nette ?? null;
11
+
12
+ if (nette) {
13
+ datagrid.el.querySelectorAll<HTMLFormElement>("form").forEach(form => nette.initForm(form));
14
+ }
15
+
16
+ return true;
17
+ }
18
+ }
@@ -0,0 +1,25 @@
1
+ import { DatagridPlugin, Selectpicker } from "../../types";
2
+ import { Datagrid } from "../..";
3
+
4
+ export class SelectpickerPlugin implements DatagridPlugin {
5
+ constructor(private selectpicker: Selectpicker) {
6
+ }
7
+
8
+ onDatagridInit(datagrid: Datagrid): boolean {
9
+ datagrid.ajax.addEventListener('complete', (event) => {
10
+ this.initSelectpicker(datagrid);
11
+ });
12
+
13
+ this.initSelectpicker(datagrid);
14
+
15
+ return true;
16
+ }
17
+
18
+ private initSelectpicker(datagrid: Datagrid): void {
19
+ const elements = datagrid.el.querySelectorAll<HTMLElement>("select.selectpicker");
20
+
21
+ if (elements.length >= 1) {
22
+ this.selectpicker.initSelectpickers(Array.from(elements), datagrid);
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,61 @@
1
+ import { Datagrid } from "../../datagrid";
2
+ import { DatagridPlugin, Sortable } from "../../types";
3
+
4
+ export class SortablePlugin implements DatagridPlugin {
5
+ constructor(private sortable: Sortable) {
6
+ }
7
+
8
+ onDatagridInit(datagrid: Datagrid): boolean {
9
+ datagrid.ajax.addEventListener('before', (event) => {
10
+ // TODO old ln 694... wtf?
11
+ })
12
+
13
+ this.sortable.initSortable(datagrid);
14
+
15
+ datagrid.ajax.addEventListener('success', ({detail: {payload}}) => {
16
+ if (payload._datagrid_sort) {
17
+ for (const key in payload._datagrid_sort) {
18
+ const href = payload._datagrid_sort[key];
19
+ const element = datagrid.el.querySelector(`#datagrid-sort-${key}`);
20
+
21
+ if (element) {
22
+ // TODO: Only for BC support, to be removed
23
+ element.setAttribute("href", href);
24
+
25
+ element.setAttribute("data-href", href);
26
+ }
27
+ }
28
+ this.sortable.initSortable(datagrid);
29
+ }
30
+
31
+ if (payload._datagrid_tree) {
32
+ const childrenContainer = datagrid.el.querySelector<HTMLElement>(
33
+ `.datagrid-tree-item[data-id='${payload._datagrid_tree}'] .datagrid-tree-item-children`
34
+ );
35
+ if (childrenContainer && payload.snippets) {
36
+ childrenContainer.classList.add("loaded");
37
+ for (const key in payload.snippets) {
38
+ const snippet = payload.snippets[key];
39
+
40
+ const doc = new DOMParser().parseFromString(snippet, 'text/html');
41
+ const element = doc.firstElementChild;
42
+ if (element) {
43
+ const treeItem = document.createElement("div");
44
+ treeItem.id = key;
45
+ treeItem.classList.add("datagrid-tree-item")
46
+ treeItem.setAttribute("data-id", key);
47
+ if (element.hasAttribute("has-children")) {
48
+ treeItem.classList.add("has-children");
49
+ }
50
+
51
+ childrenContainer.append(treeItem);
52
+ // attachSlideToggle(childrenContainer);
53
+ }
54
+ }
55
+ }
56
+ this.sortable.initSortableTree(datagrid);
57
+ }
58
+ })
59
+ return true;
60
+ }
61
+ }