quasar-ui-danx 0.4.1 → 0.4.3

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.
Files changed (80) hide show
  1. package/dist/danx.es.js +7234 -6741
  2. package/dist/danx.es.js.map +1 -1
  3. package/dist/danx.umd.js +11 -5
  4. package/dist/danx.umd.js.map +1 -1
  5. package/dist/style.css +1 -1
  6. package/package.json +3 -1
  7. package/src/components/ActionTable/ActionTable.vue +31 -43
  8. package/src/components/ActionTable/Columns/ActionTableColumn.vue +19 -18
  9. package/src/components/ActionTable/Filters/CollapsableFiltersSidebar.vue +15 -14
  10. package/src/components/ActionTable/Filters/{FilterFieldList.vue → FilterList.vue} +26 -26
  11. package/src/components/ActionTable/Filters/FilterableField.vue +28 -31
  12. package/src/components/ActionTable/Filters/index.ts +2 -2
  13. package/src/components/ActionTable/Form/Fields/EditOnClickTextField.vue +71 -0
  14. package/src/components/ActionTable/Form/Fields/FieldLabel.vue +8 -13
  15. package/src/components/ActionTable/Form/Fields/FileUploadButton.vue +34 -33
  16. package/src/components/ActionTable/Form/Fields/MultiFileField.vue +48 -44
  17. package/src/components/ActionTable/Form/Fields/NumberField.vue +60 -59
  18. package/src/components/ActionTable/Form/Fields/SelectField.vue +124 -138
  19. package/src/components/ActionTable/Form/Fields/SelectWithChildrenField.vue +28 -33
  20. package/src/components/ActionTable/Form/Fields/SingleFileField.vue +15 -15
  21. package/src/components/ActionTable/Form/Fields/SliderNumberField.vue +45 -0
  22. package/src/components/ActionTable/Form/Fields/TextField.vue +47 -66
  23. package/src/components/ActionTable/Form/Fields/index.ts +2 -0
  24. package/src/components/ActionTable/Form/RenderedForm.vue +50 -13
  25. package/src/components/ActionTable/Form/Utilities/MaxLengthCounter.vue +17 -0
  26. package/src/components/ActionTable/Form/Utilities/index.ts +1 -0
  27. package/src/components/ActionTable/Form/index.ts +1 -0
  28. package/src/components/ActionTable/Layouts/ActionTableLayout.vue +22 -16
  29. package/src/components/ActionTable/Toolbars/ActionToolbar.vue +11 -11
  30. package/src/components/ActionTable/listControls.ts +104 -166
  31. package/src/components/ActionTable/listHelpers.ts +2 -3
  32. package/src/components/ActionTable/tableColumns.ts +53 -77
  33. package/src/components/AuditHistory/AuditHistoryItemValue.vue +26 -26
  34. package/src/components/PanelsDrawer/PanelsDrawer.vue +17 -4
  35. package/src/components/PanelsDrawer/PanelsDrawerPanels.vue +6 -11
  36. package/src/components/PanelsDrawer/PanelsDrawerTabs.vue +20 -20
  37. package/src/components/Utility/Dialogs/ConfirmActionDialog.vue +39 -0
  38. package/src/components/Utility/Dialogs/ConfirmDialog.vue +57 -117
  39. package/src/components/Utility/Dialogs/DialogLayout.vue +77 -0
  40. package/src/components/Utility/Dialogs/FullscreenCarouselDialog.vue +42 -36
  41. package/src/components/Utility/Dialogs/InfoDialog.vue +40 -80
  42. package/src/components/Utility/Dialogs/index.ts +1 -0
  43. package/src/components/Utility/Files/FilePreview.vue +76 -73
  44. package/src/components/Utility/Layouts/ContentDrawer.vue +24 -31
  45. package/src/components/Utility/Tools/ActionVnode.vue +3 -3
  46. package/src/components/Utility/Tools/RenderVnode.vue +20 -11
  47. package/src/components/Utility/Transitions/MaxHeightTransition.vue +26 -0
  48. package/src/components/Utility/Transitions/index.ts +1 -0
  49. package/src/config/index.ts +36 -31
  50. package/src/helpers/FileUpload.ts +295 -297
  51. package/src/helpers/FlashMessages.ts +80 -71
  52. package/src/helpers/actions.ts +102 -82
  53. package/src/helpers/download.ts +189 -189
  54. package/src/helpers/downloadPdf.ts +55 -52
  55. package/src/helpers/formats.ts +151 -109
  56. package/src/helpers/index.ts +2 -0
  57. package/src/helpers/multiFileUpload.ts +72 -58
  58. package/src/helpers/objectStore.ts +52 -0
  59. package/src/helpers/request.ts +70 -51
  60. package/src/helpers/routes.ts +29 -0
  61. package/src/helpers/storage.ts +7 -3
  62. package/src/helpers/utils.ts +47 -29
  63. package/src/styles/quasar-reset.scss +94 -68
  64. package/src/styles/themes/danx/dialogs.scss +47 -0
  65. package/src/styles/themes/danx/forms.scss +18 -0
  66. package/src/styles/themes/danx/index.scss +4 -0
  67. package/src/types/actions.d.ts +43 -0
  68. package/src/types/config.d.ts +15 -0
  69. package/src/types/controls.d.ts +99 -0
  70. package/src/types/dialogs.d.ts +32 -0
  71. package/src/types/fields.d.ts +20 -0
  72. package/src/types/files.d.ts +54 -0
  73. package/src/types/formats.d.ts +4 -0
  74. package/src/{components/ActionTable/Form/form.d.ts → types/forms.d.ts} +6 -0
  75. package/src/types/index.d.ts +12 -0
  76. package/src/types/requests.d.ts +13 -0
  77. package/src/types/shared.d.ts +15 -0
  78. package/src/types/tables.d.ts +27 -0
  79. package/types/index.d.ts +1 -1
  80. /package/src/components/ActionTable/Filters/{FilterFieldItem.vue → FilterItem.vue} +0 -0
