quasar-ui-danx 0.4.2 → 0.4.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. package/dist/danx.es.js +7127 -6615
  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 +28 -41
  8. package/src/components/ActionTable/Columns/ActionTableColumn.vue +19 -18
  9. package/src/components/ActionTable/Filters/CollapsableFiltersSidebar.vue +6 -6
  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/MultiFileField.vue +48 -44
  16. package/src/components/ActionTable/Form/Fields/SelectField.vue +24 -38
  17. package/src/components/ActionTable/Form/Fields/SelectWithChildrenField.vue +28 -33
  18. package/src/components/ActionTable/Form/Fields/SingleFileField.vue +15 -15
  19. package/src/components/ActionTable/Form/Fields/SliderNumberField.vue +45 -0
  20. package/src/components/ActionTable/Form/Fields/TextField.vue +47 -66
  21. package/src/components/ActionTable/Form/Fields/index.ts +2 -0
  22. package/src/components/ActionTable/Form/RenderedForm.vue +50 -9
  23. package/src/components/ActionTable/Form/Utilities/MaxLengthCounter.vue +17 -0
  24. package/src/components/ActionTable/Form/Utilities/index.ts +1 -0
  25. package/src/components/ActionTable/Form/index.ts +1 -0
  26. package/src/components/ActionTable/Layouts/ActionTableLayout.vue +16 -15
  27. package/src/components/ActionTable/Toolbars/ActionToolbar.vue +6 -6
  28. package/src/components/ActionTable/listControls.ts +106 -166
  29. package/src/components/ActionTable/listHelpers.ts +2 -3
  30. package/src/components/ActionTable/tableColumns.ts +3 -27
  31. package/src/components/AuditHistory/AuditHistoryItemValue.vue +26 -26
  32. package/src/components/PanelsDrawer/PanelsDrawer.vue +17 -4
  33. package/src/components/PanelsDrawer/PanelsDrawerPanels.vue +6 -11
  34. package/src/components/PanelsDrawer/PanelsDrawerTabs.vue +20 -20
  35. package/src/components/Utility/Dialogs/ConfirmActionDialog.vue +39 -0
  36. package/src/components/Utility/Dialogs/ConfirmDialog.vue +10 -24
  37. package/src/components/Utility/Dialogs/DialogLayout.vue +10 -28
  38. package/src/components/Utility/Dialogs/FullscreenCarouselDialog.vue +42 -36
  39. package/src/components/Utility/Dialogs/index.ts +1 -0
  40. package/src/components/Utility/Files/FilePreview.vue +76 -73
  41. package/src/components/Utility/Layouts/ContentDrawer.vue +24 -31
  42. package/src/components/Utility/Tools/ActionVnode.vue +3 -3
  43. package/src/components/Utility/Tools/RenderVnode.vue +1 -1
  44. package/src/components/Utility/Transitions/MaxHeightTransition.vue +26 -0
  45. package/src/components/Utility/Transitions/index.ts +1 -0
  46. package/src/config/index.ts +36 -31
  47. package/src/helpers/FileUpload.ts +295 -297
  48. package/src/helpers/FlashMessages.ts +80 -71
  49. package/src/helpers/actions.ts +102 -82
  50. package/src/helpers/download.ts +189 -189
  51. package/src/helpers/downloadPdf.ts +55 -52
  52. package/src/helpers/formats.ts +151 -109
  53. package/src/helpers/index.ts +2 -0
  54. package/src/helpers/multiFileUpload.ts +72 -58
  55. package/src/helpers/objectStore.ts +52 -0
  56. package/src/helpers/request.ts +70 -51
  57. package/src/helpers/routes.ts +29 -0
  58. package/src/helpers/storage.ts +7 -3
  59. package/src/helpers/utils.ts +47 -29
  60. package/src/styles/quasar-reset.scss +16 -1
  61. package/src/styles/themes/danx/dialogs.scss +4 -0
  62. package/src/types/actions.d.ts +43 -0
  63. package/src/types/config.d.ts +15 -0
  64. package/src/types/controls.d.ts +99 -0
  65. package/src/types/dialogs.d.ts +32 -0
  66. package/src/types/fields.d.ts +20 -0
  67. package/src/types/files.d.ts +54 -0
  68. package/src/types/formats.d.ts +4 -0
  69. package/src/{components/ActionTable/Form/form.d.ts → types/forms.d.ts} +6 -0
  70. package/src/types/index.d.ts +12 -0
  71. package/src/types/requests.d.ts +13 -0
  72. package/src/types/shared.d.ts +15 -0
  73. package/src/types/tables.d.ts +27 -0
  74. package/types/index.d.ts +1 -1
  75. /package/src/components/ActionTable/Filters/{FilterFieldItem.vue → FilterItem.vue} +0 -0
