bt-core-app 1.1.9 → 1.2.1
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/dist/bt-core-app.js +25270 -15306
- package/dist/components/BT-Btn.vue.d.ts +41 -0
- package/dist/components/BT-Col.vue.d.ts +49 -0
- package/dist/components/BT-Field-Checkbox.vue.d.ts +56 -0
- package/dist/components/BT-Field-Date.vue.d.ts +64 -0
- package/dist/components/BT-Field-Entity.vue.d.ts +46 -0
- package/dist/components/BT-Field-Select.vue.d.ts +54 -0
- package/dist/components/BT-Field-String.vue.d.ts +53 -0
- package/dist/components/BT-Field-Switch.vue.d.ts +51 -0
- package/dist/components/BT-Field-Tags.vue.d.ts +51 -0
- package/dist/components/BT-Field-Textarea.vue.d.ts +52 -0
- package/dist/components/BT-Field-Trigger.vue.d.ts +79 -0
- package/dist/components/BT-Header-Option.vue.d.ts +18 -0
- package/dist/components/BT-Json.vue.d.ts +8 -0
- package/dist/components/BT-Select-List-Box.vue.d.ts +108 -0
- package/dist/components/BT-Select.vue.d.ts +53 -0
- package/dist/components/BT-Snack.vue.d.ts +33 -0
- package/dist/components/Dialog-Confirm.vue.d.ts +2 -2
- package/dist/components/Dialog-Select-Date.vue.d.ts +2 -2
- package/dist/components/Dialog-Select.vue.d.ts +2 -2
- package/dist/components/Dialog-Text.vue.d.ts +2 -2
- package/dist/composables/actions.d.ts +6 -6
- package/dist/composables/api.d.ts +1 -0
- package/dist/composables/auth.d.ts +1 -0
- package/dist/composables/cosmetics.d.ts +3 -1
- package/dist/composables/dates.d.ts +1 -0
- package/dist/composables/demo.d.ts +1 -0
- package/dist/composables/filters.d.ts +1 -0
- package/dist/composables/list.d.ts +11 -2
- package/dist/composables/navigation.d.ts +1 -0
- package/dist/composables/presets.d.ts +1 -0
- package/dist/composables/pwa.d.ts +1 -0
- package/dist/composables/stores.d.ts +17 -6
- package/dist/index.d.ts +11 -12
- package/dist/style.css +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/useApi.d.ts +0 -30
- package/package.json +2 -1
- package/src/components/BT-Btn.vue +1 -1
- package/src/components/BT-Field-Checkbox.vue +70 -0
- package/src/components/BT-Field-Date.vue +108 -0
- package/src/components/BT-Field-Entity.vue +48 -0
- package/src/components/BT-Field-Select.vue +67 -0
- package/src/components/BT-Field-String.vue +78 -0
- package/src/components/BT-Field-Switch.vue +68 -0
- package/src/components/BT-Field-Tags.vue +66 -0
- package/src/components/BT-Field-Textarea.vue +67 -0
- package/src/components/BT-Field-Trigger.vue +315 -0
- package/src/components/BT-Header-Option.vue +39 -0
- package/src/components/BT-Json.vue +67 -0
- package/src/components/BT-Select-List-Box.vue +258 -0
- package/src/components/BT-Select.vue +46 -0
- package/src/components/BT-Snack.vue +31 -0
- package/src/components/Dialog-Select-Date.vue +1 -1
- package/src/composables/actions.ts +6 -6
- package/src/composables/api.ts +9 -1
- package/src/composables/auth.ts +15 -21
- package/src/composables/cosmetics.ts +27 -28
- package/src/composables/dates.ts +9 -1
- package/src/composables/demo.ts +9 -1
- package/src/composables/filters.ts +9 -1
- package/src/composables/list.ts +5 -2
- package/src/composables/navigation.ts +9 -1
- package/src/composables/presets.ts +9 -1
- package/src/composables/pwa.ts +9 -1
- package/src/composables/stores.ts +32 -11
- package/src/core.ts +49 -16
- package/src/index.ts +12 -12
- package/src/types.ts +5 -1
- package/src/useApi.ts +57 -57
- package/test/auth.test.ts +63 -0
- package/test/stores-last-update.test.ts +4 -4
- package/vite.config.ts +6 -2
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-slide-x-transition group>
|
|
3
|
+
<span v-if="option.prefix != null">{{ option.prefix }}</span>
|
|
4
|
+
<span v-if="option.bool != null">
|
|
5
|
+
<v-icon v-if="nestedValue(data, option.value) === true" :size="size">mdi-check</v-icon>
|
|
6
|
+
</span>
|
|
7
|
+
<bt-entity
|
|
8
|
+
v-else-if="option.nav != null && (option.itemText != null || option.textFilter != null)"
|
|
9
|
+
inline
|
|
10
|
+
:itemText="option.itemText"
|
|
11
|
+
:itemId="nestedValue(data, option.value)"
|
|
12
|
+
:nav="option.nav"
|
|
13
|
+
:single="option.single"
|
|
14
|
+
:textFilter="option.textFilter" />
|
|
15
|
+
<span v-else>{{ displayText(data) }}</span>
|
|
16
|
+
</v-slide-x-transition>
|
|
17
|
+
</template>
|
|
18
|
+
|
|
19
|
+
<script setup lang="ts">
|
|
20
|
+
import { type TableColumn } from '../composables/list'
|
|
21
|
+
import { nestedValue } from '../composables/helpers'
|
|
22
|
+
import { useFilters } from '../composables/filters'
|
|
23
|
+
import { computed } from 'vue';
|
|
24
|
+
|
|
25
|
+
interface Props {
|
|
26
|
+
data: any
|
|
27
|
+
option: TableColumn
|
|
28
|
+
size?: string | number
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const props = defineProps<Props>()
|
|
32
|
+
const filters = useFilters()
|
|
33
|
+
const displayText = computed(() => (item: any) => {
|
|
34
|
+
let v = nestedValue(item, props.option.value)
|
|
35
|
+
v = props.option.textFunction != null ? props.option.textFunction(v) : v
|
|
36
|
+
return props.option.textFilter != null ? filters.findFilter(props.option.textFilter)(v) : v
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
</script>
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-card max-height="350" class="overflow-y-auto">
|
|
3
|
+
<v-card-text>
|
|
4
|
+
<div v-for="(j, ind) in display" :key="ind">
|
|
5
|
+
<pre v-html="syntaxHighlight(j)"></pre>
|
|
6
|
+
</div>
|
|
7
|
+
</v-card-text>
|
|
8
|
+
</v-card>
|
|
9
|
+
</template>
|
|
10
|
+
|
|
11
|
+
<script setup lang="ts">
|
|
12
|
+
import { computed } from 'vue'
|
|
13
|
+
|
|
14
|
+
const props = defineProps(['value'])
|
|
15
|
+
|
|
16
|
+
const display = computed(() => {
|
|
17
|
+
if (props.value == null) {
|
|
18
|
+
return []
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (Array.isArray(props.value))
|
|
22
|
+
return props.value
|
|
23
|
+
|
|
24
|
+
return [props.value]
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
function syntaxHighlight(json: any) {
|
|
28
|
+
if (typeof json != 'string') {
|
|
29
|
+
json = JSON.stringify(json, undefined, 2); //Object.keys(json).sort(), 2);
|
|
30
|
+
}
|
|
31
|
+
json = json.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
32
|
+
|
|
33
|
+
const e = json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match: any) {
|
|
34
|
+
var cls = 'number';
|
|
35
|
+
if (/^"/.test(match)) {
|
|
36
|
+
if (/:$/.test(match)) {
|
|
37
|
+
cls = 'key';
|
|
38
|
+
} else {
|
|
39
|
+
cls = 'string';
|
|
40
|
+
}
|
|
41
|
+
} else if (/true|false/.test(match)) {
|
|
42
|
+
cls = 'boolean';
|
|
43
|
+
} else if (/null/.test(match)) {
|
|
44
|
+
cls = 'null';
|
|
45
|
+
}
|
|
46
|
+
return '<span class="' + cls + '">' + match + '</span>';
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
return e
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
</script>
|
|
53
|
+
|
|
54
|
+
<style>
|
|
55
|
+
pre {
|
|
56
|
+
outline: 1px solid #ccc;
|
|
57
|
+
padding: 5px;
|
|
58
|
+
margin: 5px; }
|
|
59
|
+
|
|
60
|
+
pre .string {
|
|
61
|
+
color: green;
|
|
62
|
+
}
|
|
63
|
+
pre .number { color: darkorange; }
|
|
64
|
+
pre .boolean { color: rgb(191, 255, 0); }
|
|
65
|
+
pre .null { color: magenta; }
|
|
66
|
+
pre .key { color: rgb(141, 141, 141); }
|
|
67
|
+
</style>
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-col
|
|
3
|
+
:class="colClass"
|
|
4
|
+
:lg="mLg"
|
|
5
|
+
:md="mMd"
|
|
6
|
+
:sm="mSm"
|
|
7
|
+
:cols="cols">
|
|
8
|
+
<v-list-item v-if="!alwaysOpen && mIsSelecting" @click="mIsSelecting = false"
|
|
9
|
+
:subtitle="label">
|
|
10
|
+
<template #append>
|
|
11
|
+
<v-row class="ma-0 pa-0">
|
|
12
|
+
<slot name="actions" />
|
|
13
|
+
<v-icon>mdi-chevron-up</v-icon>
|
|
14
|
+
<slot name="actionsRight" />
|
|
15
|
+
<v-menu
|
|
16
|
+
v-if="showSettings"
|
|
17
|
+
offset-y
|
|
18
|
+
:close-on-content-click="false">
|
|
19
|
+
<template v-slot:activator="{ props }">
|
|
20
|
+
<v-btn
|
|
21
|
+
icon="mdi-cog"
|
|
22
|
+
:size="mSize"
|
|
23
|
+
title="Settings"
|
|
24
|
+
v-bind="props" />
|
|
25
|
+
</template>
|
|
26
|
+
<v-list>
|
|
27
|
+
<slot name="settings" />
|
|
28
|
+
</v-list>
|
|
29
|
+
</v-menu>
|
|
30
|
+
</v-row>
|
|
31
|
+
</template>
|
|
32
|
+
</v-list-item>
|
|
33
|
+
<v-slide-y-transition hide-on-leave group>
|
|
34
|
+
<v-text-field
|
|
35
|
+
v-if="(alwaysOpen || mIsSelecting) && showSearch !== false && isLengthyArray(searchProps)"
|
|
36
|
+
@click:prepend-inner="ui.searchString.value = undefined"
|
|
37
|
+
hide-details
|
|
38
|
+
key="1"
|
|
39
|
+
placeholder="Search"
|
|
40
|
+
:prepend-inner-icon="ui.searchString.value != null ? 'mdi-close' : undefined"
|
|
41
|
+
v-model="ui.searchString.value">
|
|
42
|
+
<template #append-inner>
|
|
43
|
+
<v-btn
|
|
44
|
+
v-if="canRefresh"
|
|
45
|
+
@click="ui.refresh({ deepRefresh: true })"
|
|
46
|
+
icon="mdi-refresh"
|
|
47
|
+
:size="mSize"
|
|
48
|
+
variant="text" />
|
|
49
|
+
</template>
|
|
50
|
+
|
|
51
|
+
</v-text-field>
|
|
52
|
+
<v-virtual-scroll
|
|
53
|
+
v-if="(alwaysOpen || mIsSelecting) && useVirtualScroller"
|
|
54
|
+
:height="height"
|
|
55
|
+
:items="ui.filteredItems.value"
|
|
56
|
+
key="2">
|
|
57
|
+
<template #default="{ item }">
|
|
58
|
+
<slot name="item" v-bind:item="item" v-bind:selectItem="selectItem(item)" :active="isActive(item)">
|
|
59
|
+
<v-list-item @click="selectItem(item)" :active="isActive(item)" color="primary">
|
|
60
|
+
<slot v-bind:item="item">
|
|
61
|
+
<v-list-item-title v-if="itemText != null || textFilter != null || textFunction != null">
|
|
62
|
+
{{ displayTitle(item) }}
|
|
63
|
+
</v-list-item-title>
|
|
64
|
+
<v-list-item-subtitle v-if="itemSubtext != null || subtextFilter != null || subtextFunction != null">
|
|
65
|
+
{{ displaySubtitle(item) }}
|
|
66
|
+
</v-list-item-subtitle>
|
|
67
|
+
</slot>
|
|
68
|
+
|
|
69
|
+
</v-list-item>
|
|
70
|
+
</slot>
|
|
71
|
+
</template>
|
|
72
|
+
</v-virtual-scroll>
|
|
73
|
+
<v-list
|
|
74
|
+
v-else-if="alwaysOpen || mIsSelecting"
|
|
75
|
+
:bg-color="transparent ? 'transparent' : undefined"
|
|
76
|
+
:height="height"
|
|
77
|
+
key="3">
|
|
78
|
+
<v-list-item
|
|
79
|
+
v-if="canSelectNone"
|
|
80
|
+
key="-1"
|
|
81
|
+
density="compact"
|
|
82
|
+
@click="selectItem(null)"
|
|
83
|
+
subtitle="(Select None)" />
|
|
84
|
+
|
|
85
|
+
<template v-for="(fItem, fInd) in ui.filteredItems.value">
|
|
86
|
+
<slot name="item" :items="fItem" :index="fInd" :size="mSize">
|
|
87
|
+
<v-list-item
|
|
88
|
+
:active="isActive(fItem)"
|
|
89
|
+
:key="fInd"
|
|
90
|
+
:value="fItem"
|
|
91
|
+
@click="selectItem(fItem)">
|
|
92
|
+
<slot :item="fItem" :index="fInd" :size="mSize">
|
|
93
|
+
<v-list-item-title v-if="itemText != null || textFilter != null || textFunction != null">
|
|
94
|
+
{{ displayTitle(fItem) }}
|
|
95
|
+
</v-list-item-title>
|
|
96
|
+
<v-list-item-subtitle v-if="itemSubtext != null || subtextFilter != null || subtextFunction != null">
|
|
97
|
+
{{ displaySubtitle(fItem) }}
|
|
98
|
+
</v-list-item-subtitle>
|
|
99
|
+
</slot>
|
|
100
|
+
</v-list-item>
|
|
101
|
+
</slot>
|
|
102
|
+
</template>
|
|
103
|
+
</v-list>
|
|
104
|
+
<slot v-else name="selected" :item="selectedItem" :open="openList">
|
|
105
|
+
<v-list-item
|
|
106
|
+
@click="openList"
|
|
107
|
+
key="4"
|
|
108
|
+
:title="label"
|
|
109
|
+
:subtitle="displayTitle(selectedItem) ?? placeholder">
|
|
110
|
+
<template #append>
|
|
111
|
+
<v-row no-gutters>
|
|
112
|
+
<slot name="actions" />
|
|
113
|
+
<v-icon>mdi-chevron-down</v-icon>
|
|
114
|
+
<slot name="actionsRight" />
|
|
115
|
+
<v-menu
|
|
116
|
+
v-if="showSettings"
|
|
117
|
+
offset-y
|
|
118
|
+
:close-on-content-click="false">
|
|
119
|
+
<template v-slot:activator="{ props }">
|
|
120
|
+
<v-btn
|
|
121
|
+
icon
|
|
122
|
+
v-bind="props"
|
|
123
|
+
:size="mSize"
|
|
124
|
+
title="Settings" />
|
|
125
|
+
</template>
|
|
126
|
+
<v-list>
|
|
127
|
+
<slot name="settings" />
|
|
128
|
+
</v-list>
|
|
129
|
+
</v-menu>
|
|
130
|
+
</v-row>
|
|
131
|
+
</template>
|
|
132
|
+
</v-list-item>
|
|
133
|
+
</slot>
|
|
134
|
+
|
|
135
|
+
</v-slide-y-transition>
|
|
136
|
+
|
|
137
|
+
<v-overlay
|
|
138
|
+
v-model="ui.isLoading.value"
|
|
139
|
+
class="align-center justify-center text-center"
|
|
140
|
+
contained
|
|
141
|
+
persistent>
|
|
142
|
+
<v-progress-circular indeterminate />
|
|
143
|
+
<p>{{ ui.loadingMsg.value }}</p>
|
|
144
|
+
</v-overlay>
|
|
145
|
+
</v-col>
|
|
146
|
+
|
|
147
|
+
</template>
|
|
148
|
+
|
|
149
|
+
<script setup lang="ts">
|
|
150
|
+
import { type ListProps, useList } from '../composables/list'
|
|
151
|
+
import { computed, inject, ref } from 'vue'
|
|
152
|
+
import { useFilters } from '../composables/filters'
|
|
153
|
+
import { isLengthyArray, nestedValue } from '../composables/helpers'
|
|
154
|
+
|
|
155
|
+
defineOptions({
|
|
156
|
+
inheritAttrs: false
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
interface SelectProps extends ListProps {
|
|
160
|
+
alwaysOpen?: boolean
|
|
161
|
+
canRefresh?: boolean
|
|
162
|
+
canSearch?: boolean
|
|
163
|
+
canSelectNone?: boolean
|
|
164
|
+
colClass?: string
|
|
165
|
+
cols?: string | boolean
|
|
166
|
+
height?: string
|
|
167
|
+
isMobile?: boolean
|
|
168
|
+
isEditing?: boolean
|
|
169
|
+
isSelecting?: boolean
|
|
170
|
+
items?: [],
|
|
171
|
+
itemSubtext?: string
|
|
172
|
+
itemText?: string
|
|
173
|
+
itemValue?: string //inherited
|
|
174
|
+
label?: string
|
|
175
|
+
lg?: string | boolean
|
|
176
|
+
modelValue?: any
|
|
177
|
+
md?: string | boolean
|
|
178
|
+
nav?: string
|
|
179
|
+
placeholder?: string
|
|
180
|
+
showSettings?: boolean
|
|
181
|
+
sm?: string | boolean
|
|
182
|
+
subtextFilter?: string
|
|
183
|
+
subtextFunction?: Function
|
|
184
|
+
textFilter?: string
|
|
185
|
+
textFunction?: Function
|
|
186
|
+
transparent?: boolean
|
|
187
|
+
useVirtualScroller?: boolean
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const emit = defineEmits(['update:modelValue', 'change'])
|
|
191
|
+
|
|
192
|
+
const props = withDefaults(defineProps<SelectProps>(), {
|
|
193
|
+
canRefresh: true,
|
|
194
|
+
height: '400',
|
|
195
|
+
isEditing: undefined,
|
|
196
|
+
sortOrder: 'Ascending',
|
|
197
|
+
cols: '12',
|
|
198
|
+
lg: false,
|
|
199
|
+
md: false,
|
|
200
|
+
sm: '6'
|
|
201
|
+
})
|
|
202
|
+
|
|
203
|
+
const mIsSelecting = ref(props.alwaysOpen ?? props.isSelecting ?? false)
|
|
204
|
+
const mSize = inject('size', () => ref('small'), true)
|
|
205
|
+
const mIsEditing = inject('isEditing', () => ref(false), true)
|
|
206
|
+
const cIsEditing = computed(() => props.isEditing ?? mIsEditing.value)
|
|
207
|
+
|
|
208
|
+
const ui = useList(props, undefined, {
|
|
209
|
+
useBladeSrc: false,
|
|
210
|
+
useRouteSrc: false
|
|
211
|
+
})
|
|
212
|
+
|
|
213
|
+
const filters = useFilters()
|
|
214
|
+
|
|
215
|
+
const displaySubtitle = computed(() => (item: any) => {
|
|
216
|
+
let v = props.subtextFunction != null ? props.subtextFunction(item) : item
|
|
217
|
+
v = props.itemSubtext != null ? nestedValue(v, props.itemSubtext) : v
|
|
218
|
+
return props.subtextFilter != null ? filters.findFilter(props.subtextFilter)(v) : v
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
const displayTitle = computed(() => (item: any) => {
|
|
222
|
+
let v = props.textFunction != null ? props.textFunction(item) : item
|
|
223
|
+
v = props.itemText != null ? nestedValue(v, props.itemText) : v
|
|
224
|
+
return props.textFilter != null ? filters.findFilter(props.textFilter)(v) : v
|
|
225
|
+
})
|
|
226
|
+
|
|
227
|
+
const isActive = computed(() => (item: any) => {
|
|
228
|
+
return (props.itemValue ? item[props.itemValue] : item) == props.modelValue
|
|
229
|
+
})
|
|
230
|
+
|
|
231
|
+
function openList() {
|
|
232
|
+
if (cIsEditing.value)
|
|
233
|
+
mIsSelecting.value = true
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function selectItem(item: any) {
|
|
237
|
+
mIsSelecting.value = false
|
|
238
|
+
|
|
239
|
+
if (item != null || props.canSelectNone) {
|
|
240
|
+
let v = item
|
|
241
|
+
|
|
242
|
+
if (item != null && props.itemValue != null)
|
|
243
|
+
v = item[props.itemValue]
|
|
244
|
+
|
|
245
|
+
emit('update:modelValue', v)
|
|
246
|
+
emit('change', v)
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
const selectedItem = computed(() => {
|
|
251
|
+
return props.modelValue != null ? ui.asyncItems.value.find((x: any) => (x.id == props.modelValue)) : null
|
|
252
|
+
})
|
|
253
|
+
|
|
254
|
+
const mIsMobile = inject('isMobile', () => ref(false), true)
|
|
255
|
+
const mLg = computed(() => (props.isMobile ?? mIsMobile.value) ? false : props.lg)
|
|
256
|
+
const mMd = computed(() => (props.isMobile ?? mIsMobile.value) ? false : props.md)
|
|
257
|
+
const mSm = computed(() => (props.isMobile ?? mIsMobile.value) ? false : props.sm)
|
|
258
|
+
</script>
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-select
|
|
3
|
+
:append-icon="canRefresh ? 'mdi-refresh' : undefined"
|
|
4
|
+
:clearable="canSelectNone"
|
|
5
|
+
@click:append-icon="ui.refresh({ deepRefresh: true })"
|
|
6
|
+
hide-details
|
|
7
|
+
:items="ui.filteredItems.value"
|
|
8
|
+
:item-title="itemText"
|
|
9
|
+
:item-value="itemValue"
|
|
10
|
+
:variant="fieldVariant" />
|
|
11
|
+
</template>
|
|
12
|
+
|
|
13
|
+
<script setup lang="ts">
|
|
14
|
+
import { type ListProps, type ListEvents, useList } from '../composables/list';
|
|
15
|
+
import { type FieldVariant } from '../types'
|
|
16
|
+
|
|
17
|
+
interface SelectEvents extends ListEvents {
|
|
18
|
+
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface SelectProps extends ListProps {
|
|
22
|
+
additionalUrl?: string
|
|
23
|
+
canRefresh?: boolean
|
|
24
|
+
canSelectNone?: boolean
|
|
25
|
+
fieldVariant?: FieldVariant
|
|
26
|
+
items?: [],
|
|
27
|
+
itemText?: string
|
|
28
|
+
itemValue?: string //inherited
|
|
29
|
+
multiple?: boolean
|
|
30
|
+
nav?: string
|
|
31
|
+
onFilter?: Function
|
|
32
|
+
textFilter?: string
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const emit = defineEmits<SelectEvents>()
|
|
36
|
+
|
|
37
|
+
const props = withDefaults(defineProps<SelectProps>(), {
|
|
38
|
+
sortOrder: 'Ascending'
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
const ui = useList(props, emit, {
|
|
42
|
+
useBladeSrc: false,
|
|
43
|
+
useRouteSrc: false
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
</script>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-snackbar
|
|
3
|
+
v-model="showSnack"
|
|
4
|
+
:timeout="cTimeout">
|
|
5
|
+
{{ modelValue }}
|
|
6
|
+
</v-snackbar>
|
|
7
|
+
</template>
|
|
8
|
+
|
|
9
|
+
<script setup lang="ts">
|
|
10
|
+
import { computed, ref, watch } from 'vue';
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
interface SnackProps {
|
|
14
|
+
isTimed?: boolean
|
|
15
|
+
modelValue?: string
|
|
16
|
+
timeout?: string,
|
|
17
|
+
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const props = withDefaults(defineProps<SnackProps>(), {
|
|
21
|
+
isTimed: true,
|
|
22
|
+
timeout: '5000'
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
const cTimeout = computed(() => { return props.isTimed ? props.timeout : -1 })
|
|
26
|
+
const showSnack = ref(false)
|
|
27
|
+
watch(() => props.modelValue, () => {
|
|
28
|
+
showSnack.value = true
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
</script>
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
import { computed, onMounted, ref } from 'vue'
|
|
41
41
|
import VueDatePicker from '@vuepic/vue-datepicker'
|
|
42
42
|
import '@vuepic/vue-datepicker/dist/main.css'
|
|
43
|
-
import { useAuth } from '../
|
|
43
|
+
import { useAuth } from '../composables/auth'
|
|
44
44
|
import { type SelectDateProps } from '../composables/dialogs'
|
|
45
45
|
|
|
46
46
|
const props = withDefaults(defineProps<SelectDateProps>(), {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { BladeMode } from '../types'
|
|
2
|
-
import {
|
|
2
|
+
import { BTStoreDefinition } from '../composables/stores'
|
|
3
3
|
import { BTApi, type PathOptions } from '../composables/api'
|
|
4
4
|
import { useActionsTracker, type DoActionOptions } from '../composables/actions-tracker'
|
|
5
5
|
import { ShallowRef, ComputedRef } from 'vue'
|
|
@@ -15,7 +15,7 @@ export interface GetOptions extends PathOptions, DoActionOptions {
|
|
|
15
15
|
onGetAsync?: OnGetAsync
|
|
16
16
|
/**called after get occurs successfully */
|
|
17
17
|
onGetSuccessAsync?: OnGetSuccessAsync
|
|
18
|
-
store?:
|
|
18
|
+
store?: BTStoreDefinition
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
export interface DeleteOptions extends PathOptions, DoActionOptions {
|
|
@@ -25,7 +25,7 @@ export interface DeleteOptions extends PathOptions, DoActionOptions {
|
|
|
25
25
|
onDeleteAsync?: OnDoAsync
|
|
26
26
|
/**Will open a dialog box requesting user confirmation for delete action */
|
|
27
27
|
onDeleteSuccessAsync?: OnDoAsync
|
|
28
|
-
store?:
|
|
28
|
+
store?: BTStoreDefinition
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
export interface RestoreOptions extends PathOptions, DoActionOptions {
|
|
@@ -35,7 +35,7 @@ export interface RestoreOptions extends PathOptions, DoActionOptions {
|
|
|
35
35
|
onRestoreAsync?: OnDoSuccessAsync
|
|
36
36
|
/**Called after restore succeeds */
|
|
37
37
|
onRestoreSuccessAsync?: OnDoSuccessAsync
|
|
38
|
-
store?:
|
|
38
|
+
store?: BTStoreDefinition
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
export interface SaveOptions extends PathOptions, DoActionOptions {
|
|
@@ -52,7 +52,7 @@ export interface SaveOptions extends PathOptions, DoActionOptions {
|
|
|
52
52
|
onSaveAsync?: OnDoSuccessAsync
|
|
53
53
|
/**Called after save succeeds */
|
|
54
54
|
onSaveSuccessAsync?: OnDoSuccessAsync
|
|
55
|
-
store?:
|
|
55
|
+
store?: BTStoreDefinition
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
export interface ApiActionOptions extends PathOptions, DoActionOptions {
|
|
@@ -63,7 +63,7 @@ export interface UseActionsOptions extends DoActionOptions {
|
|
|
63
63
|
nav?: string
|
|
64
64
|
proxyID?: string
|
|
65
65
|
refresh?: boolean
|
|
66
|
-
store?:
|
|
66
|
+
store?: BTStoreDefinition
|
|
67
67
|
throwError?: boolean
|
|
68
68
|
url?: string
|
|
69
69
|
}
|
package/src/composables/api.ts
CHANGED
|
@@ -91,6 +91,12 @@ export interface BTApi {
|
|
|
91
91
|
patch: <T>(pathOptions: PathOptions) => Promise<T | undefined>
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
+
let current: BTApi
|
|
95
|
+
|
|
96
|
+
export function useApi(): BTApi {
|
|
97
|
+
return current
|
|
98
|
+
}
|
|
99
|
+
|
|
94
100
|
export function createApi(options?: UseApiOptions): BTApi {
|
|
95
101
|
const buildHeaders = options?.buildHeaders ?? defaultBuildHeaders
|
|
96
102
|
const buildQuery = options?.buildQuery ?? defaultBuildQuery
|
|
@@ -458,7 +464,7 @@ export function createApi(options?: UseApiOptions): BTApi {
|
|
|
458
464
|
}
|
|
459
465
|
}
|
|
460
466
|
|
|
461
|
-
|
|
467
|
+
current = {
|
|
462
468
|
buildHeaders,
|
|
463
469
|
buildQuery,
|
|
464
470
|
buildUrl,
|
|
@@ -468,4 +474,6 @@ export function createApi(options?: UseApiOptions): BTApi {
|
|
|
468
474
|
patch,
|
|
469
475
|
post
|
|
470
476
|
}
|
|
477
|
+
|
|
478
|
+
return current
|
|
471
479
|
}
|
package/src/composables/auth.ts
CHANGED
|
@@ -31,11 +31,8 @@ export interface BaseAuthCredentials {
|
|
|
31
31
|
userPermissions?: string[]
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
// const state = useStorage<BaseAuthCredentials>('auth-credentials', {})
|
|
35
|
-
// let defaultsSet = false
|
|
36
34
|
let defaultTimeZone = 'Australia/Melbourne'
|
|
37
35
|
|
|
38
|
-
// export type FindAuthItem = (navName?: string | AuthItem) => AuthItem | undefined
|
|
39
36
|
export type GetAuthUrl = (redirectPath?: string, state?: string) => string
|
|
40
37
|
|
|
41
38
|
export interface CreateAuthOptions {
|
|
@@ -70,28 +67,17 @@ export interface BTAuth {
|
|
|
70
67
|
tryLogin: () => boolean | undefined
|
|
71
68
|
}
|
|
72
69
|
|
|
73
|
-
|
|
74
|
-
// export function useTimeZone() {
|
|
75
|
-
// return state.value.timeZone ?? defaultTimeZone
|
|
76
|
-
// }
|
|
70
|
+
let current: BTAuth
|
|
77
71
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
72
|
+
export function useAuth(): BTAuth {
|
|
73
|
+
return current
|
|
74
|
+
}
|
|
81
75
|
|
|
82
76
|
export function createAuth(options: CreateAuthOptions): BTAuth {
|
|
83
|
-
const router = useRouter()
|
|
84
77
|
const expiryFormat = options.expiryTokenFormat ?? 'd/MM/yyyy h:mm:ss a'
|
|
85
78
|
const authState = useStorage<string>('auth-credentials-state', (Math.random().toString(36).substring(4, 19) + Math.random().toString(12).substring(1, 11)))
|
|
86
79
|
const state = useStorage<BaseAuthCredentials>('auth-credentials', {})
|
|
87
|
-
|
|
88
|
-
// if (!defaultsSet) {
|
|
89
|
-
// setDefaults()
|
|
90
|
-
// defaultsSet = true
|
|
91
|
-
// }
|
|
92
80
|
|
|
93
|
-
// const { endDemo, isDemoing } = useDemo()
|
|
94
|
-
|
|
95
81
|
/**can edit if navName is undefined, isGlobalAdmin, not suspended, or user permissions allow editing of this navItem */
|
|
96
82
|
function canEdit(navName?: string): boolean {
|
|
97
83
|
if (navName == null) return true
|
|
@@ -280,12 +266,13 @@ export function createAuth(options: CreateAuthOptions): BTAuth {
|
|
|
280
266
|
state.value = undefined
|
|
281
267
|
|
|
282
268
|
//ensure time zone still exists
|
|
283
|
-
|
|
269
|
+
reinstateDefaults()
|
|
284
270
|
|
|
285
271
|
//clear stores
|
|
286
272
|
|
|
287
273
|
//maybe redirect
|
|
288
274
|
if (navNameRedirect != null) {
|
|
275
|
+
const router = useRouter()
|
|
289
276
|
if (router.currentRoute.value.name != navNameRedirect) {
|
|
290
277
|
router.push({ name: navNameRedirect })
|
|
291
278
|
}
|
|
@@ -327,13 +314,16 @@ export function createAuth(options: CreateAuthOptions): BTAuth {
|
|
|
327
314
|
v.isLoggedIn = true
|
|
328
315
|
v.permissions = d.Permissions
|
|
329
316
|
v.subscriptionCode = d.Subscription
|
|
317
|
+
|
|
330
318
|
// v.subscriptionsInUse = d.SubscriptionsInUse
|
|
319
|
+
v.timeZone ??= (options.defaultTimeZone ?? defaultTimeZone)
|
|
320
|
+
|
|
331
321
|
v.token = d
|
|
332
322
|
v.userID = d.UserLoginID
|
|
333
323
|
v.userPermissions = d.Permissions?.split(',') ?? []
|
|
334
324
|
}
|
|
335
325
|
|
|
336
|
-
function
|
|
326
|
+
function reinstateDefaults() {
|
|
337
327
|
state.value.timeZone ??= (options.defaultTimeZone ?? defaultTimeZone)
|
|
338
328
|
}
|
|
339
329
|
|
|
@@ -363,7 +353,9 @@ export function createAuth(options: CreateAuthOptions): BTAuth {
|
|
|
363
353
|
return e1 <= e2
|
|
364
354
|
}
|
|
365
355
|
|
|
366
|
-
|
|
356
|
+
reinstateDefaults()
|
|
357
|
+
|
|
358
|
+
current = {
|
|
367
359
|
authState: authState.value,
|
|
368
360
|
canEdit,
|
|
369
361
|
canEditPermit,
|
|
@@ -379,4 +371,6 @@ export function createAuth(options: CreateAuthOptions): BTAuth {
|
|
|
379
371
|
setAuth,
|
|
380
372
|
tryLogin
|
|
381
373
|
}
|
|
374
|
+
|
|
375
|
+
return current
|
|
382
376
|
}
|