Skip to content

Commit c07cabb

Browse files
committed
fix: pass unmapped node to table functions
1 parent fc264e0 commit c07cabb

File tree

5 files changed

+217
-157
lines changed

5 files changed

+217
-157
lines changed

packages/components-vue/src/components/table/Body.vue

Lines changed: 36 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
<template>
2-
<tbody v-if="nodes.length" :class="classes">
3-
<template v-for="(node, nodeIndex) in nodes" :key="nodeIndex">
2+
<tbody v-if="mappedNodes.length" :class="classes">
3+
<template
4+
v-for="(
5+
{ node, index, visibility, hydrateNode, createNodeChildrenAndRefresh }, mappedIndex
6+
) in mappedNodes.nodes"
7+
:key="index"
8+
>
49
<!-- Row -->
510
<tr
611
class="--txtAlign"
7-
:class="[`--txtSize-${size}`, { ['is--selected']: selectedNodes[nodeIndex][0] }]"
12+
:class="[`--txtSize-${size}`, { ['is--selected']: selectedNodes[index][0] }]"
813
>
914
<th
10-
v-if="nodes.length > 1 || $slots.default"
15+
v-if="mappedNodes.length > 1 || $slots.default"
1116
class="--sticky"
1217
:class="{ ['is--selected']: !!ordering['id'] }"
1318
data-column-name="id"
@@ -16,20 +21,19 @@
1621
<component
1722
:is="preferId"
1823
v-if="preferId && preferId !== true"
19-
:index="nodeIndex"
20-
:node="node"
24+
v-bind="{ index, node: nodes[index] }"
2125
/>
2226
<div v-else class="flx --flxRow --flx-start-center --gap-10">
2327
<InputToggle
2428
v-if="!isReadOnly"
25-
:id="tableId + String(node.id ?? nodeIndex)"
26-
v-model="selectedNodes[nodeIndex][0]"
29+
:id="tableId + String(node.id ?? index)"
30+
v-model="selectedNodes[mappedIndex][0]"
2731
:theme="theme || themeValues"
2832
:title="t('table_select')"
2933
:size="size"
3034
/>
31-
<span :title="String(node.id ?? nodeIndex)">
32-
{{ node.id && preferId ? node.id : nodeIndex + 1 }}
35+
<span :title="String(node.id ?? index)">
36+
{{ node.id && preferId ? node.id : index + 1 }}
3337
</span>
3438
</div>
3539
</th>
@@ -51,7 +55,7 @@
5155
meta: {
5256
...meta,
5357
...(meta.updateNode && {
54-
updateNode: (n: any) => meta.updateNode?.(n, node),
58+
updateNode: (n: any) => meta.updateNode?.(n, nodes[index]),
5559
}),
5660
},
5761
node,
@@ -89,7 +93,7 @@
8993
cloneNodeAndRefresh,
9094
deleteNodeAndRefresh,
9195
deleteNodesAndRefresh,
92-
show: visibility[nodeIndex].show,
96+
show: canShowChildren(visibility, mappedIndex),
9397
}"
9498
></slot>
9599
<ActionButton
@@ -101,7 +105,7 @@
101105
:size="size"
102106
round
103107
:disabled="selectedNodes.some(([n]) => n)"
104-
@click="() => updateNodeAndRefresh(node)"
108+
@click="() => updateNodeAndRefresh(nodes[index])"
105109
>
106110
<IconFa name="pencil" />
107111
</ActionButton>
@@ -133,7 +137,9 @@
133137
:theme="invertedTheme"
134138
:size="size"
135139
:aria-label="t('table_duplicate')"
136-
@click="() => cloneNodeAndRefresh(node, setModel)"
140+
@click="
141+
() => cloneNodeAndRefresh(nodes[index], setModel)
142+
"
137143
>
138144
<IconFa name="clone" />
139145
<span>
@@ -149,7 +155,7 @@
149155
@click="
150156
() =>
151157
deleteNodeAndRefresh(
152-
node,
158+
nodes[index],
153159
setModel,
154160
dropdownRef
155161
)
@@ -167,7 +173,7 @@
167173
cloneNodeAndRefresh,
168174
deleteNodeAndRefresh,
169175
deleteNodesAndRefresh,
170-
show: visibility[nodeIndex].show,
176+
show: canShowChildren(visibility, mappedIndex),
171177
}"
172178
></slot>
173179
</ul>
@@ -182,7 +188,7 @@
182188
<tr class="no--hover --width-100">
183189
<td :colspan="propertiesMeta.length + 2">
184190
<BaseBox
185-
v-show="visibility[nodeIndex].show"
191+
v-show="canShowChildren(visibility, mappedIndex)"
186192
:theme="theme || themeValues"
187193
transparent
188194
button
@@ -196,7 +202,7 @@
196202
deleteNodeAndRefresh,
197203
deleteNodesAndRefresh,
198204
createNodeChildrenAndRefresh,
199-
show: visibility[nodeIndex].show,
205+
show: canShowChildren(visibility, mappedIndex),
200206
hydrateParentNode: hydrateNode,
201207
}"
202208
></slot>
@@ -210,51 +216,48 @@
210216
<ActionLink
211217
:theme="theme || themeValues"
212218
:size="size"
213-
:active="visibility[nodeIndex].show"
219+
:active="canShowChildren(visibility, mappedIndex)"
214220
:tooltip="
215221
t(
216-
visibility[nodeIndex].show
222+
canShowChildren(visibility, mappedIndex)
217223
? 'table_hide_name'
218224
: 'table_see_name',
219225
{
220226
name:
221227
childrenName ||
222228
childrenCountKey ||
223-
String(node.id ?? nodeIndex).split('/')[0],
229+
String(node.id ?? index).split('/')[0],
224230
}
225231
)
226232
"
227233
tooltip-position="right"
228-
:disabled="
229-
!visibility[nodeIndex].childrenCount ||
230-
visibility[nodeIndex].showNodeChildren
231-
"
234+
:disabled="!visibility.childrenCount || visibility.showNodeChildren"
232235
class="--p-5"
233-
@click="() => toggleChildren(nodeIndex)"
236+
@click="() => toggleChildren(mappedIndex)"
234237
>
235-
<span v-if="visibility[nodeIndex].childrenCount >= 1">
236-
{{ visibility[nodeIndex].childrenCount }}
238+
<span v-if="visibility.childrenCount >= 1">
239+
{{ visibility.childrenCount }}
237240
</span>
238241
<IconFa name="chevron-down" indicator />
239242
</ActionLink>
240243
<ActionButtonLink
241244
v-if="createNodeChildren"
242245
:theme="theme || themeValues"
243246
:size="size"
244-
:disabled="visibility[nodeIndex].disableCreateNodeChildren"
247+
:disabled="visibility.disableCreateNodeChildren"
245248
:tooltip="
246249
t('table_create_new_name', {
247250
name:
248251
childrenName ||
249252
childrenCountKey ||
250-
String(node.id ?? nodeIndex).split('/')[0],
253+
String(node.id ?? index).split('/')[0],
251254
})
252255
"
253256
tooltip-position="right"
254257
class="--p-5:md-inv"
255258
link-button
256259
round
257-
@click="() => createNodeChildrenAndRefresh(node)"
260+
@click="() => createNodeChildrenAndRefresh(nodes[index])"
258261
>
259262
<IconFa name="plus" />
260263
</ActionButtonLink>
@@ -272,9 +275,7 @@
272275
</template>
273276

