quasar-ui-danx 0.0.23 → 0.0.25

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quasar-ui-danx",
3
- "version": "0.0.23",
3
+ "version": "0.0.25",
4
4
  "author": "Dan <dan@flytedesk.com>",
5
5
  "description": "DanX Vue / Quasar component library",
6
6
  "license": "MIT",
@@ -0,0 +1,97 @@
1
+ <template>
2
+ <div>
3
+ <PopoverMenu
4
+ class="px-4 h-full flex"
5
+ :items="items"
6
+ @action-item="onAction"
7
+ />
8
+ <Component
9
+ v-if="confirmDialog"
10
+ :is="confirmDialog.is"
11
+ v-bind="confirmDialog.props"
12
+ :is-saving="isSaving"
13
+ @close="onCancel"
14
+ @confirm="onConfirmAction"
15
+ />
16
+ </div>
17
+ </template>
18
+ <script setup>
19
+ import { ref, shallowRef } from 'vue';
20
+ import { FlashMessages } from '../../helpers';
21
+ import { PopoverMenu } from '../Utility';
22
+
23
+ const emit = defineEmits(['action']);
24
+ const props = defineProps({
25
+ items: {
26
+ type: Array,
27
+ required: true
28
+ },
29
+ rows: {
30
+ type: Array,
31
+ required: true
32
+ }
33
+ });
34
+
35
+
36
+ const activeAction = shallowRef(null);
37
+ const confirmDialog = shallowRef(null);
38
+ const isSaving = ref(false);
39
+
40
+ function onAction(item) {
41
+ emit('action', item);
42
+
43
+ activeAction.value = item;
44
+
45
+ if (item.confirmDialog) {
46
+ confirmDialog.value = typeof item.confirmDialog === 'function' ? item.confirmDialog(props.rows) : item.confirmDialog;
47
+ } else {
48
+ console.log('handle default action');
49
+ }
50
+ }
51
+
52
+ function onCancel() {
53
+ activeAction.value = null;
54
+ confirmDialog.value = null;
55
+ }
56
+
57
+ async function onConfirmAction(input) {
58
+ if (!activeAction.value.onAction) {
59
+ throw new Error('No onAction handler found for the selected action:' + activeAction.value.action);
60
+ }
61
+
62
+ isSaving.value = true;
63
+ const result = await activeAction.value.onAction(input, props.rows);
64
+ isSaving.value = false;
65
+
66
+ if (!result.success) {
67
+ const errors = [];
68
+ if (result.errors) {
69
+ errors.push(...result.errors);
70
+ } else if (result.error) {
71
+ errors.push(result.error.message);
72
+ } else {
73
+ errors.push('An unknown error occurred. Please try again later.');
74
+ }
75
+
76
+ FlashMessages.combine('error', errors);
77
+
78
+ if (activeAction.value.onError) {
79
+ await activeAction.value.onError(result, input);
80
+ }
81
+ }
82
+
83
+ FlashMessages.success(`The update was successful`);
84
+
85
+ if (activeAction.value.onSuccess) {
86
+ await activeAction.value.onSuccess(result, input);
87
+ }
88
+
89
+ if (activeAction.value.onFinish) {
90
+ await activeAction.value.onFinish();
91
+ }
92
+
93
+ confirmDialog.value = null;
94
+ activeAction.value = null;
95
+ }
96
+
97
+ </script>
@@ -12,7 +12,7 @@
12
12
  color="blue-base"
13
13
  @update:selected="$emit('update:selected-rows', $event)"
14
14
  @update:pagination="() => {}"
15
- @request="$emit('update:quasar-pagination', $event.pagination)"
15
+ @request="$emit('update:quasar-pagination', {...$event.pagination, __sort: mapSortBy($event.pagination, columns)})"
16
16
  >
17
17
  <template #no-data>
18
18
  <slot name="empty">
@@ -51,24 +51,30 @@
51
51
  <q-td :key="rowProps.key" :props="rowProps">
52
52
  <component
53
53
  :is="rowProps.col.onClick ? 'a' : 'div'"
54
+ class="flex items-center flex-nowrap"
54
55
  @click="() => rowProps.col.onClick && rowProps.col.onClick(rowProps.row)"
55
56
  >
56
- <template v-if="rowProps.col.component">
57
- <RenderComponent
58
- :row-props="rowProps"
59
- @action="$emit('action', $event)"
60
- />
61
- </template>
62
- <template v-else-if="rowProps.col.fieldList">
57
+ <RenderComponent
58
+ v-if="rowProps.col.component"
59
+ :row-props="rowProps"
60
+ @action="$emit('action', $event)"
61
+ />
62
+ <div v-else-if="rowProps.col.fieldList">
63
63
  <div v-for="field in rowProps.col.fieldList" :key="field">
64
64
  {{ rowProps.row[field] }}
65
65
  </div>
66
- </template>
67
- <template v-else>
66
+ </div>
67
+ <div v-else>
68
68
  <slot v-bind="{name: rowProps.col.name, row: rowProps.row, value: rowProps.value}">