@@ -31,55 +31,50 @@
31
31
  </div>
32
32
  </div>
33
33
  </template>
34
- <script setup>
34
+ <script setup lang="ts">
35
35
  import { ref, watch } from "vue";
36
36
  import { remove } from "../../../../helpers";
37
37
  import SelectField from "./SelectField";
38
38
 
39
+ export interface SelectWithChildrenFieldProps {
40
+ modelValue?: string[];
41
+ label?: string;
42
+ placeholder?: string;
43
+ options?: any[];
44
+ loading?: boolean;
45
+ }
46
+
39
47
  const emit = defineEmits(["update:model-value"]);
40
- const props = defineProps({
41
- modelValue: {
42
- type: Array,
43
- default: () => ([])
44
- },
45
- label: {
46
- type: String,
47
- default: "Selection"
48
- },
49
- placeholder: {
50
- type: String,
51
- default: "Select an option"
52
- },
53
- options: {
54
- type: Array,
55
- default: () => []
56
- },
57
- loading: Boolean
48
+ const props = withDefaults(defineProps<SelectWithChildrenFieldProps>(), {
49
+ modelValue: () => [],
50
+ label: "Selection",
51
+ placeholder: "Select an option",
52
+ options: () => []
58
53
  });
59
54
 
60
55
  function resolveSelectedOption() {
61
- if (props.modelValue?.length > 0) {
62
- return props.options.find((option) => option.children.find(child => props.modelValue.includes(child.id)));
63
- }
56
+ if (props.modelValue?.length > 0) {
57
+ return props.options.find((option) => option.children.find(child => props.modelValue.includes(child.id)));
58
+ }
64
59
 
65
- return null;
60
+ return null;
66
61
  }
67
62
  const selectedOption = ref(resolveSelectedOption());
68
63
  const selectedChildren = ref(props.modelValue || []);
69
64
  function onSelectChild(child) {
70
- if (selectedChildren.value.includes(child.id)) {
71
- selectedChildren.value = remove(selectedChildren.value, child.id);
72
- } else {
73
- selectedChildren.value.push(child.id);
74
- }
75
- emit("update:model-value", selectedChildren.value.length > 0 ? selectedChildren.value : undefined);
65
+ if (selectedChildren.value.includes(child.id)) {
66
+ selectedChildren.value = remove(selectedChildren.value, child.id);
67
+ } else {
68
+ selectedChildren.value.push(child.id);
69
+ }
70
+ emit("update:model-value", selectedChildren.value.length > 0 ? selectedChildren.value : undefined);
76
71
  }
77
72
  function onSelectOption() {
78
- selectedChildren.value = [];
79
- emit("update:model-value", undefined);
73
+ selectedChildren.value = [];
74
+ emit("update:model-value", undefined);
80
75
  }
81
76
  watch(() => props.modelValue, (value) => {
82
- selectedOption.value = resolveSelectedOption();
83
- selectedChildren.value = value || [];
77
+ selectedOption.value = resolveSelectedOption();
78
+ selectedChildren.value = value || [];
84
79
  });
85
80
  </script>
@@ -35,7 +35,7 @@
35
35
  v-if="!readonly || uploadedFile"
36
36
  class="w-32 cursor-pointer mt-2"
37
37
  :class="{'border border-dashed border-blue-600': !uploadedFile, 'mx-auto': !readonly}"
38
- :image="uploadedFile"
38
+ :file="uploadedFile"
39
39
  downloadable
40
40
  @click="!disable && $refs.file.click()"
41
41
  />
@@ -56,24 +56,24 @@ import FieldLabel from "./FieldLabel";
56
56
 
57
57
  const emit = defineEmits(["update:model-value"]);
58
58
  const props = defineProps({
59
- modelValue: {
60
- type: [Object, String],
61
- default: null
62
- },
63
- field: {
64
- type: Object,
65
- required: true
66
- },
67
- showName: Boolean,
68
- disable: Boolean,
69
- readonly: Boolean
59
+ modelValue: {
60
+ type: [Object, String],
61
+ default: null
62
+ },
63
+ field: {
64
+ type: Object,
65
+ required: true
66
+ },
67
+ showName: Boolean,
68
+ disable: Boolean,
69
+ readonly: Boolean
70
70
  });
71
71
  const { onComplete, onDrop, onFileSelected, uploadedFile, clearUploadedFile } = useSingleFileUpload();
72
72
  onComplete(() => emit("update:model-value", uploadedFile.value));
73
73
 
74
74
  onMounted(() => {
75
- if (props.modelValue) {
76
- uploadedFile.value = props.modelValue;
77
- }
75
+ if (props.modelValue) {
76
+ uploadedFile.value = props.modelValue;
77
+ }
78
78
  });
79
79
  </script>
@@ -0,0 +1,45 @@
1
+ <template>
2
+ <div class="dx-slider-number-field">
3
+ <FieldLabel
4
+ :label="label"
5
+ :field="field"
6
+ />
7
+ <QSlider
8
+ v-bind="sliderProps"
9
+ :min="min"
10
+ :max="max"
11
+ label
12
+ label-always
13
+ switch-label-side
14
+ :price-label="priceLabel"
15
+ />
16
+ </div>
17
+ </template>
18
+
19
+ <script setup lang="ts">
20
+ import { QSliderProps } from "quasar";
21
+ import { computed } from "vue";
22
+ import { FormField } from "../../../../types";
23
+ import FieldLabel from "./FieldLabel";
24
+
25
+ export interface SliderFieldProps extends QSliderProps {
26
+ modelValue?: number | null;
27
+ field?: FormField;
28
+ label?: string;
29
+ currency?: boolean;
30
+ percent?: boolean;
31
+ }
32
+
33
+ defineEmits(["update:model-value"]);
34
+ const props = defineProps<SliderFieldProps>();
35
+ const sliderProps = computed(() => ({ ...props, field: undefined, label: !!props.label }));
36
+ const priceLabel = computed(() => {
37
+ if (props.currency) {
38
+ return "$" + props.modelValue;
39
+ } else if (props.percent) {
40
+ return props.modelValue + "%";
41
+ } else {
42
+ return props.modelValue;
43
+ }
44
+ });
45
+ </script>
@@ -1,82 +1,63 @@
1
1
  <template>
2
2
  <div>
3
- <QInput
4
- v-if="!readonly"
5
- :data-dusk="'text-field-' + field?.id"
6
- :data-testid="'text-field-' + field?.id"
7
- :placeholder="field?.placeholder"
8
- outlined
9
- dense
10
- :disable="disabled"
11
- :label-slot="!noLabel"
12
- :input-class="inputClass"
13
- :class="parentClass"
14
- stack-label
15
- :type="type"
16
- :model-value="modelValue"
17
- :debounce="debounce"
18
- @keydown.enter="$emit('submit')"
19
- @update:model-value="$emit('update:model-value', $event)"
20
- >
21
- <template #label>
22
- <FieldLabel
23
- :field="field"
24
- :label="label"
25
- :show-name="showName"
26
- :class="labelClass"
27
- />
28
- </template>
29
- </QInput>
30
3
  <div v-if="readonly">
31
4
  <LabelValueBlock
32
- :label="label || field.label"
5
+ :label="label || field?.label || 'Text'"
33
6
  :value="modelValue"
34
7
  />
35
8
  </div>
9
+ <template v-else>
10
+ <QInput
11
+ :placeholder="field?.placeholder"
12
+ outlined
13
+ dense
14
+ :readonly="readonly"
15
+ :autogrow="autogrow"
16
+ :disable="disabled"
17
+ :label-slot="!noLabel"
18
+ :input-class="inputClass"
19
+ :class="parentClass"
20
+ stack-label
21
+ :type="type"
22
+ :model-value="modelValue"
23
+ :maxlength="allowOverMax ? undefined : field?.maxLength"
24
+ :debounce="debounce"
25
+ @keydown.enter="$emit('submit')"
26
+ @update:model-value="$emit('update:model-value', $event)"
27
+ >
28
+ <template #label>
29
+ <FieldLabel
30
+ :field="field"
31
+ :label="label"
32
+ :show-name="showName"
33
+ :class="labelClass"
34
+ />
35
+ </template>
36
+ </QInput>
37
+ <MaxLengthCounter
38
+ :length="modelValue?.length || 0"
39
+ :max-length="field?.maxLength"
40
+ />
41
+ </template>
36
42
  </div>
37
43
  </template>
38
44
 
39
- <script setup>
45
+ <script setup lang="ts">
46
+ import { TextFieldProps } from "../../../../types";
47
+ import MaxLengthCounter from "../Utilities/MaxLengthCounter";
40
48
  import FieldLabel from "./FieldLabel";
41
49
  import LabelValueBlock from "./LabelValueBlock";
42
50
 
43
51
  defineEmits(["update:model-value", "submit"]);
44
- defineProps({
45
- modelValue: {
46
- type: [String, Number],
47
- default: ""
48
- },
49
- field: {
50
- type: Object,
51
- default: null
52
- },
53
- type: {
54
- type: String,
55
- default: "text"
56
- },
57
- label: {
58
- type: String,
59
- default: null
60
- },
61
- labelClass: {
62
- type: String,
63
- default: ""
64
- },
65
- parentClass: {
66
- type: String,
67
- default: ""
68
- },
69
- inputClass: {
70
- type: String,
71
- default: ""
72
- },
73
- noLabel: Boolean,
74
- showName: Boolean,
75
- disabled: Boolean,
76
- readonly: Boolean,
77
- debounce: {
78
- type: [String, Number],
79
- default: 0
80
- }
52
+ withDefaults(defineProps<TextFieldProps>(), {
53
+ modelValue: "",
54
+ field: null,
55
+ type: "text",
56
+ label: "",
57
+ labelClass: "",
58
+ parentClass: "",
59
+ inputClass: "",
60
+ maxLength: null,
61
+ debounce: 0
81
62
  });
82
63
  </script>
@@ -5,6 +5,7 @@ export { default as DateRangeField } from "./DateRangeField.vue";
5
5
  export { default as DateTimeField } from "./DateTimeField.vue";
6
6
  export { default as DateTimePicker } from "./DateTimePicker.vue";
7
7
  export { default as EditableDiv } from "./EditableDiv.vue";
8
+ export { default as EditOnClickTextField } from "./EditOnClickTextField.vue";
8
9
  export { default as FieldLabel } from "./FieldLabel.vue";
9
10
  export { default as FileUploadButton } from "./FileUploadButton.vue";
10
11
  export { default as InlineDateTimeField } from "./InlineDateTimeField.vue";
@@ -20,5 +21,6 @@ export { default as SelectDrawer } from "./SelectDrawer.vue";
20
21
  export { default as SelectField } from "./SelectField.vue";
21
22
  export { default as SelectWithChildrenField } from "./SelectWithChildrenField.vue";
22
23
  export { default as SingleFileField } from "./SingleFileField.vue";
24
+ export { default as SliderNumberField } from "./SliderNumberField.vue";
23
25
  export { default as TextField } from "./TextField.vue";
24
26
  export { default as WysiwygField } from "./WysiwygField.vue";
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div class="rendered-form">
2
+ <div class="dx-rendered-form">
3
3
  <div
4
4
  v-if="form.variations > 1"
5
5
  class="mb-4"
@@ -65,16 +65,13 @@
65
65
  <div
66
66
  v-for="(field, index) in mappedFields"
67
67
  :key="field.id"
68
- :class="{ 'mt-4': index > 0 }"
68
+ :class="{ 'mt-4': index > 0, [fieldClass]: true }"
69
69
  >
70
70
  <RenderVnode
71
71
  v-if="field.vnode"
72
72
  :vnode="field.vnode"
73
- :readonly="readonly"
74
- :disable="disable"
75
- :show-name="showName"
76
- :no-label="noLabel"
77
- :model-value="getFieldValue(field.name)"
73
+ :field="field"
74
+ :props="getVnodeProps(field)"
78
75
  @update:model-value="onInput(field.name, $event)"
79
76
  />
80
77
  <Component
@@ -85,11 +82,31 @@
85
82
  :label="field.label || undefined"
86
83
  :no-label="noLabel"
87
84
  :show-name="showName"
85
+ :clearable="field.clearable || clearable"
88
86
  :disable="disable"
89
87
  :readonly="readonly"
90
88
  @update:model-value="onInput(field.name, $event)"
91
89
  />
92
90
  </div>
91
+ <div
92
+ v-if="savedAt"
93
+ :class="savingClass"
94
+ class="dx-saving-indicator flex items-center flex-nowrap"
95
+ >
96
+ <slot
97
+ v-if="saving"
98
+ name="saving"
99
+ >
100
+ Saving...
101
+ <QSpinnerPie class="ml-2" />
102
+ </slot>
103
+ <slot
104
+ v-else
105
+ name="saved"
106
+ >
107
+ Saved at {{ fDateTime(savedAt, { format: "M/d/yy h:mm:ssa" }) }}
108
+ </slot>
109
+ </div>
93
110
  <ConfirmDialog
94
111
  v-if="variationToEdit !== false"
95
112
  title="Change variation name"
@@ -117,8 +134,9 @@
117
134
  <script setup lang="ts">
118
135
  import { ExclamationCircleIcon as MissingIcon, PencilIcon as EditIcon } from "@heroicons/vue/solid";
119
136
  import { computed, ref } from "vue";
120
- import { FlashMessages, incrementName, replace } from "../../../helpers";
137
+ import { fDateTime, FlashMessages, incrementName, replace } from "../../../helpers";
121
138
  import { TrashIcon as RemoveIcon } from "../../../svg";
139
+ import { Form, FormFieldValue } from "../../../types";
122
140
  import { ConfirmDialog, RenderVnode } from "../../Utility";
123
141
  import {
124
142
  BooleanField,
@@ -131,9 +149,8 @@ import {
131
149
  TextField,
132
150
  WysiwygField
133
151
  } from "./Fields";
134
- import { Form, FormFieldValue } from "./form.d.ts";
135
152
 
136
- export interface Props {
153
+ export interface RenderedFormProps {
137
154
  values?: FormFieldValue[] | object;
138
155
  form: Form;
139
156
  noLabel?: boolean;
@@ -141,13 +158,20 @@ export interface Props {
141
158
  disable?: boolean;
142
159
  readonly?: boolean;
143
160
  saving?: boolean;
161
+ clearable?: boolean;
144
162
  emptyValue?: string | number | boolean;
145
163
  canModifyVariations?: boolean;
164
+ fieldClass?: string;
165
+ savingClass?: string;
166
+ savedAt?: string;
146
167
  }
147
168
 
148
- const props = withDefaults(defineProps<Props>(), {
169
+ const props = withDefaults(defineProps<RenderedFormProps>(), {
149
170
  values: null,
150
- emptyValue: undefined
171
+ emptyValue: undefined,
172
+ fieldClass: "",
173
+ savingClass: "text-sm text-slate-500 justify-end mt-4",
174
+ savedAt: null
151
175
  });
152
176
 
153
177
  const emit = defineEmits(["update:values"]);
@@ -176,6 +200,19 @@ const fieldResponses = computed(() => {
176
200
  if (Array.isArray(props.values)) return props.values;
177
201
  return Object.entries(props.values).map(([name, value]) => ({ name, value, variation: "" }));
178
202
  });
203
+
204
+ function getVnodeProps(field) {
205
+ return {
206
+ modelValue: getFieldValue(field.name),
207
+ label: field.label,
208
+ clearable: field.clearable || props.clearable,
209
+ readonly: props.readonly,
210
+ disable: props.disable,
211
+ showName: props.showName,
212
+ noLabel: props.noLabel
213
+ };
214
+ }
215
+
179
216
  const variationNames = computed(() => {
180
217
  const names = [...new Set(fieldResponses.value.map(v => v.variation))].sort();
181
218
  // Always guarantee that we show the default variation
@@ -187,7 +224,7 @@ const variationNames = computed(() => {
187
224
 
188
225
  const currentVariation = ref(variationNames.value[0] || "");
189
226
  const newVariationName = ref("");
190
- const variationToEdit = ref(false);
227
+ const variationToEdit = ref<boolean | string>(false);
191
228
  const variationToDelete = ref("");
192
229
  const canAddVariation = computed(() => props.canModifyVariations && !props.readonly && !props.disable && variationNames.value.length < props.form.variations);
193
230
 
@@ -0,0 +1,17 @@
1
+ <template>
2
+ <div
3
+ v-if="maxLength"
4
+ class="danx-input-chars mt-1"
5
+ :class="{'danx-input-chars--error': length > maxLength}"
6
+ >
7
+ {{ fNumber(length) }} / {{ fNumber(maxLength) }} characters
8
+ </div>
9
+ </template>
10
+ <script setup lang="ts">
11
+ import { fNumber } from "../../../../helpers";
12
+
13
+ defineProps<{
14
+ length: number;
15
+ maxLength?: number;
16
+ }>();
17
+ </script>
@@ -0,0 +1 @@
1
+ export { default as MaxLengthCounter } from "./MaxLengthCounter.vue";
@@ -1,2 +1,3 @@
1
1
  export * from "./Fields";
2
+ export * from "./Utilities";
2
3
  export { default as RenderedForm } from "./RenderedForm.vue";
@@ -3,21 +3,27 @@
3
3
  <slot name="top" />
4
4
  <slot name="toolbar">
5
5
  <ActionToolbar
6
+ :title="title"
6
7
  :refresh-button="refreshButton"
7
8
  :actions="actions?.filter(a => a.batch)"
8
9
  :action-target="controller.selectedRows.value"
9
10
  :exporter="controller.exportList"
10
11
  @refresh="controller.refreshAll"
11
- />
12
+ >
13
+ <template #default>
14
+ <slot name="action-toolbar" />
15
+ </template>
16
+ </ActionToolbar>
12
17
  </slot>
13
18
  <div class="flex flex-nowrap flex-grow overflow-hidden w-full">
14
- <slot name="filter-fields">
19
+ <slot name="filters">
15
20
  <CollapsableFiltersSidebar
16
21
  v-if="activeFilter"
17
22
  :name="controller.name"
18
23
  :show-filters="showFilters"
19
24
  :filters="filters"
20
25
  :active-filter="activeFilter"
26
+ class="dx-action-table-filters"
21
27
  @update:active-filter="controller.setActiveFilter"
22
28
  />
23
29
  </slot>
@@ -43,6 +49,7 @@
43
49
  v-if="activeItem && panels"
44
50
  :title="panelTitle"
45
51
  :model-value="activePanel"
52
+ :active-item="activeItem"
46
53
  :panels="panels"
47
54
  @update:model-value="panel => controller.activatePanel(activeItem, panel)"
48
55
  @close="controller.setActiveItem(null)"
@@ -60,26 +67,25 @@
60
67
  </template>
61
68
  <script setup lang="ts">
62
69
  import { computed } from "vue";
63
- import { ActionOptions } from "../../../helpers";
70
+ import { ActionController, ActionOptions, ActionPanel, FilterGroup, TableColumn } from "../../../types";
64
71
  import { PanelsDrawer } from "../../PanelsDrawer";
65
72
  import { PreviousNextControls } from "../../Utility";
66
73
  import ActionTable from "../ActionTable";
67
74
  import { CollapsableFiltersSidebar } from "../Filters";
68
- import { ActionController, ActionPanel, FilterField } from "../listControls";
69
- import { TableColumn } from "../tableColumns";
70
75
  import { ActionToolbar } from "../Toolbars";
71
76
 
72
77
  const props = defineProps<{
73
- refreshButton: boolean,
74
- showFilters: boolean,
75
- controller: ActionController,
76
- columns: TableColumn[],
77
- filters?: FilterField[],
78
- panels?: ActionPanel[],
79
- actions?: ActionOptions[],
80
- exporter?: () => Promise<void>,
81
- titleField?: string,
82
- tableClass?: string
78
+ title?: string;
79
+ refreshButton: boolean;
80
+ showFilters: boolean;
81
+ controller: ActionController;
82
+ columns: TableColumn[];
83
+ filters?: FilterGroup[];
84
+ panels?: ActionPanel[];
85
+ actions?: ActionOptions[];
86
+ exporter?: () => Promise<void>;
87
+ panelTitleField?: string;
88
+ tableClass?: string;
83
89
  }>();
84
90
 
85
91
  const activeFilter = computed(() => props.controller.activeFilter.value);
@@ -87,7 +93,7 @@ const activeItem = computed(() => props.controller.activeItem.value);
87
93
  const activePanel = computed(() => props.controller.activePanel.value || "");
88
94
  const panelTitle = computed(() => {
89
95
  if (activeItem.value) {
90
- return activeItem.value[props.titleField || "title"] || activeItem.value.label || activeItem.value.name;
96
+ return activeItem.value[props.panelTitleField || "title"] || activeItem.value.label || activeItem.value.name || (props.title + " " + activeItem.value.id);
91
97
  }
92
98
  return null;
93
99
  });
@@ -1,10 +1,10 @@
1
1
  <template>
2
- <div class="flex items-center">
2
+ <div class="dx-action-toolbar flex items-center">
3
3
  <div class="flex-grow px-6">
4
4
  <slot name="title">
5
- <h2 v-if="title">
5
+ <h4 v-if="title">
6
6
  {{ title }}
7
- </h2>
7
+ </h4>
8
8
  </slot>
9
9
  </div>
10
10
  <div class="py-3 px-6 flex items-center flex-nowrap">
@@ -20,7 +20,7 @@
20
20
  class="ml-4"
21
21
  />
22
22
  <ActionMenu
23
- v-if="actions.length > 0"
23
+ v-if="actions && actions.length > 0"
24
24
  class="ml-4 dx-batch-actions"
25
25
  :target="actionTarget"
26
26
  :actions="actions"
@@ -30,17 +30,17 @@
30
30
  </div>
31
31
  </template>
32
32
  <script setup lang="ts">
33
- import { ActionOptions, ActionTargetItem } from "../../../helpers";
33
+ import { ActionOptions, ActionTargetItem, AnyObject } from "../../../types";
34
34
  import { ExportButton, RefreshButton } from "../../Utility";
35
35
  import ActionMenu from "../ActionMenu";
36
36
 
37
37
  defineEmits(["refresh"]);
38
38
  defineProps<{
39
- title?: string,
40
- actions: ActionOptions[],
41
- actionTarget?: ActionTargetItem[],
42
- refreshButton?: boolean,
43
- loading?: boolean,
44
- exporter?: () => void
39
+ title?: string,
40
+ actions?: ActionOptions[],
41
+ actionTarget?: ActionTargetItem[],
42
+ refreshButton?: boolean,
43
+ loading?: boolean,
44
+ exporter?: (filter?: AnyObject) => void | Promise<void>
45
45
  }>();
46
46
  </script>