quasar-ui-danx 0.0.41 → 0.0.43
Sign up to get free protection for your applications and to get access to all the features.
- package/package.json +1 -1
- package/src/components/ActionTable/ActionMenu.vue +7 -4
- package/src/components/ActionTable/ActionTable.vue +19 -8
- package/src/components/ActionTable/listControls.ts +4 -4
- package/src/components/Utility/Tools/RenderComponent.vue +9 -5
- package/src/components/Utility/Tools/RenderVNode.vue +6 -0
- package/src/components/Utility/Tools/index.ts +1 -0
- package/src/helpers/actions.ts +18 -12
package/package.json
CHANGED
@@ -21,7 +21,7 @@ const props = defineProps({
|
|
21
21
|
},
|
22
22
|
target: {
|
23
23
|
type: [Array, Object],
|
24
|
-
|
24
|
+
default: () => []
|
25
25
|
},
|
26
26
|
tooltip: {
|
27
27
|
type: String,
|
@@ -34,10 +34,13 @@ const props = defineProps({
|
|
34
34
|
}
|
35
35
|
});
|
36
36
|
|
37
|
-
const hasTarget = computed(() => !!props.target
|
37
|
+
const hasTarget = computed(() => Array.isArray(props.target) ? props.target.length > 0 : !!props.target);
|
38
38
|
|
39
39
|
const activeActions = computed(() => props.actions.filter(action => {
|
40
|
-
if (
|
41
|
-
|
40
|
+
if (Array.isArray(props.target)) {
|
41
|
+
return action.batchEnabled ? action.batchEnabled(props.target) : true;
|
42
|
+
}
|
43
|
+
|
44
|
+
return action.enabled ? action.enabled(props.target) : true;
|
42
45
|
}));
|
43
46
|
</script>
|
@@ -56,12 +56,14 @@
|
|
56
56
|
:style="getColumnStyle(rowProps.col)"
|
57
57
|
@click="() => rowProps.col.onClick && rowProps.col.onClick(rowProps.row)"
|
58
58
|
>
|
59
|
+
<RenderVNode
|
60
|
+
v-if="rowProps.col.vnode"
|
61
|
+
:vnode="rowProps.col.vnode(rowProps.row)"
|
62
|
+
/>
|
59
63
|
<RenderComponent
|
60
|
-
v-if="rowProps.col.component"
|
64
|
+
v-else-if="rowProps.col.component"
|
61
65
|
:params="[rowProps.row]"
|
62
66
|
:component="rowProps.col.component"
|
63
|
-
:text="rowProps.value"
|
64
|
-
@action="$emit('action', $event)"
|
65
67
|
/>
|
66
68
|
<div v-else-if="rowProps.col.fieldList">
|
67
69
|
<div v-for="field in rowProps.col.fieldList" :key="field">
|
@@ -77,8 +79,8 @@
|
|
77
79
|
<ActionMenu
|
78
80
|
:actions="rowProps.col.actions"
|
79
81
|
:target="rowProps.row"
|
80
|
-
:loading="
|
81
|
-
@action="(action) => $emit('action',
|
82
|
+
:loading="isSavingRow(rowProps.row)"
|
83
|
+
@action="(action) => $emit('action', action, rowProps.row)"
|
82
84
|
/>
|
83
85
|
</div>
|
84
86
|
</component>
|
@@ -95,10 +97,10 @@ import { ref } from 'vue';
|
|
95
97
|
import { getItem, setItem } from '../../helpers';
|
96
98
|
import { DragHandleIcon as RowResizeIcon } from '../../svg';
|
97
99
|
import { HandleDraggable } from '../DragAndDrop';
|
98
|
-
import { ActionInputComponent, mapSortBy, RenderComponent } from '../index';
|
100
|
+
import { ActionInputComponent, mapSortBy, RenderComponent, RenderVNode } from '../index';
|
99
101
|
import { ActionMenu, EmptyTableState, registerStickyScrolling, TableSummaryRow } from './index';
|
100
102
|
|
101
|
-
defineEmits(['action', '
|
103
|
+
defineEmits(['action', 'update:quasar-pagination', 'update:selected-rows']);
|
102
104
|
const props = defineProps({
|
103
105
|
name: {
|
104
106
|
type: String,
|
@@ -116,7 +118,7 @@ const props = defineProps({
|
|
116
118
|
type: Object,
|
117
119
|
required: true
|
118
120
|
},
|
119
|
-
|
121
|
+
isSavingTarget: {
|
120
122
|
type: Object,
|
121
123
|
default: null
|
122
124
|
},
|
@@ -158,6 +160,15 @@ function getColumnStyle(column) {
|
|
158
160
|
}
|
159
161
|
return null;
|
160
162
|
}
|
163
|
+
|
164
|
+
function isSavingRow(row) {
|
165
|
+
if (!props.isSavingTarget) return false;
|
166
|
+
|
167
|
+
if (Array.isArray(props.isSavingTarget)) {
|
168
|
+
return !!props.isSavingTarget.find(t => t.id === row.id);
|
169
|
+
}
|
170
|
+
return props.isSavingTarget.id === row.id;
|
171
|
+
}
|
161
172
|
</script>
|
162
173
|
|
163
174
|
<style lang="scss" scoped>
|
@@ -259,11 +259,11 @@ export function useListControls(name: string, {
|
|
259
259
|
* Opens the item's form with the given item and tab
|
260
260
|
*
|
261
261
|
* @param item
|
262
|
-
* @param
|
262
|
+
* @param panel
|
263
263
|
*/
|
264
|
-
function
|
264
|
+
function activatePanel(item, panel) {
|
265
265
|
activeItem.value = item;
|
266
|
-
activePanel.value =
|
266
|
+
activePanel.value = panel;
|
267
267
|
}
|
268
268
|
|
269
269
|
/**
|
@@ -336,7 +336,7 @@ export function useListControls(name: string, {
|
|
336
336
|
loadMore,
|
337
337
|
refreshAll,
|
338
338
|
getNextItem,
|
339
|
-
|
339
|
+
activatePanel,
|
340
340
|
applyFilterFromUrl,
|
341
341
|
setItemInPagedList
|
342
342
|
};
|
@@ -1,9 +1,16 @@
|
|
1
1
|
<template>
|
2
2
|
<Component
|
3
|
+
v-if="content"
|
3
4
|
:is="resolvedComponent.is"
|
4
5
|
v-bind="{...resolvedComponent.props, ...overrideProps}"
|
5
6
|
@action="$emit('action', $event)"
|
6
|
-
>{{
|
7
|
+
>{{ content }}</Component>
|
8
|
+
<Component
|
9
|
+
v-else
|
10
|
+
:is="resolvedComponent.is"
|
11
|
+
v-bind="{...resolvedComponent.props, ...overrideProps}"
|
12
|
+
@action="$emit('action', $event)"
|
13
|
+
/>
|
7
14
|
</template>
|
8
15
|
<script setup>
|
9
16
|
import { computed } from 'vue';
|
@@ -18,16 +25,13 @@ const props = defineProps({
|
|
18
25
|
type: Array,
|
19
26
|
default: () => []
|
20
27
|
},
|
21
|
-
text: {
|
22
|
-
type: String,
|
23
|
-
default: ''
|
24
|
-
},
|
25
28
|
overrideProps: {
|
26
29
|
type: Object,
|
27
30
|
default: () => ({})
|
28
31
|
}
|
29
32
|
});
|
30
33
|
|
34
|
+
const content = computed(() => resolvedComponent.value?.value || resolvedComponent.value?.props?.text);
|
31
35
|
const resolvedComponent = computed(() => {
|
32
36
|
if (typeof props.component === 'function') {
|
33
37
|
return props.component(...props.params);
|
package/src/helpers/actions.ts
CHANGED
@@ -7,8 +7,10 @@ interface ActionOptions {
|
|
7
7
|
menu?: boolean;
|
8
8
|
batch?: boolean;
|
9
9
|
category?: string;
|
10
|
+
class?: string;
|
10
11
|
inputComponent?: (target: object[] | object) => any;
|
11
|
-
enabled?: (target: object
|
12
|
+
enabled?: (target: object) => boolean;
|
13
|
+
batchEnabled?: (targets: object[]) => boolean;
|
12
14
|
onAction?: (action: string | null, target: object, input: any) => Promise<any>;
|
13
15
|
onBatchAction?: (action: string | null, targets: object[], input: any) => Promise<any>;
|
14
16
|
onSuccess?: (action: string | null, targets: object, input: any) => any;
|
@@ -20,7 +22,7 @@ export const activeActionInput = shallowRef(null);
|
|
20
22
|
|
21
23
|
/**
|
22
24
|
* Hook to perform an action on a set of targets
|
23
|
-
* This helper allows you
|
25
|
+
* This helper allows you to perform actions by name on a set of targets using a provided list of actions
|
24
26
|
*
|
25
27
|
* @param actions
|
26
28
|
* @param {ActionOptions} globalOptions
|
@@ -70,8 +72,6 @@ export function useActions(actions: ActionOptions[], globalOptions: ActionOption
|
|
70
72
|
* TODO: HOW TO INTEGRATE optimistic updates and single item updates?
|
71
73
|
*/
|
72
74
|
async applyAction(item, input, itemData = {}) {
|
73
|
-
isSavingItem.value = item;
|
74
|
-
|
75
75
|
setItemInPagedList({ ...item, ...input, ...itemData });
|
76
76
|
const result = await applyActionRoute(item, input);
|
77
77
|
if (result.success) {
|
@@ -86,7 +86,6 @@ export function useActions(actions: ActionOptions[], globalOptions: ActionOption
|
|
86
86
|
activeItem.value = { ...activeItem.value, ...result.item };
|
87
87
|
}
|
88
88
|
}
|
89
|
-
isSavingItem.value = null;
|
90
89
|
return result;
|
91
90
|
},
|
92
91
|
|
@@ -113,10 +112,19 @@ export function useActions(actions: ActionOptions[], globalOptions: ActionOption
|
|
113
112
|
result = await new Promise((resolve, reject) => {
|
114
113
|
activeActionInput.value = {
|
115
114
|
component,
|
116
|
-
confirm: async
|
117
|
-
|
115
|
+
confirm: async input => {
|
116
|
+
const result = await onConfirmAction(action, target, input);
|
117
|
+
|
118
|
+
// Only resolve when we have a non-error response, so we can show the error message w/o
|
119
|
+
// hiding the dialog / inputComponent
|
120
|
+
if (result === undefined || result === true || result?.success) {
|
121
|
+
resolve(result);
|
122
|
+
}
|
123
|
+
},
|
124
|
+
cancel: resolve
|
118
125
|
};
|
119
126
|
});
|
127
|
+
|
120
128
|
activeActionInput.value = null;
|
121
129
|
} else {
|
122
130
|
result = await onConfirmAction(action, target, input);
|
@@ -146,16 +154,14 @@ async function onConfirmAction(action: ActionOptions, target: object[] | object,
|
|
146
154
|
}
|
147
155
|
|
148
156
|
// If there is no return value or the result marks it as successful, we show a success message
|
149
|
-
if (result === undefined || result?.success) {
|
150
|
-
|
151
|
-
|
152
|
-
FlashMessages.success(`The update was successful`);
|
157
|
+
if (result === undefined || result === true || result?.success) {
|
158
|
+
if (result?.success && Array.isArray(target)) {
|
159
|
+
FlashMessages.success(`Successfully performed action ${action.label} on ${target.length} items`);
|
153
160
|
}
|
154
161
|
|
155
162
|
if (action.onSuccess) {
|
156
163
|
action.onSuccess(result, target, input);
|
157
164
|
}
|
158
|
-
|
159
165
|
} else {
|
160
166
|
const errors = [];
|
161
167
|
if (result.errors) {
|