quasar-ui-danx 0.0.42 → 0.0.44

Sign up to get free protection for your applications and to get access to all the features.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quasar-ui-danx",
3
- "version": "0.0.42",
3
+ "version": "0.0.44",
4
4
  "author": "Dan <dan@flytedesk.com>",
5
5
  "description": "DanX Vue / Quasar component library",
6
6
  "license": "MIT",
@@ -48,44 +48,17 @@
48
48
  </q-th>
49
49
  </template>
50
50
  <template #body-cell="rowProps">
51
- <q-td :key="rowProps.key" :props="rowProps">
52
- <component
53
- :is="rowProps.col.onClick ? 'a' : 'div'"
54
- class="flex items-center flex-nowrap"
55
- :class="{'justify-end': rowProps.col.align === 'right', 'justify-center': rowProps.col.align === 'center', 'justify-start': rowProps.col.align === 'left'}"
56
- :style="getColumnStyle(rowProps.col)"
57
- @click="() => rowProps.col.onClick && rowProps.col.onClick(rowProps.row)"
58
- >
59
- <RenderComponent
60
- v-if="rowProps.col.component"
61
- :params="[rowProps.row]"
62
- :component="rowProps.col.component"
63
- :text="rowProps.value"
64
- @action="action => $emit('action', {action,target: rowProps.row})"
65
- />
66
- <div v-else-if="rowProps.col.fieldList">
67
- <div v-for="field in rowProps.col.fieldList" :key="field">
68
- {{ rowProps.row[field] }}
69
- </div>
70
- </div>
71
- <div v-else>
72
- <slot v-bind="{name: rowProps.col.name, row: rowProps.row, value: rowProps.value}">
73
- {{ rowProps.value }}
74
- </slot>
75
- </div>
76
- <div v-if="rowProps.col.actions" class="flex-grow flex justify-end pl-2">
77
- <ActionMenu
78
- :actions="rowProps.col.actions"
79
- :target="rowProps.row"
80
- :loading="isSavingRow(rowProps.row)"
81
- @action="(action) => $emit('action', action, rowProps.row)"
82
- />
83
- </div>
84
- </component>
85
- </q-td>
51
+ <ActionTableColumn
52
+ :row-props="rowProps"
53
+ :settings="columnSettings[rowProps.col.name]"
54
+ :is-saving="isSavingRow(rowProps.row)"
55
+ @action="$emit('action', $event, rowProps.row)"
56
+ >
57
+ <slot />
58
+ </ActionTableColumn>
86
59
  </template>
87
60
  <template #bottom>
88
- <ActionInputComponent />
61
+ <ActionVnode />
89
62
  </template>
90
63
  </q-table>
91
64
  </template>
@@ -95,10 +68,10 @@ import { ref } from 'vue';
95
68
  import { getItem, setItem } from '../../helpers';
96
69
  import { DragHandleIcon as RowResizeIcon } from '../../svg';
97
70
  import { HandleDraggable } from '../DragAndDrop';
98
- import { ActionInputComponent, mapSortBy, RenderComponent } from '../index';
99
- import { ActionMenu, EmptyTableState, registerStickyScrolling, TableSummaryRow } from './index';
71
+ import { ActionVnode, mapSortBy } from '../index';
72
+ import { ActionTableColumn, EmptyTableState, registerStickyScrolling, TableSummaryRow } from './index';
100
73
 
