@7365admin1/layer-common 3.2.2-staging.91 → 3.2.2-staging.93
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/.changeset/pm-sidebar-grouping-and-list-scaffold.md +27 -0
- package/assets/css/primitives.css +147 -0
- package/components/AppKpiTile.vue +65 -0
- package/components/AppSegmented.vue +38 -0
- package/components/Avatar/Main.vue +13 -1
- package/components/DashboardMain.vue +69 -124
- package/components/FeedbackMain.vue +33 -36
- package/components/InvitationMain.vue +45 -62
- package/components/Layout/Header.vue +16 -2
- package/components/Layout/NavigationDrawer.vue +4 -3
- package/components/ServiceProviderMain.vue +105 -135
- package/components/SwitchContext.vue +33 -1
- package/components/WorkOrder/Main.vue +42 -51
- package/package.json +1 -1
- package/utils/nav-sections.test.ts +70 -11
- package/utils/nav-sections.ts +48 -25
|
@@ -1,69 +1,45 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
</v-col>
|
|
2
|
+
<div>
|
|
3
|
+
<!-- The design's page scaffold: a title with the action on the right of
|
|
4
|
+
that line, then ONE row inside the card - the two tabs on the left,
|
|
5
|
+
refresh, the range and the pager on the right. The tabs route exactly
|
|
6
|
+
as they did; only where they sit has changed. -->
|
|
7
|
+
<PageHeader title="Invitations">
|
|
8
|
+
<template v-if="props.inviteMember" #actions>
|
|
9
|
+
<AppButton @click="inviteMember()">Invite member</AppButton>
|
|
10
|
+
</template>
|
|
11
|
+
</PageHeader>
|
|
12
|
+
|
|
13
|
+
<v-row no-gutters>
|
|
15
14
|
<v-col cols="12">
|
|
16
|
-
<
|
|
17
|
-
<
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
icon
|
|
26
|
-
density="comfortable"
|
|
27
|
-
@click="getVerifications()"
|
|
15
|
+
<AppCard class="table-card">
|
|
16
|
+
<CardToolbar :count="pageRange">
|
|
17
|
+
<template #tabs>
|
|
18
|
+
<NuxtLink
|
|
19
|
+
v-for="tab in invitationTabs"
|
|
20
|
+
:key="tab.status"
|
|
21
|
+
class="app-tab"
|
|
22
|
+
:class="{ 'app-tab--active': props.status === tab.status }"
|
|
23
|
+
:to="{ name: props.route, params: { status: tab.status } }"
|
|
28
24
|
>
|
|
29
|
-
|
|
30
|
-
</
|
|
31
|
-
</template>
|
|
32
|
-
|
|
33
|
-
<template #append>
|
|
34
|
-
<v-row no-gutters justify="end" align="center">
|
|
35
|
-
<span class="mr-2 table-card__range">
|
|
36
|
-
{{ pageRange }}
|
|
37
|
-
</span>
|
|
38
|
-
<local-pagination
|
|
39
|
-
v-model="page"
|
|
40
|
-
:length="pages"
|
|
41
|
-
@update:value="getVerifications"
|
|
42
|
-
/>
|
|
43
|
-
</v-row>
|
|
25
|
+
{{ tab.label }}
|
|
26
|
+
</NuxtLink>
|
|
44
27
|
</template>
|
|
45
28
|
|
|
46
|
-
<template #
|
|
47
|
-
<
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
name: props.route,
|
|
59
|
-
params: { status: 'expired' },
|
|
60
|
-
}"
|
|
61
|
-
>
|
|
62
|
-
Expired
|
|
63
|
-
</v-tab>
|
|
64
|
-
</v-tabs>
|
|
29
|
+
<template #right>
|
|
30
|
+
<AppButton
|
|
31
|
+
variant="icon"
|
|
32
|
+
icon="mdi-refresh"
|
|
33
|
+
aria-label="Refresh"
|
|
34
|
+
@click="getVerifications()"
|
|
35
|
+
/>
|
|
36
|
+
<local-pagination
|
|
37
|
+
v-model="page"
|
|
38
|
+
:length="pages"
|
|
39
|
+
@update:value="getVerifications"
|
|
40
|
+
/>
|
|
65
41
|
</template>
|
|
66
|
-
</
|
|
42
|
+
</CardToolbar>
|
|
67
43
|
|
|
68
44
|
<v-data-table
|
|
69
45
|
:headers="headers"
|
|
@@ -105,7 +81,7 @@
|
|
|
105
81
|
{{ formatStatus(value) }}
|
|
106
82
|
</template>
|
|
107
83
|
</v-data-table>
|
|
108
|
-
</
|
|
84
|
+
</AppCard>
|
|
109
85
|
</v-col>
|
|
110
86
|
|
|
111
87
|
<ConfirmDialog
|
|
@@ -155,10 +131,17 @@
|
|
|
155
131
|
:app="props.app"
|
|
156
132
|
/>
|
|
157
133
|
</v-dialog>
|
|
158
|
-
|
|
134
|
+
</v-row>
|
|
135
|
+
</div>
|
|
159
136
|
</template>
|
|
160
137
|
|
|
161
138
|
<script setup lang="ts">
|
|
139
|
+
/** The same two tabs, same labels, same routes. */
|
|
140
|
+
const invitationTabs = [
|
|
141
|
+
{ status: "pending", label: "Pending" },
|
|
142
|
+
{ status: "expired", label: "Expired" },
|
|
143
|
+
];
|
|
144
|
+
|
|
162
145
|
const props = defineProps({
|
|
163
146
|
app: {
|
|
164
147
|
type: String,
|
|
@@ -126,7 +126,18 @@ const { currentUser } = useLocalAuth();
|
|
|
126
126
|
*/
|
|
127
127
|
const { site } = useSite();
|
|
128
128
|
|
|
129
|
-
|
|
129
|
+
/**
|
|
130
|
+
* The shared `site` state is only populated by the screens that load a site
|
|
131
|
+
* document, so on most screens - the dashboard included - the bar had no name
|
|
132
|
+
* to print. `SwitchContext` mirrors the label it is ALREADY showing in the
|
|
133
|
+
* rail into this state, so the bar falls back to the very name the user can
|
|
134
|
+
* see two inches to the left. Still no request from this component.
|
|
135
|
+
*/
|
|
136
|
+
const shellSiteName = useState<string>("shell-context-site-name", () => "");
|
|
137
|
+
|
|
138
|
+
const siteName = computed(() =>
|
|
139
|
+
String(site.value?.name || shellSiteName.value || "").trim()
|
|
140
|
+
);
|
|
130
141
|
|
|
131
142
|
const route = useRoute();
|
|
132
143
|
|
|
@@ -188,8 +199,11 @@ const name = computed(() => {
|
|
|
188
199
|
|
|
189
200
|
if(full) return full;
|
|
190
201
|
|
|
202
|
+
/* A member invited by email has no name stored yet, which left the avatar's
|
|
203
|
+
initials empty and the circle blank. The address is what the product shows
|
|
204
|
+
that member everywhere else, so it stands in here too. */
|
|
191
205
|
const alternative = user?.name?.trim();
|
|
192
|
-
return alternative || ""
|
|
206
|
+
return alternative || user?.email?.trim() || ""
|
|
193
207
|
|
|
194
208
|
})
|
|
195
209
|
|
|
@@ -283,9 +283,10 @@ const handleClick = (item: any) => {
|
|
|
283
283
|
font-weight: var(--fw-card-title);
|
|
284
284
|
line-height: 1.2;
|
|
285
285
|
color: var(--text);
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
286
|
+
/* The design prints the application's name in full ("Property Management").
|
|
287
|
+
Truncating it to "Property Managem…" in a 252px rail loses the word that
|
|
288
|
+
tells the user which product they are in, so it wraps instead. */
|
|
289
|
+
overflow-wrap: anywhere;
|
|
289
290
|
text-transform: capitalize;
|
|
290
291
|
}
|
|
291
292
|
|
|
@@ -1,108 +1,91 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
<div class="sp-table-header">
|
|
61
|
-
<!-- No fixed colour: `grey-lighten-4` is a light-mode grey in both
|
|
62
|
-
themes, which is what made this strip a white slab in dark
|
|
63
|
-
mode. `transparent` lets the themed .sp-table-header show. -->
|
|
64
|
-
<v-toolbar
|
|
65
|
-
density="compact"
|
|
66
|
-
color="transparent"
|
|
67
|
-
flat
|
|
68
|
-
class="sp-toolbar-top px-2"
|
|
69
|
-
>
|
|
70
|
-
<v-btn
|
|
71
|
-
icon
|
|
72
|
-
variant="text"
|
|
73
|
-
density="comfortable"
|
|
74
|
-
@click="loadList()"
|
|
75
|
-
>
|
|
76
|
-
<v-icon>mdi-refresh</v-icon>
|
|
77
|
-
</v-btn>
|
|
78
|
-
|
|
79
|
-
<v-spacer />
|
|
80
|
-
|
|
81
|
-
<template v-if="canViewServiceProviders">
|
|
82
|
-
<span class="mr-2 text-caption text-medium-emphasis">{{
|
|
83
|
-
pageRange
|
|
84
|
-
}}</span>
|
|
85
|
-
<local-pagination
|
|
86
|
-
v-model="page"
|
|
87
|
-
:length="pages"
|
|
88
|
-
@update:value="loadList()"
|
|
89
|
-
/>
|
|
90
|
-
</template>
|
|
91
|
-
</v-toolbar>
|
|
92
|
-
|
|
93
|
-
<v-tabs
|
|
94
|
-
v-model="listTab"
|
|
95
|
-
color="primary"
|
|
96
|
-
density="comfortable"
|
|
97
|
-
class="sp-tabs screen-tabs"
|
|
98
|
-
align-tabs="start"
|
|
2
|
+
<div>
|
|
3
|
+
<!--
|
|
4
|
+
THE DESIGN'S PAGE SCAFFOLD (same shape as Members).
|
|
5
|
+
|
|
6
|
+
The screen had no title at all, its primary actions sat top-LEFT, the
|
|
7
|
+
search box floated outside the card, and the refresh + pager sat on one
|
|
8
|
+
row with the tabs stacked on a second row below. The design draws a 22px
|
|
9
|
+
title with the actions on the right of that line, then ONE row inside the
|
|
10
|
+
card: tabs left, search / refresh / count / pager right.
|
|
11
|
+
|
|
12
|
+
Placement only. The same buttons open the same dialogs under the same
|
|
13
|
+
permission conditions, the same three tabs load the same three lists, the
|
|
14
|
+
same search feeds the same debounced `loadList()`, and the table, its
|
|
15
|
+
columns and its row menu are untouched.
|
|
16
|
+
-->
|
|
17
|
+
<PageHeader title="Service Providers">
|
|
18
|
+
<template #actions>
|
|
19
|
+
<AppButton
|
|
20
|
+
v-if="showBillingButton"
|
|
21
|
+
variant="ghost"
|
|
22
|
+
@click="
|
|
23
|
+
useRouter().push({
|
|
24
|
+
name: 'org-site-service-provider-mgmt-billing',
|
|
25
|
+
})
|
|
26
|
+
"
|
|
27
|
+
>
|
|
28
|
+
Billing
|
|
29
|
+
</AppButton>
|
|
30
|
+
<AppButton
|
|
31
|
+
v-if="showAddButton && canAddServiceProvider"
|
|
32
|
+
variant="ghost"
|
|
33
|
+
@click="(createDialog = true), setServiceProvider({ mode: 'add' })"
|
|
34
|
+
>
|
|
35
|
+
Add
|
|
36
|
+
</AppButton>
|
|
37
|
+
<AppButton
|
|
38
|
+
v-if="canInviteServiceProvider"
|
|
39
|
+
@click="
|
|
40
|
+
(createInviteDialog = true), setServiceProvider({ mode: 'invite' })
|
|
41
|
+
"
|
|
42
|
+
>
|
|
43
|
+
Invite
|
|
44
|
+
</AppButton>
|
|
45
|
+
</template>
|
|
46
|
+
</PageHeader>
|
|
47
|
+
|
|
48
|
+
<AppCard class="table-card">
|
|
49
|
+
<CardToolbar :count="canViewServiceProviders ? pageRange : ''">
|
|
50
|
+
<template #tabs>
|
|
51
|
+
<button
|
|
52
|
+
v-for="tab in listTabs"
|
|
53
|
+
:key="tab.value"
|
|
54
|
+
type="button"
|
|
55
|
+
role="tab"
|
|
56
|
+
class="app-tab"
|
|
57
|
+
:class="{ 'app-tab--active': listTab === tab.value }"
|
|
58
|
+
:aria-selected="listTab === tab.value"
|
|
59
|
+
@click="listTab = tab.value"
|
|
99
60
|
>
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
61
|
+
{{ tab.label }}
|
|
62
|
+
</button>
|
|
63
|
+
</template>
|
|
64
|
+
|
|
65
|
+
<template #right>
|
|
66
|
+
<AppField
|
|
67
|
+
v-model="searchText"
|
|
68
|
+
search
|
|
69
|
+
compact
|
|
70
|
+
placeholder="Search"
|
|
71
|
+
klass="app-toolbar__search"
|
|
72
|
+
/>
|
|
73
|
+
<AppButton
|
|
74
|
+
variant="icon"
|
|
75
|
+
icon="mdi-refresh"
|
|
76
|
+
aria-label="Refresh"
|
|
77
|
+
@click="loadList()"
|
|
78
|
+
/>
|
|
79
|
+
<local-pagination
|
|
80
|
+
v-if="canViewServiceProviders"
|
|
81
|
+
v-model="page"
|
|
82
|
+
:length="pages"
|
|
83
|
+
@update:value="loadList()"
|
|
84
|
+
/>
|
|
85
|
+
</template>
|
|
86
|
+
</CardToolbar>
|
|
87
|
+
|
|
88
|
+
<div class="app-table-scroll">
|
|
106
89
|
<v-data-table
|
|
107
90
|
v-if="canViewServiceProviders"
|
|
108
91
|
:headers="headers"
|
|
@@ -111,6 +94,7 @@
|
|
|
111
94
|
:items-per-page="pageSize"
|
|
112
95
|
fixed-header
|
|
113
96
|
hide-default-footer
|
|
97
|
+
:loading="loading"
|
|
114
98
|
class="sp-table"
|
|
115
99
|
style="max-height: calc(100vh - 280px)"
|
|
116
100
|
>
|
|
@@ -222,12 +206,16 @@
|
|
|
222
206
|
</v-menu>
|
|
223
207
|
</template>
|
|
224
208
|
</v-data-table>
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
209
|
+
</div>
|
|
210
|
+
|
|
211
|
+
<div
|
|
212
|
+
v-if="!canViewServiceProviders"
|
|
213
|
+
class="pa-4 text-body-2 text-medium-emphasis"
|
|
214
|
+
>
|
|
215
|
+
You do not have permission to view service providers.
|
|
216
|
+
</div>
|
|
217
|
+
</AppCard>
|
|
218
|
+
</div>
|
|
231
219
|
|
|
232
220
|
<v-dialog v-model="viewDialog" max-width="514">
|
|
233
221
|
<v-card rounded="lg" class="sp-members-card">
|
|
@@ -791,6 +779,12 @@ const { requiredRule, emailRule, debounce } = useUtils();
|
|
|
791
779
|
const { getUserByEmail } = useUser();
|
|
792
780
|
|
|
793
781
|
const listTab = ref<ListTab>("active");
|
|
782
|
+
/** The same three tabs, in the same order, with the same labels. */
|
|
783
|
+
const listTabs: Array<{ value: ListTab; label: string }> = [
|
|
784
|
+
{ value: "active", label: "Service Providers" },
|
|
785
|
+
{ value: "pending", label: "Pending" },
|
|
786
|
+
{ value: "inactive", label: "In-Active" },
|
|
787
|
+
];
|
|
794
788
|
const page = ref(1);
|
|
795
789
|
const pages = ref(0);
|
|
796
790
|
const pageRange = ref("-- - -- of --");
|
|
@@ -1489,32 +1483,8 @@ async function submitServiceProviderInvite() {
|
|
|
1489
1483
|
</script>
|
|
1490
1484
|
|
|
1491
1485
|
<style scoped>
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
align-items: center;
|
|
1495
|
-
flex-wrap: nowrap;
|
|
1496
|
-
gap: 4px;
|
|
1497
|
-
}
|
|
1498
|
-
|
|
1499
|
-
.sp-table-header {
|
|
1500
|
-
/* Was a hardcoded #f5f5f5 with a black border: in dark mode the tab strip
|
|
1501
|
-
became a white slab and the tab labels and the page range disappeared
|
|
1502
|
-
into it. These take the colour of whichever theme they are in. */
|
|
1503
|
-
background: rgb(var(--v-theme-surface-light, var(--v-theme-surface)));
|
|
1504
|
-
border-bottom: 1px solid
|
|
1505
|
-
rgba(var(--v-border-color), var(--v-border-opacity));
|
|
1506
|
-
}
|
|
1507
|
-
|
|
1508
|
-
.sp-tabs {
|
|
1509
|
-
width: 100%;
|
|
1510
|
-
min-height: 40px;
|
|
1511
|
-
}
|
|
1512
|
-
|
|
1513
|
-
.sp-tabs :deep(.v-tab) {
|
|
1514
|
-
min-width: 120px;
|
|
1515
|
-
justify-content: flex-start;
|
|
1516
|
-
text-transform: none;
|
|
1517
|
-
}
|
|
1486
|
+
/* The tab strip's own theming went with the strip: the tabs are the card's
|
|
1487
|
+
first row now and take `.app-tab` from the shared primitives. */
|
|
1518
1488
|
|
|
1519
1489
|
.sp-col-company {
|
|
1520
1490
|
max-width: 220px;
|
|
@@ -15,7 +15,10 @@
|
|
|
15
15
|
:to="props.route"
|
|
16
16
|
class="text-subtitle-2 font-weight-bold"
|
|
17
17
|
>
|
|
18
|
-
|
|
18
|
+
<!-- The design prints the organisation and site names in full.
|
|
19
|
+
Vuetify's list-item title truncates by default, which cut them
|
|
20
|
+
to "Property Managem…" / "Seventh Cond…" in the 252px rail. -->
|
|
21
|
+
<v-list-item-title class="switch-context__name">
|
|
19
22
|
{{ name || `Select ${prop.title}` }}
|
|
20
23
|
</v-list-item-title>
|
|
21
24
|
</v-list-item>
|
|
@@ -100,9 +103,38 @@ const name = computed(() => {
|
|
|
100
103
|
return prop.items.find((item) => item.value === selected.value)?.text ?? "";
|
|
101
104
|
});
|
|
102
105
|
|
|
106
|
+
/**
|
|
107
|
+
* THE BREADCRUMB'S SITE HALF.
|
|
108
|
+
*
|
|
109
|
+
* The top bar draws `Site name / Page`, but the site's NAME is only ever
|
|
110
|
+
* resolved here - each application loads its own site list and hands it to
|
|
111
|
+
* this selector, so the bar had nothing to print and showed the page alone.
|
|
112
|
+
* The label already on screen is mirrored into shared state for the bar to
|
|
113
|
+
* read. It is a label: no request is made, and what the selector selects is
|
|
114
|
+
* untouched.
|
|
115
|
+
*/
|
|
116
|
+
const shellSiteName = useState<string>("shell-context-site-name", () => "");
|
|
117
|
+
|
|
118
|
+
watchEffect(() => {
|
|
119
|
+
if (prop.title?.toLowerCase() === "site" && name.value) {
|
|
120
|
+
shellSiteName.value = name.value;
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
|
|
103
124
|
const selectItem = (value: string) => {
|
|
104
125
|
selected.value = value;
|
|
105
126
|
menu.value = false;
|
|
106
127
|
emit("select", value);
|
|
107
128
|
};
|
|
108
129
|
</script>
|
|
130
|
+
|
|
131
|
+
<style scoped>
|
|
132
|
+
/* Wrap onto a second line instead of truncating - the design shows the full
|
|
133
|
+
organisation and site names. */
|
|
134
|
+
.switch-context__name {
|
|
135
|
+
white-space: normal;
|
|
136
|
+
overflow: visible;
|
|
137
|
+
overflow-wrap: anywhere;
|
|
138
|
+
line-height: 1.25;
|
|
139
|
+
}
|
|
140
|
+
</style>
|
|
@@ -1,58 +1,47 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
>
|
|
2
|
+
<div>
|
|
3
|
+
<!--
|
|
4
|
+
The design's page scaffold. The screen had no heading, its Create button
|
|
5
|
+
sat top-left and the search floated top-right outside the card, with
|
|
6
|
+
refresh and the pager stacked on their own bar above the table. Same
|
|
7
|
+
button, same dialog, same permission, same debounced search, same pager.
|
|
8
|
+
-->
|
|
9
|
+
<PageHeader title="Work Orders">
|
|
10
|
+
<template v-if="canCreateWorkOrder" #actions>
|
|
11
|
+
<AppButton @click="(showCreateDialog = true), (isEditMode = false)">
|
|
13
12
|
Create Work Order
|
|
14
|
-
</
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
variant="outlined"
|
|
20
|
-
density="comfortable"
|
|
21
|
-
clearable
|
|
22
|
-
hide-details
|
|
23
|
-
class="ml-2"
|
|
24
|
-
style="max-width: 250px"
|
|
25
|
-
/>
|
|
26
|
-
</v-row>
|
|
27
|
-
</v-col>
|
|
13
|
+
</AppButton>
|
|
14
|
+
</template>
|
|
15
|
+
</PageHeader>
|
|
16
|
+
|
|
17
|
+
<v-row no-gutters>
|
|
28
18
|
<v-col cols="12">
|
|
29
|
-
<
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
<v-btn fab icon density="comfortable" @click="updatePage(1)">
|
|
39
|
-
<v-icon>mdi-refresh</v-icon>
|
|
40
|
-
</v-btn>
|
|
19
|
+
<AppCard class="table-card">
|
|
20
|
+
<CardToolbar :count="pageRange">
|
|
21
|
+
<template #left>
|
|
22
|
+
<AppButton
|
|
23
|
+
variant="icon"
|
|
24
|
+
icon="mdi-refresh"
|
|
25
|
+
aria-label="Refresh"
|
|
26
|
+
@click="updatePage(1)"
|
|
27
|
+
/>
|
|
41
28
|
</template>
|
|
42
29
|
|
|
43
|
-
<template #
|
|
44
|
-
<
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
30
|
+
<template #right>
|
|
31
|
+
<AppField
|
|
32
|
+
v-model="searchText"
|
|
33
|
+
search
|
|
34
|
+
compact
|
|
35
|
+
placeholder="Search work order..."
|
|
36
|
+
klass="app-toolbar__search"
|
|
37
|
+
/>
|
|
38
|
+
<local-pagination
|
|
39
|
+
v-model="page"
|
|
40
|
+
:length="pages"
|
|
41
|
+
@update:value="updatePage"
|
|
42
|
+
/>
|
|
54
43
|
</template>
|
|
55
|
-
</
|
|
44
|
+
</CardToolbar>
|
|
56
45
|
|
|
57
46
|
<v-data-table
|
|
58
47
|
:headers="headers"
|
|
@@ -62,6 +51,7 @@
|
|
|
62
51
|
fixed-header
|
|
63
52
|
hide-default-footer
|
|
64
53
|
:hide-default-header="false"
|
|
54
|
+
:loading="loading"
|
|
65
55
|
@click:row="tableRowClickHandler"
|
|
66
56
|
style="max-height: calc(100vh - (200px))"
|
|
67
57
|
>
|
|
@@ -69,9 +59,10 @@
|
|
|
69
59
|
{{ formatDateDDMMYYYYLocal(item.createdAt) }}
|
|
70
60
|
</template>
|
|
71
61
|
</v-data-table>
|
|
72
|
-
</
|
|
62
|
+
</AppCard>
|
|
73
63
|
</v-col>
|
|
74
|
-
|
|
64
|
+
</v-row>
|
|
65
|
+
</div>
|
|
75
66
|
|
|
76
67
|
<WorkOrderCreate
|
|
77
68
|
v-model="showCreateDialog"
|