quasar-ui-danx 0.3.22 → 0.4.2
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/.eslintrc.cjs +32 -30
- package/danx-local.sh +1 -1
- package/dist/danx.es.js +7413 -7461
- package/dist/danx.es.js.map +1 -1
- package/dist/danx.umd.js +5 -5
- package/dist/danx.umd.js.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/components/ActionTable/ActionMenu.vue +1 -1
- package/src/components/ActionTable/ActionTable.vue +67 -47
- package/src/components/ActionTable/{ActionTableColumn.vue → Columns/ActionTableColumn.vue} +4 -3
- package/src/components/ActionTable/{ActionTableHeaderColumn.vue → Columns/ActionTableHeaderColumn.vue} +2 -2
- package/src/components/ActionTable/Columns/index.ts +2 -0
- package/src/components/ActionTable/Filters/CollapsableFiltersSidebar.vue +23 -21
- package/src/components/ActionTable/Form/Fields/DateRangeField.vue +3 -5
- package/src/components/ActionTable/Form/Fields/NumberField.vue +60 -59
- package/src/components/ActionTable/Form/Fields/SelectField.vue +135 -135
- package/src/components/ActionTable/Form/Fields/TextField.vue +36 -36
- package/src/components/ActionTable/Form/RenderedForm.vue +133 -112
- package/src/components/ActionTable/Form/form.d.ts +31 -0
- package/src/components/ActionTable/Layouts/ActionTableLayout.vue +93 -4
- package/src/components/ActionTable/TableSummaryRow.vue +4 -4
- package/src/components/ActionTable/Toolbars/ActionToolbar.vue +46 -0
- package/src/components/ActionTable/Toolbars/index.ts +1 -0
- package/src/components/ActionTable/index.ts +1 -2
- package/src/components/ActionTable/listControls.ts +512 -385
- package/src/components/ActionTable/listHelpers.ts +46 -44
- package/src/components/ActionTable/tableColumns.ts +66 -66
- package/src/components/PanelsDrawer/PanelsDrawer.vue +37 -26
- package/src/components/PanelsDrawer/PanelsDrawerPanels.vue +1 -1
- package/src/components/PanelsDrawer/PanelsDrawerTabs.vue +1 -6
- package/src/components/Utility/Buttons/ExportButton.vue +1 -1
- package/src/components/Utility/Buttons/RefreshButton.vue +5 -5
- package/src/components/Utility/Controls/PreviousNextControls.vue +4 -4
- package/src/components/Utility/Dialogs/ConfirmDialog.vue +69 -115
- package/src/components/Utility/Dialogs/DialogLayout.vue +95 -0
- package/src/components/Utility/Dialogs/InfoDialog.vue +40 -80
- package/src/components/Utility/Layouts/CollapsableSidebar.vue +2 -8
- package/src/components/Utility/Popovers/PopoverMenu.vue +3 -3
- package/src/components/Utility/Tools/RenderVnode.vue +21 -12
- package/src/helpers/actions.ts +198 -188
- package/src/styles/general.scss +12 -11
- package/src/styles/quasar-reset.scss +81 -22
- package/src/styles/themes/danx/action-table.scss +19 -0
- package/src/styles/themes/danx/buttons.scss +13 -0
- package/src/styles/themes/danx/dialogs.scss +43 -0
- package/src/styles/themes/danx/forms.scss +23 -0
- package/src/styles/themes/danx/index.scss +7 -0
- package/src/styles/themes/danx/panels.scss +19 -0
- package/src/styles/themes/danx/sidebar.scss +3 -0
- package/src/styles/themes/danx/toolbar.scss +3 -0
- package/types/index.d.ts +1 -0
- package/src/styles/actions.scss +0 -10
package/package.json
CHANGED
@@ -1,21 +1,24 @@
|
|
1
1
|
<template>
|
2
|
-
<div
|
2
|
+
<div
|
3
|
+
class="dx-action-table overflow-hidden"
|
4
|
+
:class="{'dx-no-data': !hasData}"
|
5
|
+
>
|
3
6
|
<ActionVnode />
|
4
7
|
<QTable
|
5
8
|
ref="actionTable"
|
6
9
|
:selected="selectedRows"
|
7
|
-
:pagination="
|
8
|
-
:columns="
|
9
|
-
:loading="
|
10
|
+
:pagination="pagination"
|
11
|
+
:columns="tableColumns"
|
12
|
+
:loading="loadingList"
|
10
13
|
:rows="pagedItems?.data || []"
|
11
14
|
:binary-state-sort="false"
|
12
15
|
selection="multiple"
|
13
16
|
:rows-per-page-options="rowsPerPageOptions"
|
14
17
|
class="sticky-column sticky-header w-full h-full !border-0"
|
15
|
-
color="
|
18
|
+
:color="color"
|
16
19
|
@update:selected="$emit('update:selected-rows', $event)"
|
17
20
|
@update:pagination="() => {}"
|
18
|
-
@request="$emit('update:
|
21
|
+
@request="(e) => $emit('update:pagination', {...e.pagination, __sort: mapSortBy(e.pagination, tableColumns)})"
|
19
22
|
>
|
20
23
|
<template #no-data>
|
21
24
|
<slot name="empty">
|
@@ -24,12 +27,13 @@
|
|
24
27
|
</template>
|
25
28
|
<template #top-row>
|
26
29
|
<TableSummaryRow
|
30
|
+
v-if="hasData"
|
27
31
|
:label="label"
|
28
32
|
:item-count="summary?.count || 0"
|
29
33
|
:selected-count="selectedRows.length"
|
30
|
-
:loading="
|
34
|
+
:loading="loadingSummary"
|
31
35
|
:summary="summary"
|
32
|
-
:columns="
|
36
|
+
:columns="tableColumns"
|
33
37
|
@clear="$emit('update:selected-rows', [])"
|
34
38
|
/>
|
35
39
|
</template>
|
@@ -60,58 +64,74 @@
|
|
60
64
|
|
61
65
|
<script setup>
|
62
66
|
import { QTable } from "quasar";
|
63
|
-
import { ref } from "vue";
|
67
|
+
import { computed, ref } from "vue";
|
64
68
|
import { getItem, setItem } from "../../helpers";
|
65
69
|
import { ActionVnode } from "../Utility";
|
66
|
-
import ActionTableColumn from "./
|
67
|
-
import ActionTableHeaderColumn from "./ActionTableHeaderColumn";
|
70
|
+
import { ActionTableColumn, ActionTableHeaderColumn } from "./Columns";
|
68
71
|
import EmptyTableState from "./EmptyTableState.vue";
|
69
72
|
import { mapSortBy, registerStickyScrolling } from "./listHelpers";
|
70
73
|
import TableSummaryRow from "./TableSummaryRow.vue";
|
71
74
|
|
72
|
-
defineEmits(["update:
|
75
|
+
defineEmits(["update:selected-rows", "update:pagination"]);
|
73
76
|
const props = defineProps({
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
77
|
+
name: {
|
78
|
+
type: String,
|
79
|
+
required: true
|
80
|
+
},
|
81
|
+
label: {
|
82
|
+
type: String,
|
83
|
+
required: true
|
84
|
+
},
|
85
|
+
color: {
|
86
|
+
type: String,
|
87
|
+
default: "blue-600"
|
88
|
+
},
|
89
|
+
selectedRows: {
|
90
|
+
type: Array,
|
91
|
+
required: true
|
92
|
+
},
|
93
|
+
pagination: {
|
94
|
+
type: Object,
|
95
|
+
required: true
|
96
|
+
},
|
97
|
+
loadingList: Boolean,
|
98
|
+
loadingSummary: Boolean,
|
99
|
+
pagedItems: {
|
100
|
+
type: Object,
|
101
|
+
default: null
|
102
|
+
},
|
103
|
+
summary: {
|
104
|
+
type: Object,
|
105
|
+
default: null
|
106
|
+
},
|
107
|
+
columns: {
|
108
|
+
type: Array,
|
109
|
+
required: true
|
110
|
+
},
|
111
|
+
rowsPerPageOptions: {
|
112
|
+
type: Array,
|
113
|
+
default: () => [10, 25, 50, 100]
|
114
|
+
}
|
108
115
|
});
|
109
116
|
const actionTable = ref(null);
|
110
117
|
registerStickyScrolling(actionTable);
|
111
118
|
|
119
|
+
const tableColumns = computed(() => props.columns.map((column) => ({ ...column, field: column.field || column.name })));
|
120
|
+
const hasData = computed(() => props.pagedItems?.data?.length);
|
112
121
|
const COLUMN_SETTINGS_KEY = `column-settings-${props.name}`;
|
113
122
|
const columnSettings = ref(getItem(COLUMN_SETTINGS_KEY) || {});
|
114
123
|
function onUpdateColumnSettings() {
|
115
|
-
|
124
|
+
setItem(COLUMN_SETTINGS_KEY, columnSettings.value);
|
116
125
|
}
|
117
126
|
</script>
|
127
|
+
|
128
|
+
<style scoped lang="scss">
|
129
|
+
.dx-action-table {
|
130
|
+
&.dx-no-data {
|
131
|
+
:deep(.q-table__middle) {
|
132
|
+
flex-grow: 0;
|
133
|
+
flex-shrink: 1;
|
134
|
+
}
|
135
|
+
}
|
136
|
+
}
|
137
|
+
</style>
|
@@ -44,6 +44,7 @@
|
|
44
44
|
class="flex flex-shrink-0 pl-2"
|
45
45
|
>
|
46
46
|
<ActionMenu
|
47
|
+
class="dx-column-action-menu"
|
47
48
|
:actions="column.actionMenu"
|
48
49
|
:target="row"
|
49
50
|
:loading="isSaving"
|
@@ -56,9 +57,9 @@
|
|
56
57
|
<script setup>
|
57
58
|
import { QTd } from "quasar";
|
58
59
|
import { computed } from "vue";
|
59
|
-
import { RenderVnode } from "
|
60
|
-
import ActionMenu from "
|
61
|
-
import { TitleColumnFormat } from "./
|
60
|
+
import { RenderVnode } from "../../Utility";
|
61
|
+
import ActionMenu from "../ActionMenu";
|
62
|
+
import { TitleColumnFormat } from "./";
|
62
63
|
|
63
64
|
const props = defineProps({
|
64
65
|
rowProps: {
|
@@ -20,8 +20,8 @@
|
|
20
20
|
<script setup>
|
21
21
|
import { QTh } from "quasar";
|
22
22
|
import { computed } from "vue";
|
23
|
-
import { DragHandleIcon as RowResizeIcon } from "
|
24
|
-
import { HandleDraggable } from "
|
23
|
+
import { DragHandleIcon as RowResizeIcon } from "../../../svg";
|
24
|
+
import { HandleDraggable } from "../../DragAndDrop";
|
25
25
|
|
26
26
|
const emit = defineEmits(["update:model-value"]);
|
27
27
|
const props = defineProps({
|
@@ -1,3 +1,5 @@
|
|
1
|
+
export { default as ActionTableColumn } from "./ActionTableColumn.vue";
|
2
|
+
export { default as ActionTableHeaderColumn } from "./ActionTableHeaderColumn.vue";
|
1
3
|
export { default as ColumnListItem } from "./ColumnListItem.vue";
|
2
4
|
export { default as ColumnSettingsDialog } from "./ColumnSettingsDialog.vue";
|
3
5
|
export { default as TitleColumnFormat } from "./TitleColumnFormat.vue";
|
@@ -1,37 +1,39 @@
|
|
1
1
|
<template>
|
2
2
|
<CollapsableSidebar
|
3
|
+
class="dx-collapsable-filters-sidebar"
|
3
4
|
:collapse="!showFilters"
|
4
5
|
disabled
|
5
|
-
min-width="
|
6
|
-
max-width="
|
6
|
+
:min-width="minWidth"
|
7
|
+
:max-width="maxWidth"
|
7
8
|
:name="name"
|
8
9
|
@update:collapse="$emit('update:show-filters', !$event)"
|
9
10
|
>
|
10
11
|
<FilterFieldList
|
11
|
-
:filter="
|
12
|
-
:filter-fields="
|
13
|
-
@update:filter="$emit('update:filter', $event)"
|
12
|
+
:filter="activeFilter"
|
13
|
+
:filter-fields="filters"
|
14
|
+
@update:filter="$emit('update:active-filter', $event)"
|
14
15
|
/>
|
15
16
|
</CollapsableSidebar>
|
16
17
|
</template>
|
17
|
-
<script setup>
|
18
|
+
<script setup lang="ts">
|
19
|
+
import { FilterField, ListControlsFilter } from "src/components/ActionTable/listControls";
|
18
20
|
import { FilterFieldList } from ".";
|
19
21
|
import { CollapsableSidebar } from "../../Utility";
|
20
22
|
|
21
|
-
defineEmits(["update:filter", "update:show-filters"]);
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
23
|
+
defineEmits(["update:active-filter", "update:show-filters"]);
|
24
|
+
|
25
|
+
export interface Props {
|
26
|
+
name: string,
|
27
|
+
showFilters?: boolean,
|
28
|
+
activeFilter: ListControlsFilter,
|
29
|
+
minWidth?: string,
|
30
|
+
maxWidth?: string,
|
31
|
+
filters?: FilterField[]
|
32
|
+
}
|
33
|
+
|
34
|
+
withDefaults(defineProps<Props>(), {
|
35
|
+
minWidth: "5rem",
|
36
|
+
maxWidth: "18rem",
|
37
|
+
filters: () => []
|
36
38
|
});
|
37
39
|
</script>
|
@@ -1,10 +1,7 @@
|
|
1
1
|
<template>
|
2
2
|
<div>
|
3
|
-
<div
|
4
|
-
|
5
|
-
class="font-bold text-xs mb-2"
|
6
|
-
>
|
7
|
-
{{ label }}
|
3
|
+
<div class="mb-2">
|
4
|
+
<FieldLabel :label="label" />
|
8
5
|
</div>
|
9
6
|
<template v-if="inline">
|
10
7
|
<QDate
|
@@ -41,6 +38,7 @@
|
|
41
38
|
import { CalendarIcon as DateIcon } from "@heroicons/vue/outline";
|
42
39
|
import { computed, ref, watch } from "vue";
|
43
40
|
import { fDate, parseQDate, parseQDateTime } from "../../../../helpers";
|
41
|
+
import FieldLabel from "./FieldLabel";
|
44
42
|
|
45
43
|
const emit = defineEmits(["update:model-value"]);
|
46
44
|
const props = defineProps({
|
@@ -1,13 +1,14 @@
|
|
1
1
|
<template>
|
2
2
|
<QInput
|
3
|
+
class="dx-number-field max-w-full"
|
4
|
+
:class="{'dx-no-prepend-label': hidePrependLabel, 'dx-prepend-label': !hidePrependLabel}"
|
3
5
|
:model-value="numberVal"
|
4
6
|
:data-testid="'number-field-' + fieldOptions.id"
|
5
7
|
:placeholder="fieldOptions.placeholder"
|
6
8
|
outlined
|
7
9
|
dense
|
8
10
|
inputmode="numeric"
|
9
|
-
:input-class="
|
10
|
-
:class="{'no-prepend-icon w-32 max-w-full': hidePrependLabel, 'prepend-label': !hidePrependLabel}"
|
11
|
+
:input-class="inputClass"
|
11
12
|
@update:model-value="onInput"
|
12
13
|
>
|
13
14
|
<template #prepend>
|
@@ -27,33 +28,33 @@ import FieldLabel from "./FieldLabel";
|
|
27
28
|
|
28
29
|
const emit = defineEmits(["update:model-value", "update"]);
|
29
30
|
const props = defineProps({
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
31
|
+
modelValue: {
|
32
|
+
type: [String, Number],
|
33
|
+
default: ""
|
34
|
+
},
|
35
|
+
precision: {
|
36
|
+
type: Number,
|
37
|
+
default: 2
|
38
|
+
},
|
39
|
+
label: {
|
40
|
+
type: String,
|
41
|
+
default: undefined
|
42
|
+
},
|
43
|
+
field: {
|
44
|
+
type: Object,
|
45
|
+
default: null
|
46
|
+
},
|
47
|
+
inputClass: {
|
48
|
+
type: [String, Object],
|
49
|
+
default: ""
|
50
|
+
},
|
51
|
+
delay: {
|
52
|
+
type: Number,
|
53
|
+
default: 1000
|
54
|
+
},
|
55
|
+
hidePrependLabel: Boolean,
|
56
|
+
currency: Boolean,
|
57
|
+
showName: Boolean
|
57
58
|
});
|
58
59
|
|
59
60
|
const numberVal = ref(format(props.modelValue));
|
@@ -62,46 +63,46 @@ watch(() => props.modelValue, () => numberVal.value = format(props.modelValue));
|
|
62
63
|
const fieldOptions = computed(() => props.field || { label: props.label || "", placeholder: "", id: "" });
|
63
64
|
|
64
65
|
function format(number) {
|
65
|
-
|
66
|
+
if (!number && number !== 0 && number !== "0") return number;
|
66
67
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
68
|
+
const minimumFractionDigits = Math.min(props.precision, ("" + number).split(".")[1]?.length || 0);
|
69
|
+
let options = {
|
70
|
+
minimumFractionDigits
|
71
|
+
};
|
71
72
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
73
|
+
if (props.currency) {
|
74
|
+
options = {
|
75
|
+
style: "currency",
|
76
|
+
currency: "USD",
|
77
|
+
minimumFractionDigits
|
78
|
+
};
|
79
|
+
}
|
80
|
+
return fNumber(number, options);
|
80
81
|
}
|
81
82
|
|
82
83
|
const onUpdateDebounced = useDebounceFn((val) => emit("update", val), props.delay);
|
83
84
|
|
84
85
|
function onInput(value) {
|
85
|
-
|
86
|
+
let number = "";
|
86
87
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
88
|
+
// Prevent invalid characters
|
89
|
+
if (value.match(/[^\d.,$]/)) {
|
90
|
+
const oldVal = numberVal.value;
|
91
|
+
// XXX: To get QInput to show only the value we want
|
92
|
+
numberVal.value += " ";
|
93
|
+
return nextTick(() => numberVal.value = oldVal);
|
94
|
+
}
|
94
95
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
96
|
+
if (value !== "") {
|
97
|
+
value = value.replace(/[^\d.]/g, "");
|
98
|
+
number = Number(value);
|
99
|
+
numberVal.value = format(number);
|
100
|
+
}
|
100
101
|
|
101
|
-
|
102
|
-
|
102
|
+
number = number === "" ? undefined : number;
|
103
|
+
emit("update:model-value", number);
|
103
104
|
|
104
|
-
|
105
|
-
|
105
|
+
// Delay the change event, so we only see the value after the user has finished
|
106
|
+
onUpdateDebounced(number);
|
106
107
|
}
|
107
108
|
</script>
|