274277
<script setup lang="ts" generic="T extends Record<string, any>, TM extends Record<string, any> = T">
275-
import { computed } from "vue";
276-
277-
import { useI18n, useSwal } from "@open-xamu-co/ui-common-helpers";
278+
import { useI18n } from "@open-xamu-co/ui-common-helpers";
278279
279280
import IconFa from "../icon/Fa.vue";
280281
import ActionLink from "../action/Link.vue";
@@ -287,21 +288,13 @@
287288
288289
import type { iTableChildProps } from "../../types/props";
289290
import useTheme from "../../composables/theme";
290-
import { useHelpers, useResolveNodeFn } from "../../composables/utils";
291-
import type { iNodeFn } from "@open-xamu-co/ui-common-types";
291+
import { useHelpers } from "../../composables/utils";
292292
293293
export interface iTableBodyProps<
294294
Ti extends Record<string, any>,
295295
TMi extends Record<string, any> = Ti,
296296
> extends iTableChildProps<Ti, TMi> {}
297297
298-
interface INodeVisibility {
299-
disableCreateNodeChildren?: boolean;
300-
showNodeChildren?: boolean;
301-
childrenCount: number;
302-
show: boolean;
303-
}
304-
305298
/**
306299
* Table body
307300
*
@@ -312,90 +305,6 @@
312305
313306
const props = defineProps<iTableBodyProps<T, TM>>();
314307
315-
const Swal = useHelpers(useSwal);
316308
const { t } = useHelpers(useI18n);
317309
const { themeValues, dangerThemeValues } = useTheme(props);
318-
319-
/**
320-
* Cached node visibility
321-
*/
322-
const visibility = computed(() => {
323-
return props.nodes.reduce(
324-
(acc, node, nodeIndex) => {
325-
const disableCreateNodeChildren = props.disableCreateNodeChildren?.(node);
326-
const showNodeChildren = props.showNodeChildren?.(node);
327-
const childrenCount = props.childrenCount(node);
328-
const shouldShow = props.selectedNodes[nodeIndex][1] && !!childrenCount;
329-
330-
acc[nodeIndex] = {
331-
disableCreateNodeChildren,
332-
showNodeChildren,
333-
childrenCount,
334-
show: showNodeChildren ?? shouldShow,
335-
};
336-
337-
return acc;
338-
},
339-
{} as Record<number, INodeVisibility>
340-
);
341-
});
342-
343-
function hydrateNode(newNode: T | null, _newErrors?: unknown) {
344-
if (!props.hydrateNodes || !newNode) return;
345-
346-
// Replace the node with the updated one
347-
const nodeIndex = props.nodes.findIndex(({ id }) => id === newNode.id);
348-
const existingNode = props.nodes[nodeIndex];
349-
const updatedNodes = props.nodes.toSpliced(nodeIndex, 1, { ...existingNode, ...newNode });
350-
351-
props.hydrateNodes(updatedNodes);
352-
}
353-
354-
/**
355-
* Creates children for given node
356-
* sometimes it could fail but still update (api issue)
357-
*
358-
* @single
359-
*/
360-
const createNodeChildrenAndRefresh: iNodeFn<T> = async (node: T) => {
361-
// display loader
362-
Swal.fireLoader();
363-
364-
// run process
365-
const response = await useResolveNodeFn(props.createNodeChildren?.(node));
366-
const [updatedParent, event, closeModal] = response;
367-
368-
// unfinished task
369-
if (typeof updatedParent === "undefined" || updatedParent === null) {
370-
if (Swal.isLoading()) Swal.close();
371-
} else if (updatedParent) {
372-
Swal.fire({
373-
icon: "success",
374-
title: t("swal.table_created"),
375-
text: t("swal.table_created_text"),
376-
willOpen() {
377-
// If has children, prefer hydration over refreshing
378-
if (
379-
props.childrenCount(node) &&
380-
props.hydrateNodes &&
381-
typeof updatedParent === "object"
382-
) {
383-
hydrateNode({ ...node, ...updatedParent });
384-
} else if (!props.omitRefresh) props.refresh?.();
385-
386-
closeModal?.();
387-
},
388-
});
389-
} else {
390-
// Error, children possibly not created
391-
Swal.fire({
392-
icon: "warning",
393-
title: t("swal.table_possibly_not_created"),
394-
text: t("swal.table_possibly_not_created_text"),
395-
target: event,
396-
});
397-
}
398-
399-
return response;
400-
};
401310
</script>

