quasar-ui-danx 0.0.35 → 0.0.37

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.35",
3
+ "version": "0.0.37",
4
4
  "author": "Dan <dan@flytedesk.com>",
5
5
  "description": "DanX Vue / Quasar component library",
6
6
  "license": "MIT",
@@ -3,13 +3,14 @@
3
3
  class="px-2 flex action-button"
4
4
  :items="activeItems"
5
5
  :disabled="targets.length === 0"
6
+ :tooltip="targets.length === 0 ? tooltip : null"
7
+ :loading="isSaving"
8
+ :loading-component="loadingComponent"
6
9
  @action-item="onAction"
7
- >
8
- <q-tooltip v-if="targets.length === 0">{{ tooltip }}</q-tooltip>
9
- </PopoverMenu>
10
+ />
10
11
  </template>
11
12
  <script setup>
12
- import { computed } from 'vue';
13
+ import { computed, ref } from 'vue';
13
14
  import { performAction } from '../../helpers';
14
15
  import { PopoverMenu } from '../Utility';
15
16
 
@@ -26,6 +27,10 @@ const props = defineProps({
26
27
  tooltip: {
27
28
  type: String,
28
29
  default: 'First select records to perform a batch action'
30
+ },
31
+ loadingComponent: {
32
+ type: [Function, Object],
33
+ default: undefined
29
34
  }
30
35
  });
31
36
 
@@ -34,8 +39,11 @@ const activeItems = computed(() => props.items.filter(item => {
34
39
  return typeof item.enabled === 'function' ? !!item.enabled(props.targets?.[0] ?? null, props.targets) : !!item.enabled;
35
40
  }));
36
41
 
37
- function onAction(item) {
42
+ const isSaving = ref(false);
43
+ async function onAction(item) {
38
44
  emit('action', item);
39
- performAction(item, props.targets);
45
+ isSaving.value = true;
46
+ await performAction(item, props.targets);
47
+ isSaving.value = false;
40
48
  }
41
49
  </script>
@@ -41,7 +41,7 @@
41
41
  v-if="rowProps.col.resizeable"
42
42
  :drop-zone="`resize-column-` + rowProps.col.name"
43
43
  class="resize-handle"
44
- @resize="rowProps.col.onResize"
44
+ @resize="onResizeColumn(rowProps.col, $event)"
45
45
  >
46
46
  <RowResizeIcon class="w-4 text-neutral-base" />
47
47
  </HandleDraggable>
@@ -53,6 +53,7 @@
53
53
  :is="rowProps.col.onClick ? 'a' : 'div'"
54
54
  class="flex items-center flex-nowrap"
55
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)"
56
57
  @click="() => rowProps.col.onClick && rowProps.col.onClick(rowProps.row)"
57
58
  >
58
59
  <RenderComponent
@@ -87,19 +88,18 @@
87
88
 
88
89
  <script setup>
89
90
  import { ref } from 'vue';
91
+ import { getItem, setItem } from '../../helpers';
90
92
  import { DragHandleIcon as RowResizeIcon } from '../../svg';
91
93
  import { HandleDraggable } from '../DragAndDrop';
92
- import {
93
- ActionMenu,
94
- EmptyTableState,
95
- mapSortBy,
96
- registerStickyScrolling,
97
- RenderComponent,
98
- TableSummaryRow
99
- } from './index';
94
+ import { mapSortBy, RenderComponent } from '../index';
95
+ import { ActionMenu, EmptyTableState, registerStickyScrolling, TableSummaryRow } from './index';
100
96
 
101
97
  defineEmits(['action', 'filter', 'update:quasar-pagination', 'update:selected-rows']);