69
69
  {{ rowProps.value }}
70
70
  </slot>
71
- </template>
71
+ </div>
72
+ <ActionMenu
73
+ v-if="rowProps.col.actions" class="ml-2"
74
+ :items="rowProps.col.actions"
75
+ :rows="[rowProps.row]"
76
+ @action="(action) => $emit('action', {action: action, row: rowProps.row})"
77
+ />
72
78
  </component>
73
79
  </q-td>
74
80
  </template>
@@ -79,7 +85,14 @@
79
85
  import { ref } from 'vue';
80
86
  import { DragHandleIcon as RowResizeIcon } from '../../svg';
81
87
  import { HandleDraggable } from '../DragAndDrop';
82
- import { EmptyTableState, registerStickyScrolling, RenderComponent, TableSummaryRow } from './index';
88
+ import {
89
+ ActionMenu,
90
+ EmptyTableState,
91
+ mapSortBy,
92
+ registerStickyScrolling,
93
+ RenderComponent,
94
+ TableSummaryRow
95
+ } from './index';
83
96
 
84
97
  defineEmits(['action', 'filter', 'update:quasar-pagination', 'update:selected-rows']);
85
98
  defineProps({
@@ -23,7 +23,7 @@
23
23
  </template>
24
24
  <script setup>
25
25
  import { computed, ref } from 'vue';
26
- import PopoverMenu from '../../components/Utility/Popover/PopoverMenu';
26
+ import { PopoverMenu } from '../Utility';
27
27
 
28
28
  const emit = defineEmits(['action']);
29
29
  const props = defineProps({
@@ -33,7 +33,7 @@
33
33
  </div>
34
34
 
35
35
  <div class="max-w-[50em] flex items-stretch justify-start">
36
- <ImagePreview
36
+ <FilePreview
37
37
  v-for="file in uploadedFiles"
38
38
  :key="'file-upload-' + file.id"
39
39
  class="w-32 m-2 cursor-pointer bg-neutral-plus-5"
@@ -44,7 +44,7 @@
44
44
  :removable="!readonly && !disable"
45
45
  @remove="onRemove(file)"
46
46
  />
47
- <ImagePreview
47
+ <FilePreview
48
48
  v-if="!disable && !readonly"
49
49
  class="w-32 m-2 cursor-pointer border border-dashed border-blue-base"
50
50
  disabled
@@ -63,7 +63,7 @@
63
63
  <script setup>
64
64
  import { onMounted } from 'vue';
65
65
  import { useMultiFileUpload } from '../../../../helpers';
66
- import { ImagePreview } from '../../../Utility';
66
+ import { FilePreview } from '../../../Utility';
67
67
  import FieldLabel from './FieldLabel';
68
68
 
69
69
  const emit = defineEmits(['update:model-value']);
@@ -31,7 +31,7 @@
31
31
  />
32
32
  </div>
33
33
 
34
- <ImagePreview
34
+ <FilePreview
35
35
  v-if="!readonly || uploadedFile"
36
36
  class="w-32 cursor-pointer mt-2"
37
37
  :class="{'border border-dashed border-blue-base': !uploadedFile, 'mx-auto': !readonly}"
@@ -50,7 +50,7 @@
50
50
  <script setup>
51
51
  import { onMounted } from 'vue';
52
52
  import { useSingleFileUpload } from '../../../../helpers';
53
- import { ImagePreview } from '../../../Utility';
53
+ import { FilePreview } from '../../../Utility';
54
54
  import FieldLabel from './FieldLabel';
55
55
 
56
56
  const emit = defineEmits(['update:model-value']);
@@ -3,6 +3,7 @@ export * from "./Form";
3
3
  export * from "./listActions";
4
4
  export * from "./listHelpers";
5
5
  export * from "./tableColumns";
6
+ export { default as ActionMenu } from "./ActionMenu.vue";
6
7
  export { default as ActionTable } from "./ActionTable.vue";
7
8
  export { default as BatchActionMenu } from "./BatchActionMenu.vue";
8
9
  export { default as EmptyTableState } from "./EmptyTableState.vue";
@@ -1,6 +1,6 @@
1
1
  import { computed, ref, watch } from "vue";
2
2
  import { getItem, setItem } from "../../helpers";
3
- import { getFilterFromUrl, mapSortBy, waitForRef } from "./listHelpers";
3
+ import { getFilterFromUrl, waitForRef } from "./listHelpers";
4
4
 
5
5
  export function useListActions(name, {
6
6
  listRoute,
@@ -10,7 +10,6 @@ export function useListActions(name, {
10
10
  applyActionRoute = null,
11
11
  applyBatchActionRoute = null,
12
12
  itemDetailsRoute = null,
13
- columns = null,
14
13
  filterGroups = null,
15
14
  refreshFilters = false,
16
15
  urlPattern = null,
@@ -30,6 +29,7 @@ export function useListActions(name, {
30
29
  const filterActiveCount = computed(() => Object.keys(filter.value).filter(key => filter.value[key] !== undefined).length);
31
30
 
32
31
  const PAGING_DEFAULT = {
32
+ __sort: null,
33
33
  sortBy: null,
34
34
  descending: false,
35
35
  page: 1,
@@ -42,7 +42,7 @@ export function useListActions(name, {
42
42
  perPage: quasarPagination.value.rowsPerPage,
43
43
  page: quasarPagination.value.page,
44
44
  filter: { ...filter.value, ...globalFilter.value },
45
- sort: columns ? mapSortBy(quasarPagination.value, columns) : undefined
45
+ sort: quasarPagination.value.__sort || undefined
46
46
  }));
47
47
 
48
48
  // When any part of the filter changes, get the new list of creatives
@@ -95,15 +95,15 @@ export function useListActions(name, {
95
95
  isLoadingFilters.value = false;
96
96
  }
97
97
 
98
- // A flat list of valid filterable field names
99
- const validFilterKeys = computed(() => filterGroups?.value?.map(group => group.fields.map(field => field.name)).flat());
100
-
101
98
  /**
102
99
  * Watches for a filter URL parameter and applies the filter if it is set.
103
100
  */
104
- function applyFilterFromUrl(url) {
101
+ function applyFilterFromUrl(url, filterGroups = null) {
105
102
  if (url.match(urlPattern)) {
106
- const urlFilter = getFilterFromUrl(url, validFilterKeys.value);
103
+ // A flat list of valid filterable field names
104
+ const validFilterKeys = filterGroups?.value?.map(group => group.fields.map(field => field.name)).flat();
105
+
106
+ const urlFilter = getFilterFromUrl(url, validFilterKeys);
107
107
 
108
108
  if (Object.keys(urlFilter).length > 0) {
109
109
  filter.value = urlFilter;
@@ -187,9 +187,6 @@ export function useListActions(name, {
187
187
  filter.value = { ...filterDefaults, ...filter.value };
188
188
  }
189
189
 
190
- // Load the URL filters if they are set
191
- applyFilterFromUrl(window.location.href);
192
-
193
190
  setTimeout(() => {
194
191
  if (!isLoadingList.value) {
195
192
  loadList();
@@ -355,7 +352,6 @@ export function useListActions(name, {
355
352
  isApplyingBatchAction,
356
353
  activeItem,
357
354
  formTab,
358
- columns,
359
355
  filterGroups,
360
356
 
361
357
  // Actions
@@ -16,8 +16,8 @@
16
16
  </div>
17
17
  </template>
18
18
  <script setup>
19
- import SvgImg from 'src/components/Utility/Files/SvgImg';
20
19
  import { DragHandleDotsIcon as DragHandleIcon } from '../../svg';
20
+ import { SvgImg } from '../Utility';
21
21
  import { ListDragAndDrop } from './listDragAndDrop';
22
22
 
23
23
  const emit = defineEmits(['position', 'update:list-items']);
@@ -99,10 +99,10 @@
99
99
 
100
100
  <script setup>
101
101
  import { DocumentTextIcon as TextFileIcon, DownloadIcon, PlayIcon } from '@heroicons/vue/outline';
102
- import { FullScreenCarouselDialog } from 'src/components/Utility/index';
103
- import { download } from 'src/helpers';
104
- import { ImageIcon, PdfIcon, TrashIcon as RemoveIcon } from 'src/svg';
105
102
  import { computed, ref } from 'vue';
103
+ import { download } from '../../../helpers';
104
+ import { ImageIcon, PdfIcon, TrashIcon as RemoveIcon } from '../../../svg';
105
+ import { FullScreenCarouselDialog } from '../Dialogs';
106
106
 
107
107
  const emit = defineEmits(['remove']);
108
108
  const props = defineProps({
@@ -37,19 +37,19 @@
37
37
  :key="item.action"
38
38
  clickable
39
39
  :class="item.class"
40
- @click="$emit('action', item.action)"
40
+ @click="onAction(item)"
41
41
  >
42
42
  {{ item.label }}
43
- </q-item>
43
+ </q-item>
44
44
  </template>
45
- </q-list>
46
- </q-menu>
45
+ </q-list>
46
+ </q-menu>
47
47
  </a>
48
48
  </template>
49
49
  <script setup>
50
50
  import { DotsVerticalIcon as MenuIcon } from '@heroicons/vue/outline';
51
51
 
52
- defineEmits(['action']);
52
+ const emit = defineEmits(['action', 'action-item']);
53
53
  defineProps({
54
54
  items: {
55
55
  type: Array,
@@ -61,4 +61,9 @@ defineProps({
61
61
  disabled: Boolean,
62
62
  loading: Boolean
63
63
  });
64
+
65
+ function onAction(item) {
66
+ emit('action', item.action);
67
+ emit('action-item', item);
68
+ }
64
69
  </script>