packages/components-vue/src/components/table/HeadActions.vue

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
<ActionButtonLink
1818
v-if="
1919
withDefaultSlot &&
20-
nodes.length > 1 &&
21-
nodes.some(childrenCount)
20+
mappedNodes.length > 1 &&
21+
mappedNodes.withChildren
2222
"
2323
:theme="theme"
2424
:active="openNodesCount === selectedNodes.length"
@@ -44,6 +44,7 @@
4444
name="headActions"
4545
v-bind="{
4646
nodes,
47+
mappedNodes,
4748
updateNodeAndRefresh,
4849
cloneNodeAndRefresh,
4950
deleteNodeAndRefresh,

packages/components-vue/src/components/table/HeadContent.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
<template>
22
<!-- Table header -->
33
<thead>
4-
<tr v-if="nodes.length" class="--txtAlign" :class="`--txtSize-${size}`">
4+
<tr v-if="mappedNodes.length" class="--txtAlign" :class="`--txtSize-${size}`">
55
<!-- TODO: define filters, filter table contents -->
66
<th
7-
v-if="nodes.length > 1 || withDefaultSlot"
7+
v-if="mappedNodes.length > 1 || withDefaultSlot"
88
class="--sticky"
99
:class="{ ['is--selected']: sort && !!ordering['id'] }"
1010
data-column-name="id"

0 commit comments

Comments
 (0)