102
- defineProps({
98
+ const props = defineProps({
99
+ name: {
100
+ type: String,
101
+ required: true
102
+ },
103
103
  label: {
104
104
  type: String,
105
105
  required: true
@@ -133,6 +133,23 @@ defineProps({
133
133
  });
134
134
  const actionTable = ref(null);
135
135
  registerStickyScrolling(actionTable);
136
+
137
+ const COLUMN_SETTINGS_KEY = `column-settings-${props.name}`;
138
+ const columnSettings = ref(getItem(COLUMN_SETTINGS_KEY) || {});
139
+ function onResizeColumn(column, val) {
140
+ columnSettings.value[column.name] = Math.max(Math.min(val.distance + val.startDropZoneSize, column.maxWidth || 500), column.minWidth || 80);
141
+ setItem(COLUMN_SETTINGS_KEY, columnSettings.value);
142
+ }
143
+ function getColumnStyle(column) {
144
+ const width = columnSettings.value[column.name] || column.width;
145
+
146
+ if (width) {
147
+ return {
148
+ width: `${width}px`
149
+ };
150
+ }
151
+ return null;
152
+ }
136
153
  </script>
137
154
 
138
155
  <style lang="scss" scoped>
@@ -7,5 +7,4 @@ export * from "./tableColumns";
7
7
  export { default as ActionMenu } from "./ActionMenu.vue";
8
8
  export { default as ActionTable } from "./ActionTable.vue";
9
9
  export { default as EmptyTableState } from "./EmptyTableState.vue";
10
- export { default as RenderComponent } from "./RenderComponent.vue";
11
10
  export { default as TableSummaryRow } from "./TableSummaryRow.vue";
@@ -252,10 +252,10 @@ export function useListActions(name: string, {
252
252
  return result;
253
253
  }
254
254
 
255
- // The active ad for viewing / editing in the Ad Form
255
+ // The active ad for viewing / editing
256
256
  const activeItem = ref(null);
257
- // Controls the tab on the Ad Form
258
- const formTab = ref("general");
257
+ // Controls the active panel (ie: tab) if rendering a panels drawer or similar
258
+ const activePanel = ref(null);
259
259
 
260
260
  /**
261
261
  * Gets the additional details for the currently active item.
@@ -293,7 +293,7 @@ export function useListActions(name: string, {
293
293
  */
294
294
  function openItemForm(item, tab) {
295
295
  activeItem.value = item;
296
- formTab.value = tab;
296
+ activePanel.value = tab;
297
297
  }
298
298
 
299
299
  /**
@@ -357,7 +357,7 @@ export function useListActions(name: string, {
357
357
  quasarPagination,
358
358
  isApplyingActionToItem,
359
359
  activeItem,
360
- formTab,
360
+ activePanel,
361
361
 
362
362
  // Actions
363
363
  initialize,
@@ -1,11 +1,10 @@
1
1
  import { computed, ref, watch } from "vue";
2
2
  import { getItem, setItem } from "../../helpers";
3
3
 
4
- export function useTableColumns(name, columns, options = { titleMinWidth: 120, titleMaxWidth: 200 }) {
4
+ export function useTableColumns(name, columns) {
5
5
  const COLUMN_ORDER_KEY = `${name}-column-order`;
6
6
  const VISIBLE_COLUMNS_KEY = `${name}-visible-columns`;
7
7
  const TITLE_COLUMNS_KEY = `${name}-title-columns`;
8
- const TITLE_WIDTH_KEY = `${name}-title-width`;
9
8
 
10
9
  // The list that defines the order the columns should appear in
11
10
  const columnOrder = ref(getItem(COLUMN_ORDER_KEY) || []);
@@ -16,17 +15,6 @@ export function useTableColumns(name, columns, options = { titleMinWidth: 120, t
16
15
  // Title columns will have their name appear on the first column of the table as part of the records' title
17
16
  const titleColumnNames = ref(getItem(TITLE_COLUMNS_KEY, []));
18
17
 
19
- // The width of the title column
20
- const titleWidth = ref(getItem(TITLE_WIDTH_KEY, options.titleMinWidth));
21
-
22
- /**
23
- * When the title column is resized, update the titleWidth
24
- * @param val
25
- */
26
- function onResizeTitleColumn(val) {
27
- titleWidth.value = Math.max(Math.min(val.distance + val.startDropZoneSize, options.titleMaxWidth), options.titleMinWidth);
28
- }
29
-
30
18
  // Columns that should be locked to the left side of the table
31
19
  const lockedColumns = computed(() => orderedColumns.value.slice(0, 1));
32
20
 
@@ -57,7 +45,6 @@ export function useTableColumns(name, columns, options = { titleMinWidth: 120, t
57
45
  // Save changes to the list of hidden columns in localStorage
58
46
  watch(() => hiddenColumnNames.value, () => setItem(VISIBLE_COLUMNS_KEY, hiddenColumnNames.value));
59
47
  watch(() => titleColumnNames.value, () => setItem(TITLE_COLUMNS_KEY, titleColumnNames.value));
60
- watch(() => titleWidth.value, () => setItem(TITLE_WIDTH_KEY, titleWidth.value));
61
48
 
62
49
  return {
63
50
  sortableColumns,
@@ -65,8 +52,6 @@ export function useTableColumns(name, columns, options = { titleMinWidth: 120, t
65
52
  visibleColumns,
66
53
  hiddenColumnNames,
67
54
  titleColumnNames,
68
- titleWidth,
69
- orderedTitleColumns,
70
- onResizeTitleColumn
55
+ orderedTitleColumns
71
56
  };
72
57
  }
@@ -3,14 +3,16 @@
3
3
  class="p-3 actionable"
4
4
  :class="{'opacity-50 cursor-not-allowed': disabled}"
5
5
  >
6
- <slot />
6
+ <q-tooltip v-if="$slots.tooltip || tooltip">
7
+ <slot name="tooltip">{{ tooltip }}</slot>
8
+ </q-tooltip>
7
9
  <Transition
8
10
  mode="out-in"
9
11
  :duration="150"
10
12
  >
11
- <q-spinner
13
+ <RenderComponent
12
14
  v-if="loading"
13
- class="w-4 h-4 text-black"
15
+ :component="loadingComponent"
14
16
  />
15
17
  <MenuIcon
16
18
  v-else
@@ -49,6 +51,8 @@
49
51
  </template>
50
52
  <script setup>
51
53
  import { DotsVerticalIcon as MenuIcon } from '@heroicons/vue/outline';
54
+ import { QSpinner } from 'quasar';
55
+ import { RenderComponent } from '../index';
52
56
 
53
57
  const emit = defineEmits(['action', 'action-item']);
54
58
  defineProps({
@@ -56,11 +60,22 @@ defineProps({
56
60
  type: Array,
57
61
  required: true,
58
62
  validator(items) {
59
- return items.every((item) => item.label && (item.url || item.action || item.name));
63
+ return items.every((item) => item.url || item.action || item.name);
60
64
  }
61
65
  },
66
+ tooltip: {
67
+ type: String,
68
+ default: null
69
+ },
62
70
  disabled: Boolean,
63
- loading: Boolean
71
+ loading: Boolean,
72
+ loadingComponent: {
73
+ type: [Function, Object],
74
+ default: () => ({
75
+ is: QSpinner,
76
+ props: { class: 'w-4 h-4 text-black' }
77
+ })
78
+ }
64
79
  });
65
80
 
66
81
  function onAction(item) {
@@ -42,11 +42,22 @@ async function onConfirmAction(input) {
42
42
  }
43
43
 
44
44
  isSaving.value = true;
45
- const result = await props.action.onAction(props.targets, input);
45
+ let result;
46
+ try {
47
+ result = await props.action.onAction(props.targets, input);
48
+ } catch (e) {
49
+ console.error(e);
50
+ result = { error: `An error occurred while performing the action ${props.action.label}. Please try again later.` };
51
+ }
52
+
46
53
  isSaving.value = false;
47
54
 
48
- if (result.success) {
49
- FlashMessages.success(`The update was successful`);
55
+ // If there is no return value or the result marks it as successful, we show a success message
56
+ if (result === undefined || result?.success) {
57
+
58
+ if (result?.success) {
59
+ FlashMessages.success(`The update was successful`);
60
+ }
50
61
 
51
62
  if (props.action.onSuccess) {
52
63
  await props.action.onSuccess(result, props.targets, input);
@@ -58,7 +69,7 @@ async function onConfirmAction(input) {
58
69
  if (result.errors) {
59
70
  errors.push(...result.errors);
60
71
  } else if (result.error) {
61
- errors.push(result.error.message);
72
+ errors.push(typeof result.error === 'string' ? result.error : result.error.message);
62
73
  } else {
63
74
  errors.push('An unknown error occurred. Please try again later.');
64
75
  }
@@ -1 +1,2 @@
1
1
  export { default as ActionPerformerTool } from "./ActionPerformerTool.vue";
2
+ export { default as RenderComponent } from "./RenderComponent.vue";
package/tsconfig.json CHANGED
@@ -25,9 +25,6 @@
25
25
  "paths": {
26
26
  "@/*": [
27
27
  "./dev/src/*"
28
- ],
29
- "ui": [
30
- "./src/index.esm.js"
31
28
  ]
32
29
  }
33
30
  },