101
- defineEmits(['action', 'filter', 'update:quasar-pagination', 'update:selected-rows']);
74
+ defineEmits(['action', 'update:quasar-pagination', 'update:selected-rows']);
102
75
  const props = defineProps({
103
76
  name: {
104
77
  type: String,
@@ -145,19 +118,14 @@ registerStickyScrolling(actionTable);
145
118
  const COLUMN_SETTINGS_KEY = `column-settings-${props.name}`;
146
119
  const columnSettings = ref(getItem(COLUMN_SETTINGS_KEY) || {});
147
120
  function onResizeColumn(column, val) {
148
- columnSettings.value[column.name] = Math.max(Math.min(val.distance + val.startDropZoneSize, column.maxWidth || 500), column.minWidth || 80);
121
+ columnSettings.value = {
122
+ ...columnSettings.value,
123
+ [column.name]: {
124
+ width: Math.max(Math.min(val.distance + val.startDropZoneSize, column.maxWidth || 500), column.minWidth || 80)
125
+ }
126
+ };
149
127
  setItem(COLUMN_SETTINGS_KEY, columnSettings.value);
150
128
  }
151
- function getColumnStyle(column) {
152
- const width = columnSettings.value[column.name] || column.width;
153
-
154
- if (width) {
155
- return {
156
- width: `${width}px`
157
- };
158
- }
159
- return null;
160
- }
161
129
 
162
130
  function isSavingRow(row) {
163
131
  if (!props.isSavingTarget) return false;
@@ -0,0 +1,72 @@
1
+ <template>
2
+ <q-td :key="rowProps.key" :props="rowProps" :style="columnStyle">
3
+ <div
4
+ class="flex items-center flex-nowrap"
5
+ :class="columnClass"
6
+ >
7
+ <a
8
+ v-if="column.onClick"
9
+ class="flex-grow"
10
+ @click="column.onClick(row)"
11
+ >
12
+ <RenderVnode
13
+ v-if="column.vnode"
14
+ :vnode="column.vnode(row)"
15
+ />
16
+ <slot v-else v-bind="{name: column.name, row, value}">
17
+ {{ value }}
18
+ </slot>
19
+ </a>
20
+ <div v-else class="flex-grow">
21
+ <RenderVnode
22
+ v-if="column.vnode"
23
+ :vnode="column.vnode(row)"
24
+ />
25
+ <slot v-else v-bind="{name: column.name, row, value}">
26
+ {{ value }}
27
+ </slot>
28
+ </div>
29
+ <div v-if="column.actions" class="flex flex-shrink-0 pl-2">
30
+ <ActionMenu
31
+ :actions="column.actions"
32
+ :target="row"
33
+ :loading="isSaving"
34
+ @action="$emit('action', $event)"
35
+ />
36
+ </div>
37
+ </div>
38
+ </q-td>
39
+ </template>
40
+ <script setup>
41
+ import { computed } from 'vue';
42
+ import { RenderVnode } from '../Utility';
43
+ import { ActionMenu } from './index';
44
+
45
+ defineEmits(['action']);
46
+ const props = defineProps({
47
+ rowProps: {
48
+ type: Object,
49
+ required: true
50
+ },
51
+ settings: {
52
+ type: Object,
53
+ default: null
54
+ },
55
+ isSaving: Boolean
56
+ });
57
+
58
+ const row = computed(() => props.rowProps.row);
59
+ const column = computed(() => props.rowProps.col);
60
+ const value = computed(() => props.rowProps.value);
61
+
62
+ const columnStyle = computed(() => {
63
+ const width = props.settings?.width || column.value.width;
64
+ return width ? { width: `${width}px` } : null;
65
+ });
66
+
67
+ const columnClass = computed(() => ({
68
+ 'justify-end': column.value.align === 'right',
69
+ 'justify-center': column.value.align === 'center',
70
+ 'justify-start': column.value.align === 'left'
71
+ }));
72
+ </script>
@@ -6,5 +6,6 @@ export * from "./listHelpers";
6
6
  export * from "./tableColumns";
7
7
  export { default as ActionMenu } from "./ActionMenu.vue";
8
8
  export { default as ActionTable } from "./ActionTable.vue";
9
+ export { default as ActionTableColumn } from "./ActionTableColumn.vue";
9
10
  export { default as EmptyTableState } from "./EmptyTableState.vue";
10
11
  export { default as TableSummaryRow } from "./TableSummaryRow.vue";
@@ -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 tab
262
+ * @param panel
263
263
  */
264
- function openItemForm(item, tab) {
264
+ function activatePanel(item, panel) {
265
265
  activeItem.value = item;
266
- activePanel.value = tab;
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
- openItemForm,
339
+ activatePanel,
340
340
  applyFilterFromUrl,
341
341
  setItemInPagedList
342
342
  };
@@ -2,7 +2,7 @@
2
2
  <div class="flex items-center">
3
3
  <component :is="icon" :class="iconClass" />
4
4
  <div :class="textClass">
5
- <slot />
5
+ <slot>{{ text }}</slot>
6
6
  </div>
7
7
  </div>
8
8
  </template>
@@ -14,11 +14,15 @@ defineProps({
14
14
  },
15
15
  iconClass: {
16
16
  type: String,
17
- default: "w-6"
17
+ default: 'w-6'
18
+ },
19
+ text: {
20
+ type: String,
21
+ default: null
18
22
  },
19
23
  textClass: {
20
24
  type: String,
21
- default: "ml-2"
25
+ default: 'ml-2'
22
26
  }
23
27
  });
24
28
  </script>
@@ -0,0 +1,23 @@
1
+ <template>
2
+ <div>
3
+ <RenderVnode
4
+ v-if="activeActionVnode"
5
+ :vnode="activeActionVnode.vnode"
6
+ :is-saving="isSaving"
7
+ @confirm="onConfirm"
8
+ @close="activeActionVnode.cancel"
9
+ />
10
+ </div>
11
+ </template>
12
+ <script setup>
13
+ import { ref } from 'vue';
14
+ import { activeActionVnode } from '../../../helpers';
15
+ import { RenderVnode } from './index';
16
+
17
+ const isSaving = ref(false);
18
+ async function onConfirm(input) {
19
+ isSaving.value = true;
20
+ await activeActionVnode.value.confirm(input);
21
+ isSaving.value = false;
22
+ }
23
+ </script>
@@ -25,17 +25,13 @@ const props = defineProps({
25
25
  type: Array,
26
26
  default: () => []
27
27
  },
28
- text: {
29
- type: String,
30
- default: undefined
31
- },
32
28
  overrideProps: {
33
29
  type: Object,
34
30
  default: () => ({})
35
31
  }
36
32
  });
37
33
 
38
- const content = computed(() => resolvedComponent.value?.value || resolvedComponent.value?.props?.text || props.text);
34
+ const content = computed(() => resolvedComponent.value?.value || resolvedComponent.value?.props?.text);
39
35
  const resolvedComponent = computed(() => {
40
36
  if (typeof props.component === 'function') {
41
37
  return props.component(...props.params);
@@ -0,0 +1,5 @@
1
+ <script>
2
+ const RenderVnode = (props) => props.vnode;
3
+ RenderVnode.props = { vnode: { type: Object, required: true } };
4
+ export default RenderVnode;
5
+ </script>
@@ -1,2 +1,3 @@
1
- export { default as ActionInputComponent } from "./ActionInputComponent.vue";
1
+ export { default as ActionVnode } from "./ActionVnode.vue";
2
2
  export { default as RenderComponent } from "./RenderComponent.vue";
3
+ export { default as RenderVnode } from "./RenderVnode.vue";
@@ -1,4 +1,4 @@
1
- import { shallowRef } from "vue";
1
+ import { shallowRef, VNode } from "vue";
2
2
  import { FlashMessages } from "./index";
3
3
 
4
4
  interface ActionOptions {
@@ -8,7 +8,7 @@ interface ActionOptions {
8
8
  batch?: boolean;
9
9
  category?: string;
10
10
  class?: string;
11
- inputComponent?: (target: object[] | object) => any;
11
+ vnode?: (target: object[] | object) => VNode;
12
12
  enabled?: (target: object) => boolean;
13
13
  batchEnabled?: (targets: object[]) => boolean;
14
14
  onAction?: (action: string | null, target: object, input: any) => Promise<any>;
@@ -18,7 +18,7 @@ interface ActionOptions {
18
18
  onFinish?: (action: string | null, targets: object, input: any) => any;
19
19
  }
20
20
 
21
- export const activeActionInput = shallowRef(null);
21
+ export const activeActionVnode = shallowRef(null);
22
22
 
23
23
  /**
24
24
  * Hook to perform an action on a set of targets
@@ -98,25 +98,25 @@ export function useActions(actions: ActionOptions[], globalOptions: ActionOption
98
98
  */
99
99
  async performAction(name: string | object, target: object[] | object, input: any = null) {
100
100
  const action = resolveAction(name);
101
- const component = action.inputComponent && action.inputComponent(target);
101
+ const vnode = action.vnode && action.vnode(target);
102
102
  let result = null;
103
103
 
104
104
  isSavingTarget.value = target;
105
105
 
106
- // If no component input is required, we can directly perform the action
107
- if (component) {
108
- // If the action requires an input, we set the activeActionInput to the input component.
109
- // This will tell the ActionInputComponent to render the input component, and confirm or cancel the
106
+ // If additional input is required, first render the vnode and wait for the confirm or cancel action
107
+ if (vnode) {
108
+ // If the action requires an input, we set the activeActionVnode to the input component.
109
+ // This will tell the ActionVnode to render the input component, and confirm or cancel the
110
110
  // action The confirm function has the input from the component passed and will resolve the promise
111
111
  // with the result of the action
112
112
  result = await new Promise((resolve, reject) => {
113
- activeActionInput.value = {
114
- component,
113
+ activeActionVnode.value = {
114
+ vnode,
115
115
  confirm: async input => {
116
116
  const result = await onConfirmAction(action, target, input);
117
117
 
118
118
  // Only resolve when we have a non-error response, so we can show the error message w/o
119
- // hiding the dialog / inputComponent
119
+ // hiding the dialog / vnode
120
120
  if (result === undefined || result === true || result?.success) {
121
121
  resolve(result);
122
122
  }
@@ -125,7 +125,7 @@ export function useActions(actions: ActionOptions[], globalOptions: ActionOption
125
125
  };
126
126
  });
127
127
 
128
- activeActionInput.value = null;
128
+ activeActionVnode.value = null;
129
129
  } else {
130
130
  result = await onConfirmAction(action, target, input);
131
131
  }
@@ -183,6 +183,5 @@ async function onConfirmAction(action: ActionOptions, target: object[] | object,
183
183
  action.onFinish(result, target, input);
184
184
  }
185
185
 
186
- console.log("onConrirm result", result);
187
186
  return result;
188
187
  }
@@ -1,23 +0,0 @@
1
- <template>
2
- <div>
3
- <RenderComponent
4
- v-if="activeActionInput"
5
- :component="activeActionInput.component"
6
- :is-saving="isSaving"
7
- @confirm="onConfirm"
8
- @close="activeActionInput.cancel"
9
- />
10
- </div>
11
- </template>
12
- <script setup>
13
- import { ref } from 'vue';
14
- import { activeActionInput } from '../../../helpers';
15
- import RenderComponent from './RenderComponent';
16
-
17
- const isSaving = ref(false);
18
- async function onConfirm(input) {
19
- isSaving.value = true;
20
- await activeActionInput.value.confirm(input);
21
- isSaving.value = false;
22
- }
23
- </script>