@@ -64,47 +64,33 @@
64
64
  </QSelect>
65
65
  </div>
66
66
  </template>
67
- <script setup>
67
+ <script setup lang="ts">
68
68
  import { ChevronDownIcon as DropDownIcon } from "@heroicons/vue/outline";
69
- import { QSelect } from "quasar";
69
+ import { QSelect, QSelectProps } from "quasar";
70
70
  import { computed, isRef, nextTick, ref } from "vue";
71
71
 
72
+ export interface Props extends QSelectProps {
73
+ modelValue?: any;
74
+ placeholder?: string;
75
+ selectionLabel?: string | ((option) => string);
76
+ chipLimit?: number;
77
+ inputClass?: string;
78
+ selectionClass?: string;
79
+ options?: unknown[];
80
+ filterable?: boolean;
81
+ filterFn?: (val: string) => void;
82
+ }
83
+
72
84
  const emit = defineEmits(["update:model-value", "search", "update"]);
73
- const props = defineProps({
74
- ...QSelect.props,
75
- modelValue: {
76
- type: [Array, String, Number, Object],
77
- default: undefined
78
- },
79
- placeholder: {
80
- type: String,
81
- default: ""
82
- },
83
- selectionLabel: {
84
- type: String,
85
- default: null
86
- },
87
- chipLimit: {
88
- type: Number,
89
- default: 3
90
- },
91
- inputClass: {
92
- type: String,
93
- default: ""
94
- },
95
- selectionClass: {
96
- type: String,
97
- default: ""
98
- },
99
- options: {
100
- type: Array,
101
- default: () => []
102
- },
103
- filterable: Boolean,
104
- filterFn: {
105
- type: Function,
106
- default: null
107
- }
85
+ const props = withDefaults(defineProps<Props>(), {
86
+ modelValue: undefined,
87
+ placeholder: "",
88
+ selectionLabel: null,
89
+ chipLimit: 3,
90
+ inputClass: "",
91
+ selectionClass: "",
92
+ options: () => [],
93
+ filterFn: null
108
94
  });
109
95
 
110
96
  const selectField = ref(null);
@@ -136,7 +122,7 @@ const computedOptions = computed(() => {
136
122
 
137
123
  const filteredOptions = computed(() => {
138
124
  if (filter.value && !props.filterFn) {
139
- return computedOptions.value.filter(o => o.label.toLocaleLowerCase().indexOf(filter.value.toLowerCase()) > -1);
125
+ return computedOptions.value.filter(o => o.label.toLocaleLowerCase().indexOf(filter.value?.toLowerCase()) > -1);
140
126
  } else {
141
127
  return computedOptions.value;
142
128
  }
@@ -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,12 +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
- :props="{field, modelValue: getFieldValue(field.name), readonly, disable, showName, noLabel}"
73
+ :field="field"
74
+ :props="getVnodeProps(field)"
74
75
  @update:model-value="onInput(field.name, $event)"
75
76
  />
76
77
  <Component
@@ -81,11 +82,31 @@
81
82
  :label="field.label || undefined"
82
83
  :no-label="noLabel"
83
84
  :show-name="showName"
85
+ :clearable="field.clearable || clearable"
84
86
  :disable="disable"
85
87
  :readonly="readonly"
86
88
  @update:model-value="onInput(field.name, $event)"
87
89
  />
88
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>
89
110
  <ConfirmDialog
90
111
  v-if="variationToEdit !== false"
91
112
  title="Change variation name"
@@ -113,8 +134,9 @@
113
134
  <script setup lang="ts">
114
135
  import { ExclamationCircleIcon as MissingIcon, PencilIcon as EditIcon } from "@heroicons/vue/solid";
115
136
  import { computed, ref } from "vue";
116
- import { FlashMessages, incrementName, replace } from "../../../helpers";
137
+ import { fDateTime, FlashMessages, incrementName, replace } from "../../../helpers";
117
138
  import { TrashIcon as RemoveIcon } from "../../../svg";
139
+ import { Form, FormFieldValue } from "../../../types";
118
140
  import { ConfirmDialog, RenderVnode } from "../../Utility";
119
141
  import {
120
142
  BooleanField,
@@ -127,9 +149,8 @@ import {
127
149
  TextField,
128
150
  WysiwygField
129
151
  } from "./Fields";
130
- import { Form, FormFieldValue } from "./form.d.ts";
131
152
 
132
- export interface Props {
153
+ export interface RenderedFormProps {
133
154
  values?: FormFieldValue[] | object;
134
155
  form: Form;
135
156
  noLabel?: boolean;
@@ -137,13 +158,20 @@ export interface Props {
137
158
  disable?: boolean;
138
159
  readonly?: boolean;
139
160
  saving?: boolean;
161
+ clearable?: boolean;
140
162
  emptyValue?: string | number | boolean;
141
163
  canModifyVariations?: boolean;
164
+ fieldClass?: string;
165
+ savingClass?: string;
166
+ savedAt?: string;
142
167
  }
143
168
 
144
- const props = withDefaults(defineProps<Props>(), {
169
+ const props = withDefaults(defineProps<RenderedFormProps>(), {
145
170
  values: null,
146
- emptyValue: undefined
171
+ emptyValue: undefined,
172
+ fieldClass: "",
173
+ savingClass: "text-sm text-slate-500 justify-end mt-4",
174
+ savedAt: null
147
175
  });
148
176
 
149
177
  const emit = defineEmits(["update:values"]);
@@ -172,6 +200,19 @@ const fieldResponses = computed(() => {
172
200
  if (Array.isArray(props.values)) return props.values;
173
201
  return Object.entries(props.values).map(([name, value]) => ({ name, value, variation: "" }));
174
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
+
175
216
  const variationNames = computed(() => {
176
217
  const names = [...new Set(fieldResponses.value.map(v => v.variation))].sort();
177
218
  // Always guarantee that we show the default variation
@@ -183,7 +224,7 @@ const variationNames = computed(() => {
183
224
 
184
225
  const currentVariation = ref(variationNames.value[0] || "");
185
226
  const newVariationName = ref("");
186
- const variationToEdit = ref(false);
227
+ const variationToEdit = ref<boolean | string>(false);
187
228
  const variationToDelete = ref("");
188
229
  const canAddVariation = computed(() => props.canModifyVariations && !props.readonly && !props.disable && variationNames.value.length < props.form.variations);
189
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,6 +3,7 @@
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"
@@ -15,7 +16,7 @@
15
16
  </ActionToolbar>
16
17
  </slot>
17
18
  <div class="flex flex-nowrap flex-grow overflow-hidden w-full">
18
- <slot name="filter-fields">
19
+ <slot name="filters">
19
20
  <CollapsableFiltersSidebar
20
21
  v-if="activeFilter"
21
22
  :name="controller.name"
@@ -48,6 +49,7 @@
48
49
  v-if="activeItem && panels"
49
50
  :title="panelTitle"
50
51
  :model-value="activePanel"
52
+ :active-item="activeItem"
51
53
  :panels="panels"
52
54
  @update:model-value="panel => controller.activatePanel(activeItem, panel)"
53
55
  @close="controller.setActiveItem(null)"
@@ -65,26 +67,25 @@
65
67
  </template>
66
68
  <script setup lang="ts">
67
69
  import { computed } from "vue";
68
- import { ActionOptions } from "../../../helpers";
70
+ import { ActionController, ActionOptions, ActionPanel, FilterGroup, TableColumn } from "../../../types";
69
71
  import { PanelsDrawer } from "../../PanelsDrawer";
70
72
  import { PreviousNextControls } from "../../Utility";
71
73
  import ActionTable from "../ActionTable";
72
74
  import { CollapsableFiltersSidebar } from "../Filters";
73
- import { ActionController, ActionPanel, FilterGroup } from "../listControls";
74
- import { TableColumn } from "../tableColumns";
75
75
  import { ActionToolbar } from "../Toolbars";
76
76
 
77
77
  const props = defineProps<{
78
- refreshButton: boolean,
79
- showFilters: boolean,
80
- controller: ActionController,
81
- columns: TableColumn[],
82
- filters?: FilterGroup[],
83
- panels?: ActionPanel[],
84
- actions?: ActionOptions[],
85
- exporter?: () => Promise<void>,
86
- titleField?: string,
87
- 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;
88
89
  }>();
89
90
 
90
91
  const activeFilter = computed(() => props.controller.activeFilter.value);
@@ -92,7 +93,7 @@ const activeItem = computed(() => props.controller.activeItem.value);
92
93
  const activePanel = computed(() => props.controller.activePanel.value || "");
93
94
  const panelTitle = computed(() => {
94
95
  if (activeItem.value) {
95
- 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);
96
97
  }
97
98
  return null;
98
99
  });
@@ -2,9 +2,9 @@
2
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
39
  title?: string,
40
- actions: ActionOptions[],
40
+ actions?: ActionOptions[],
41
41
  actionTarget?: ActionTargetItem[],
42
42
  refreshButton?: boolean,
43
43
  loading?: boolean,
44
- exporter?: () => void
44
+ exporter?: (filter?: AnyObject) => void | Promise<void>
45
45
  }>();
46
46
  </script>