@7365admin1/layer-common 3.2.2-staging.128 → 3.2.2-staging.129
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/components/Carousel.vue +56 -36
- package/components/Chat/Bubbles.vue +43 -14
- package/components/Chat/Information.vue +49 -32
- package/components/Chat/ListCard.vue +38 -9
- package/components/Chat/Message.vue +41 -15
- package/components/Chat/Navigation.vue +27 -15
- package/components/DrawImage.vue +29 -21
- package/components/Input/Date.vue +3 -0
- package/components/Input/File.vue +55 -10
- package/components/Input/ListGroupSelection.vue +56 -8
- package/components/WorkOrder/Create.vue +26 -17
- package/package.json +1 -1
package/components/Carousel.vue
CHANGED
|
@@ -22,9 +22,7 @@
|
|
|
22
22
|
|
|
23
23
|
<div class="edit-btn mb-5" v-if="imgEditable">
|
|
24
24
|
<v-btn
|
|
25
|
-
|
|
26
|
-
height="42px"
|
|
27
|
-
width="100px"
|
|
25
|
+
class="screen-btn-primary"
|
|
28
26
|
@click.stop="onMediaEdit(item.url, idx)"
|
|
29
27
|
>
|
|
30
28
|
Edit
|
|
@@ -32,14 +30,9 @@
|
|
|
32
30
|
</div>
|
|
33
31
|
|
|
34
32
|
<div class="delete-btn mb-3" v-if="imgDelete">
|
|
35
|
-
<
|
|
36
|
-
color="red"
|
|
37
|
-
height="42px"
|
|
38
|
-
width="100px"
|
|
39
|
-
@click.stop="onMediaDelete(item.url)"
|
|
40
|
-
>
|
|
33
|
+
<AppButton variant="err" @click.stop="onMediaDelete(item.url)">
|
|
41
34
|
Delete
|
|
42
|
-
</
|
|
35
|
+
</AppButton>
|
|
43
36
|
</div>
|
|
44
37
|
</v-carousel-item>
|
|
45
38
|
|
|
@@ -53,20 +46,15 @@
|
|
|
53
46
|
<source :src="item.url" />
|
|
54
47
|
</video>
|
|
55
48
|
<div class="play-overlay">
|
|
56
|
-
<v-btn class="play-btn" icon size="55"
|
|
49
|
+
<v-btn class="play-btn" icon size="55">
|
|
57
50
|
<v-icon icon="mdi-play" size="40" />
|
|
58
51
|
</v-btn>
|
|
59
52
|
</div>
|
|
60
53
|
|
|
61
54
|
<div class="delete-btn pb-4" v-if="imgDelete">
|
|
62
|
-
<
|
|
63
|
-
color="red"
|
|
64
|
-
height="42px"
|
|
65
|
-
width="100px"
|
|
66
|
-
@click.stop="onMediaDelete(item.url)"
|
|
67
|
-
>
|
|
55
|
+
<AppButton variant="err" @click.stop="onMediaDelete(item.url)">
|
|
68
56
|
Delete
|
|
69
|
-
</
|
|
57
|
+
</AppButton>
|
|
70
58
|
</div>
|
|
71
59
|
</div>
|
|
72
60
|
</v-carousel-item>
|
|
@@ -82,19 +70,16 @@
|
|
|
82
70
|
<v-icon
|
|
83
71
|
:icon="getFileIcon(item.type)"
|
|
84
72
|
size="150"
|
|
85
|
-
:
|
|
73
|
+
:class="getFileIconTone(getFileIcon(item.type))"
|
|
86
74
|
/>
|
|
87
|
-
<div class="
|
|
75
|
+
<div class="screen-card-title text-center text-wrap mt-2">
|
|
76
|
+
{{ item.name }}
|
|
77
|
+
</div>
|
|
88
78
|
|
|
89
79
|
<div class="delete-btn pb-4" v-if="imgDelete">
|
|
90
|
-
<
|
|
91
|
-
color="red"
|
|
92
|
-
height="42px"
|
|
93
|
-
width="100px"
|
|
94
|
-
@click.stop="onMediaDelete(item.url)"
|
|
95
|
-
>
|
|
80
|
+
<AppButton variant="err" @click.stop="onMediaDelete(item.url)">
|
|
96
81
|
Delete
|
|
97
|
-
</
|
|
82
|
+
</AppButton>
|
|
98
83
|
</div>
|
|
99
84
|
</div>
|
|
100
85
|
</v-carousel-item>
|
|
@@ -105,7 +90,7 @@
|
|
|
105
90
|
|
|
106
91
|
<!-- Dialog for fullscreen view -->
|
|
107
92
|
<v-dialog v-model="isDialogOpen" max-width="700">
|
|
108
|
-
<v-card>
|
|
93
|
+
<v-card class="screen-modal">
|
|
109
94
|
<v-btn icon class="close-btn" @click="isDialogOpen = false">
|
|
110
95
|
<v-icon icon="mdi-close" size="40" />
|
|
111
96
|
</v-btn>
|
|
@@ -346,14 +331,21 @@ const getFileIcon = (type: string) => {
|
|
|
346
331
|
return iconMap[type] || "mdi-file-outline";
|
|
347
332
|
};
|
|
348
333
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
334
|
+
/**
|
|
335
|
+
* The file-type tone. The handoff draws no file-type icon palette at all, so
|
|
336
|
+
* the six distinctions this screen already made are kept and simply said in the
|
|
337
|
+
* tokens that carry those tones - the same reading `AttachmentsViewer` took.
|
|
338
|
+
* The one exception is the archive icon, which was purple: there is no purple
|
|
339
|
+
* token, so it falls in with the generic files on `--muted`. That IS a change
|
|
340
|
+
* of meaning and is recorded rather than papered over.
|
|
341
|
+
*/
|
|
342
|
+
function getFileIconTone(icon?: string) {
|
|
343
|
+
if (icon === "mdi-file-pdf-box") return "tone-err";
|
|
344
|
+
if (icon === "mdi-file-word-box") return "tone-info";
|
|
352
345
|
if (icon === "mdi-file-excel-box" || icon === "mdi-file-delimited-outline")
|
|
353
|
-
return "
|
|
354
|
-
if (icon === "mdi-file-powerpoint-box") return "
|
|
355
|
-
|
|
356
|
-
return "grey";
|
|
346
|
+
return "tone-ok";
|
|
347
|
+
if (icon === "mdi-file-powerpoint-box") return "tone-warn";
|
|
348
|
+
return "tone-muted";
|
|
357
349
|
}
|
|
358
350
|
|
|
359
351
|
const message = ref("");
|
|
@@ -419,6 +411,13 @@ async function downloadFile({
|
|
|
419
411
|
right: 5%;
|
|
420
412
|
}
|
|
421
413
|
|
|
414
|
+
/**
|
|
415
|
+
* DELIBERATELY NOT `.screen-modal__close`. This close sits ON the picture, not
|
|
416
|
+
* on a card, so the design's borderless muted glyph would be unreadable over a
|
|
417
|
+
* bright photo in light theme and over a dark one in dark theme. The existing
|
|
418
|
+
* dark chip is legible on both, and the handoff draws no media lightbox at all
|
|
419
|
+
* - parity with a readable control wins over a primitive that would disappear.
|
|
420
|
+
*/
|
|
422
421
|
.close-btn {
|
|
423
422
|
position: absolute;
|
|
424
423
|
top: 10px;
|
|
@@ -440,8 +439,29 @@ async function downloadFile({
|
|
|
440
439
|
pointer-events: auto;
|
|
441
440
|
}
|
|
442
441
|
|
|
442
|
+
/* Was `color="primary"`, i.e. the FOREGROUND token used as a fill. The button
|
|
443
|
+
the design fills is `--accent-strong` with `--on-accent-strong` ink. */
|
|
443
444
|
.play-btn {
|
|
444
|
-
border-radius:
|
|
445
|
+
border-radius: var(--r-pill);
|
|
446
|
+
background: var(--accent-strong);
|
|
447
|
+
color: var(--on-accent-strong);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/* The file-type tones, on tokens instead of six hard-coded hexes. */
|
|
451
|
+
.tone-err {
|
|
452
|
+
color: var(--err);
|
|
453
|
+
}
|
|
454
|
+
.tone-info {
|
|
455
|
+
color: var(--info);
|
|
456
|
+
}
|
|
457
|
+
.tone-ok {
|
|
458
|
+
color: var(--ok);
|
|
459
|
+
}
|
|
460
|
+
.tone-warn {
|
|
461
|
+
color: var(--warn);
|
|
462
|
+
}
|
|
463
|
+
.tone-muted {
|
|
464
|
+
color: var(--muted);
|
|
445
465
|
}
|
|
446
466
|
|
|
447
467
|
.dialog-video-container {
|
|
@@ -1,36 +1,32 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<v-card class="mb-2 pa-4
|
|
2
|
+
<v-card class="chat-bubble screen-card mb-2 pa-4" width="400" elevation="0">
|
|
3
3
|
<v-row no-gutters align="center">
|
|
4
4
|
<v-col cols="auto" class="mr-3">
|
|
5
|
-
<v-avatar
|
|
5
|
+
<v-avatar class="chat-bubble__avatar" size="35">
|
|
6
6
|
<v-img v-if="currentUser?.profile" width="15" height="15" />
|
|
7
|
-
<span v-else
|
|
7
|
+
<span v-else>{{ getNameInitials(senderName) }}</span>
|
|
8
8
|
</v-avatar>
|
|
9
9
|
</v-col>
|
|
10
10
|
|
|
11
11
|
<v-col class="d-flex flex-column">
|
|
12
|
-
<span class="
|
|
13
|
-
<span class="
|
|
12
|
+
<span class="chat-bubble__sender">{{ senderName }}</span>
|
|
13
|
+
<span class="chat-bubble__sub">{{ role }}</span>
|
|
14
14
|
</v-col>
|
|
15
15
|
</v-row>
|
|
16
16
|
|
|
17
17
|
<v-row no-gutters class="mt-1">
|
|
18
18
|
<v-col>
|
|
19
|
-
<span class="py-2">{{ message }}</span>
|
|
19
|
+
<span class="chat-bubble__text py-2">{{ message }}</span>
|
|
20
20
|
|
|
21
21
|
<v-row no-gutters justify="space-between" align="center" class="mt-1">
|
|
22
22
|
<v-col cols="auto">
|
|
23
|
-
<span class="
|
|
23
|
+
<span class="chat-bubble__sub">{{ timestamp }}</span>
|
|
24
24
|
</v-col>
|
|
25
|
-
<v-col
|
|
26
|
-
v-
|
|
27
|
-
cols="auto"
|
|
28
|
-
class="d-flex align-center bg-grey-200"
|
|
29
|
-
>
|
|
30
|
-
<v-icon size="16" class="mr-1 text--secondary"
|
|
25
|
+
<v-col v-if="isCurrentUser" cols="auto" class="d-flex align-center">
|
|
26
|
+
<v-icon size="16" class="chat-bubble__sub mr-1"
|
|
31
27
|
>mdi-eye-outline</v-icon
|
|
32
28
|
>
|
|
33
|
-
<span class="
|
|
29
|
+
<span class="chat-bubble__sub">{{ seenLabel }}</span>
|
|
34
30
|
</v-col>
|
|
35
31
|
</v-row>
|
|
36
32
|
</v-col>
|
|
@@ -51,3 +47,36 @@ defineProps<{
|
|
|
51
47
|
const { currentUser } = useLocalAuth();
|
|
52
48
|
const { getNameInitials } = useUtils();
|
|
53
49
|
</script>
|
|
50
|
+
|
|
51
|
+
<style scoped>
|
|
52
|
+
.chat-bubble {
|
|
53
|
+
font-family: var(--font-sans);
|
|
54
|
+
color: var(--text);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/* Was `color="surface-variant"` with the initials at `text-h5`, i.e. a 24px
|
|
58
|
+
pair of letters in a 35px circle. The design's avatar is the tone wash with
|
|
59
|
+
the accent ink, and the initials fit inside it. */
|
|
60
|
+
.chat-bubble__avatar {
|
|
61
|
+
background: var(--hover);
|
|
62
|
+
color: var(--text2);
|
|
63
|
+
font-size: 13px;
|
|
64
|
+
font-weight: 700;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.chat-bubble__sender {
|
|
68
|
+
font-size: var(--fs-cell);
|
|
69
|
+
font-weight: 600;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.chat-bubble__text {
|
|
73
|
+
font-size: var(--fs-cell);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/* The role, the timestamp and the seen label were `text-grey`, `text-caption`
|
|
77
|
+
and `text--secondary` - three different greys for one sub-line. One tone. */
|
|
78
|
+
.chat-bubble__sub {
|
|
79
|
+
font-size: var(--fs-chip);
|
|
80
|
+
color: var(--muted);
|
|
81
|
+
}
|
|
82
|
+
</style>
|
|
@@ -1,21 +1,16 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<v-sheet
|
|
3
|
-
elevation="
|
|
3
|
+
elevation="0"
|
|
4
4
|
rounded="0"
|
|
5
|
-
class="fill-height d-flex flex-column"
|
|
6
|
-
style="border-right: 1px solid #e0e0e0; border-top: 1px solid #e0e0e0"
|
|
5
|
+
class="chat-info fill-height d-flex flex-column"
|
|
7
6
|
>
|
|
8
7
|
<v-row class="pa-4">
|
|
9
8
|
<v-sheet
|
|
10
9
|
class="overflow-y-auto flex-grow-1"
|
|
11
10
|
:style="{ height: 'calc(100vh - 250px)', overflowX: 'hidden' }"
|
|
12
11
|
>
|
|
13
|
-
<v-col
|
|
14
|
-
|
|
15
|
-
class="mb-2"
|
|
16
|
-
style="position: sticky; top: 0; background-color: white; z-index: 1"
|
|
17
|
-
>
|
|
18
|
-
<h3 class="text-h6">
|
|
12
|
+
<v-col cols="12" class="chat-info__head mb-2">
|
|
13
|
+
<h3 class="screen-card-title">
|
|
19
14
|
{{ type === "workOrder" ? "Work Order" : "Feedback" }} Information
|
|
20
15
|
</h3>
|
|
21
16
|
</v-col>
|
|
@@ -105,7 +100,7 @@
|
|
|
105
100
|
</v-col>
|
|
106
101
|
<v-col v-else cols="6" class="py-1 text-right">
|
|
107
102
|
<v-btn
|
|
108
|
-
class="
|
|
103
|
+
class="chat-info__link text-none"
|
|
109
104
|
rounded="pill"
|
|
110
105
|
variant="flat"
|
|
111
106
|
size="small"
|
|
@@ -130,13 +125,7 @@
|
|
|
130
125
|
<v-row dense class="my-1">
|
|
131
126
|
<v-col cols="6" class="py-1"><strong>Status:</strong></v-col>
|
|
132
127
|
<v-col cols="6" class="py-1 text-right">
|
|
133
|
-
<
|
|
134
|
-
:color="getColorStatus(item.status)"
|
|
135
|
-
size="x-small"
|
|
136
|
-
text-color="white"
|
|
137
|
-
>
|
|
138
|
-
{{ item.status }}
|
|
139
|
-
</v-chip>
|
|
128
|
+
<StatusChip :status="item.status" />
|
|
140
129
|
</v-col>
|
|
141
130
|
</v-row>
|
|
142
131
|
|
|
@@ -152,12 +141,11 @@
|
|
|
152
141
|
</v-sheet>
|
|
153
142
|
</v-row>
|
|
154
143
|
|
|
155
|
-
<v-sheet class="px-4 py-2">
|
|
144
|
+
<v-sheet class="chat-info__actions px-4 py-2">
|
|
156
145
|
<v-btn
|
|
157
146
|
block
|
|
158
|
-
color="primary"
|
|
159
147
|
variant="flat"
|
|
160
|
-
class="mb-2
|
|
148
|
+
class="screen-btn-primary mb-2"
|
|
161
149
|
@click="$emit('edit')"
|
|
162
150
|
>
|
|
163
151
|
Edit
|
|
@@ -165,23 +153,15 @@
|
|
|
165
153
|
<v-btn
|
|
166
154
|
v-if="item?.status !== 'Completed'"
|
|
167
155
|
block
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
class="mb-2 text-capitalize"
|
|
156
|
+
variant="flat"
|
|
157
|
+
class="screen-btn-primary mb-2"
|
|
171
158
|
@click="$emit('mark-complete-request')"
|
|
172
159
|
>
|
|
173
160
|
Mark as Complete
|
|
174
161
|
</v-btn>
|
|
175
|
-
<
|
|
176
|
-
block
|
|
177
|
-
variant="flat"
|
|
178
|
-
color="red"
|
|
179
|
-
density="default"
|
|
180
|
-
class="text-white text-capitalize"
|
|
181
|
-
@click="$emit('delete')"
|
|
182
|
-
>
|
|
162
|
+
<AppButton variant="err" class="chat-info__delete" @click="$emit('delete')">
|
|
183
163
|
Delete
|
|
184
|
-
</
|
|
164
|
+
</AppButton>
|
|
185
165
|
</v-sheet>
|
|
186
166
|
|
|
187
167
|
<WorkOrderCreate
|
|
@@ -414,3 +394,40 @@ function showWorkOrderInfo(workOrderId: string) {
|
|
|
414
394
|
};
|
|
415
395
|
}
|
|
416
396
|
</script>
|
|
397
|
+
|
|
398
|
+
<style scoped>
|
|
399
|
+
/* The same two hard-coded #e0e0e0 hairlines the other two chat panels carried,
|
|
400
|
+
and a sticky heading whose background was the literal word `white` - i.e. a
|
|
401
|
+
white bar across the dark theme. */
|
|
402
|
+
.chat-info {
|
|
403
|
+
background: var(--card);
|
|
404
|
+
border-right: 1px solid var(--border);
|
|
405
|
+
border-top: 1px solid var(--border);
|
|
406
|
+
font-family: var(--font-sans);
|
|
407
|
+
color: var(--text);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
.chat-info__head {
|
|
411
|
+
position: sticky;
|
|
412
|
+
top: 0;
|
|
413
|
+
z-index: 1;
|
|
414
|
+
background: var(--card);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
.chat-info__actions {
|
|
418
|
+
background: var(--card);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/* AppButton is a <button>, not a v-btn, so `block` does not reach it. */
|
|
422
|
+
.chat-info__delete {
|
|
423
|
+
width: 100%;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/* Was `text-blue` - a Vuetify palette word, not a token. */
|
|
427
|
+
.chat-info__link {
|
|
428
|
+
background: transparent;
|
|
429
|
+
color: var(--accent-text);
|
|
430
|
+
font-size: var(--fs-btn);
|
|
431
|
+
font-weight: var(--fw-btn-strong);
|
|
432
|
+
}
|
|
433
|
+
</style>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<v-card class="mb-2 pa-2
|
|
2
|
+
<v-card class="chat-listcard screen-card mb-2 pa-2" elevation="0">
|
|
3
3
|
<v-row no-gutters align="center">
|
|
4
4
|
<v-col cols="12" sm="4" class="d-flex justify-center align-center">
|
|
5
5
|
<v-img
|
|
@@ -15,30 +15,30 @@
|
|
|
15
15
|
<v-col cols="12" sm="8" class="py-2 pe-1">
|
|
16
16
|
<v-row dense>
|
|
17
17
|
<v-col cols="12" class="d-flex align-center flex-wrap">
|
|
18
|
-
<span class="
|
|
18
|
+
<span class="chat-listcard__label me-1">Created by</span>
|
|
19
19
|
|
|
20
|
-
<v-avatar
|
|
20
|
+
<v-avatar class="chat-listcard__avatar me-1" size="20">
|
|
21
21
|
<v-img
|
|
22
22
|
v-if="userProfile"
|
|
23
23
|
:src="userProfile"
|
|
24
24
|
width="20"
|
|
25
25
|
height="20"
|
|
26
26
|
/>
|
|
27
|
-
<span v-else class="
|
|
27
|
+
<span v-else class="chat-listcard__initials">
|
|
28
28
|
{{ getNameInitials }}
|
|
29
29
|
</span>
|
|
30
30
|
</v-avatar>
|
|
31
31
|
|
|
32
|
-
<span class="
|
|
32
|
+
<span class="chat-listcard__cell">{{ createdByName || "Unknown" }}</span>
|
|
33
33
|
</v-col>
|
|
34
34
|
|
|
35
|
-
<v-col cols="12" class="
|
|
35
|
+
<v-col cols="12" class="chat-listcard__cell">Subject: {{ subject }}</v-col>
|
|
36
36
|
|
|
37
|
-
<v-col cols="12" class="
|
|
38
|
-
Status: <
|
|
37
|
+
<v-col cols="12" class="chat-listcard__cell d-flex align-center ga-1">
|
|
38
|
+
Status: <StatusChip :status="status" />
|
|
39
39
|
</v-col>
|
|
40
40
|
|
|
41
|
-
<v-col cols="12" class="
|
|
41
|
+
<v-col cols="12" class="chat-listcard__cell">
|
|
42
42
|
Date Created: {{ createdAt }}
|
|
43
43
|
</v-col>
|
|
44
44
|
</v-row>
|
|
@@ -60,3 +60,32 @@ defineProps({
|
|
|
60
60
|
getNameInitials: Function,
|
|
61
61
|
});
|
|
62
62
|
</script>
|
|
63
|
+
|
|
64
|
+
<style scoped>
|
|
65
|
+
.chat-listcard {
|
|
66
|
+
font-family: var(--font-sans);
|
|
67
|
+
color: var(--text);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.chat-listcard__cell,
|
|
71
|
+
.chat-listcard__label {
|
|
72
|
+
font-size: var(--fs-cell-dense);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.chat-listcard__label {
|
|
76
|
+
font-weight: 600;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/* Was `color="surface-variant"` with `text-overline` initials - 10px letters
|
|
80
|
+
with 1.6px tracking inside a 20px circle, which drew as one clipped glyph. */
|
|
81
|
+
.chat-listcard__avatar {
|
|
82
|
+
background: var(--hover);
|
|
83
|
+
color: var(--text2);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.chat-listcard__initials {
|
|
87
|
+
font-size: 9px;
|
|
88
|
+
font-weight: 700;
|
|
89
|
+
letter-spacing: 0;
|
|
90
|
+
}
|
|
91
|
+
</style>
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<v-sheet
|
|
3
|
-
elevation="
|
|
3
|
+
elevation="0"
|
|
4
4
|
rounded="0"
|
|
5
|
-
class="fill-height d-flex flex-column"
|
|
6
|
-
style="border-right: 1px solid #e0e0e0; border-top: 1px solid #e0e0e0"
|
|
5
|
+
class="chat-panel fill-height d-flex flex-column"
|
|
7
6
|
>
|
|
8
|
-
<div
|
|
9
|
-
<h3 class="
|
|
7
|
+
<div class="chat-panel__head px-4 pt-4 pb-2 mb-2">
|
|
8
|
+
<h3 class="screen-card-title">
|
|
10
9
|
{{ type === "workOrder" ? "Work Order" : "Feedback" }} Chat
|
|
11
10
|
</h3>
|
|
12
11
|
</div>
|
|
13
12
|
|
|
14
13
|
<v-sheet
|
|
15
|
-
class="overflow-y-auto flex-grow-1 pa-3"
|
|
14
|
+
class="chat-panel__thread overflow-y-auto flex-grow-1 pa-3"
|
|
16
15
|
:style="{ height: 'calc(100vh - 300px)', overflowX: 'hidden' }"
|
|
17
16
|
>
|
|
18
17
|
<v-row
|
|
@@ -35,10 +34,11 @@
|
|
|
35
34
|
</v-row>
|
|
36
35
|
</v-sheet>
|
|
37
36
|
|
|
38
|
-
<v-card class="mx-4 mb-4 mt-2 pa-3
|
|
37
|
+
<v-card class="screen-card mx-4 mb-4 mt-2 pa-3" elevation="0">
|
|
39
38
|
<v-row no-gutters align="end">
|
|
40
39
|
<v-col cols="10">
|
|
41
40
|
<v-textarea
|
|
41
|
+
class="filter-field"
|
|
42
42
|
label="Message"
|
|
43
43
|
auto-grow
|
|
44
44
|
hide-details
|
|
@@ -47,9 +47,7 @@
|
|
|
47
47
|
/>
|
|
48
48
|
</v-col>
|
|
49
49
|
<v-col cols="2" class="pl-2">
|
|
50
|
-
<v-btn
|
|
51
|
-
>Send</v-btn
|
|
52
|
-
>
|
|
50
|
+
<v-btn class="screen-btn-primary" variant="flat" block>Send</v-btn>
|
|
53
51
|
</v-col>
|
|
54
52
|
</v-row>
|
|
55
53
|
|
|
@@ -57,23 +55,27 @@
|
|
|
57
55
|
|
|
58
56
|
<v-row justify="start" no-gutters align="center">
|
|
59
57
|
<v-col cols="auto">
|
|
60
|
-
<v-icon size="20" class="mr-3">mdi-paperclip</v-icon>
|
|
58
|
+
<v-icon size="20" class="chat-panel__tool mr-3">mdi-paperclip</v-icon>
|
|
61
59
|
</v-col>
|
|
62
60
|
|
|
63
61
|
<v-col cols="auto">
|
|
64
|
-
<v-icon size="20" class="mr-3"
|
|
62
|
+
<v-icon size="20" class="chat-panel__tool mr-3"
|
|
63
|
+
>mdi-emoticon-happy-outline</v-icon
|
|
64
|
+
>
|
|
65
65
|
</v-col>
|
|
66
66
|
|
|
67
67
|
<v-col cols="auto">
|
|
68
68
|
<v-menu location="top" offset="10">
|
|
69
69
|
<template #activator="{ props }">
|
|
70
70
|
<v-btn icon v-bind="props" density="compact" variant="text">
|
|
71
|
-
<v-icon size="20"
|
|
71
|
+
<v-icon size="20" class="chat-panel__tool"
|
|
72
|
+
>mdi-message-outline</v-icon
|
|
73
|
+
>
|
|
72
74
|
</v-btn>
|
|
73
75
|
</template>
|
|
74
76
|
|
|
75
|
-
<v-card min-width="350" class="
|
|
76
|
-
<v-card-title class="
|
|
77
|
+
<v-card min-width="350" class="screen-card">
|
|
78
|
+
<v-card-title class="screen-card-title pb-1"
|
|
77
79
|
>Quick Chat</v-card-title
|
|
78
80
|
>
|
|
79
81
|
<v-divider class="mb-1" />
|
|
@@ -156,3 +158,27 @@ const selectQuickChat = (msg: string) => {
|
|
|
156
158
|
console.log("Quick Chat Selected:", msg);
|
|
157
159
|
};
|
|
158
160
|
</script>
|
|
161
|
+
|
|
162
|
+
<style scoped>
|
|
163
|
+
/* The panel's two rules were hard-coded `1px solid #e0e0e0`, which is a light-
|
|
164
|
+
theme hairline drawn on the dark theme as well. Same lines, on `--border`. */
|
|
165
|
+
.chat-panel {
|
|
166
|
+
background: var(--card);
|
|
167
|
+
border-right: 1px solid var(--border);
|
|
168
|
+
border-top: 1px solid var(--border);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.chat-panel__head {
|
|
172
|
+
border-bottom: 1px solid var(--border);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.chat-panel__thread {
|
|
176
|
+
background: var(--bg);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/* Was a bare icon and one `color="gray"` - not a token, and not the same tone
|
|
180
|
+
as the icon beside it. */
|
|
181
|
+
.chat-panel__tool {
|
|
182
|
+
color: var(--muted);
|
|
183
|
+
}
|
|
184
|
+
</style>
|
|
@@ -1,31 +1,24 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<v-sheet
|
|
3
|
-
|
|
4
|
-
rounded="0"
|
|
5
|
-
class="pa-4 fill-height"
|
|
6
|
-
style="border-right: 1px solid #e0e0e0; border-top: 1px solid #e0e0e0"
|
|
7
|
-
>
|
|
8
|
-
<h3 class="text-h6 mb-4">{{ title }}</h3>
|
|
2
|
+
<v-sheet elevation="0" rounded="0" class="chat-nav pa-4 fill-height">
|
|
3
|
+
<h3 class="screen-card-title mb-4">{{ title }}</h3>
|
|
9
4
|
|
|
10
5
|
<v-text-field
|
|
11
6
|
v-model="search"
|
|
12
7
|
@input="_search"
|
|
13
8
|
label="Search"
|
|
14
9
|
prepend-inner-icon="mdi-magnify"
|
|
15
|
-
density="compact"
|
|
16
10
|
hide-details
|
|
17
11
|
variant="outlined"
|
|
18
|
-
class="mb-4"
|
|
12
|
+
class="filter-field mb-4"
|
|
19
13
|
/>
|
|
20
14
|
|
|
21
15
|
<v-select
|
|
22
16
|
label="Filter by Status"
|
|
23
17
|
:items="['All', 'In Progress', 'To Do', 'Done']"
|
|
24
18
|
v-model="selectedStatus"
|
|
25
|
-
density="compact"
|
|
26
19
|
hide-details
|
|
27
20
|
variant="outlined"
|
|
28
|
-
class="mb-4"
|
|
21
|
+
class="filter-field mb-4"
|
|
29
22
|
/>
|
|
30
23
|
|
|
31
24
|
<v-row dense class="mb-4" align="center">
|
|
@@ -43,7 +36,7 @@
|
|
|
43
36
|
v-bind="props"
|
|
44
37
|
v-model="startDate"
|
|
45
38
|
label="Start Date"
|
|
46
|
-
|
|
39
|
+
class="filter-field"
|
|
47
40
|
variant="outlined"
|
|
48
41
|
readonly
|
|
49
42
|
hide-details
|
|
@@ -63,7 +56,7 @@
|
|
|
63
56
|
</v-col>
|
|
64
57
|
|
|
65
58
|
<v-col cols="2" class="d-flex align-center justify-center">
|
|
66
|
-
<span class="
|
|
59
|
+
<span class="chat-nav__to">to</span>
|
|
67
60
|
</v-col>
|
|
68
61
|
|
|
69
62
|
<v-col cols="5">
|
|
@@ -80,7 +73,7 @@
|
|
|
80
73
|
v-bind="props"
|
|
81
74
|
v-model="endDate"
|
|
82
75
|
label="End Date"
|
|
83
|
-
|
|
76
|
+
class="filter-field"
|
|
84
77
|
variant="outlined"
|
|
85
78
|
readonly
|
|
86
79
|
hide-details
|
|
@@ -101,7 +94,7 @@
|
|
|
101
94
|
</v-row>
|
|
102
95
|
|
|
103
96
|
<v-sheet
|
|
104
|
-
class="overflow-y-auto flex-grow-1 pa-3"
|
|
97
|
+
class="chat-nav__list overflow-y-auto flex-grow-1 pa-3"
|
|
105
98
|
:style="{ height: 'calc(100vh - 320px)', overflowX: 'hidden' }"
|
|
106
99
|
>
|
|
107
100
|
<v-row dense>
|
|
@@ -148,3 +141,22 @@ function _search() {
|
|
|
148
141
|
emit("search", search.value);
|
|
149
142
|
}
|
|
150
143
|
</script>
|
|
144
|
+
|
|
145
|
+
<style scoped>
|
|
146
|
+
/* Same two hard-coded #e0e0e0 hairlines the chat panel carried, on --border. */
|
|
147
|
+
.chat-nav {
|
|
148
|
+
background: var(--card);
|
|
149
|
+
border-right: 1px solid var(--border);
|
|
150
|
+
border-top: 1px solid var(--border);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.chat-nav__list {
|
|
154
|
+
background: var(--bg);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.chat-nav__to {
|
|
158
|
+
font-family: var(--font-sans);
|
|
159
|
+
font-size: var(--fs-cell);
|
|
160
|
+
color: var(--muted);
|
|
161
|
+
}
|
|
162
|
+
</style>
|
package/components/DrawImage.vue
CHANGED
|
@@ -4,32 +4,25 @@
|
|
|
4
4
|
transition="dialog-top-transition"
|
|
5
5
|
max-width="1000"
|
|
6
6
|
>
|
|
7
|
-
<v-card class="
|
|
8
|
-
<
|
|
9
|
-
<v-spacer></v-spacer>
|
|
10
|
-
<v-btn icon="mdi-close" @click="emit('onCloseDialog')" />
|
|
11
|
-
</v-toolbar>
|
|
12
|
-
<canvas id="imageCanvas" />
|
|
13
|
-
<v-card-title class="text-end">
|
|
7
|
+
<v-card class="screen-modal">
|
|
8
|
+
<div class="draw-image__head">
|
|
14
9
|
<v-btn
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
@click="
|
|
20
|
-
|
|
10
|
+
class="screen-modal__close"
|
|
11
|
+
variant="text"
|
|
12
|
+
icon="mdi-close"
|
|
13
|
+
aria-label="Close"
|
|
14
|
+
@click="emit('onCloseDialog')"
|
|
15
|
+
/>
|
|
16
|
+
</div>
|
|
17
|
+
<canvas id="imageCanvas" />
|
|
18
|
+
<div class="screen-modal__footer">
|
|
19
|
+
<v-btn class="screen-btn-ghost" variant="outlined" @click="onClearDrawing()">
|
|
21
20
|
Clear Drawing
|
|
22
21
|
</v-btn>
|
|
23
|
-
<v-btn
|
|
24
|
-
color="blue-darken-3"
|
|
25
|
-
size="small"
|
|
26
|
-
variant="flat"
|
|
27
|
-
style="height: 40px"
|
|
28
|
-
@click="submit"
|
|
29
|
-
>
|
|
22
|
+
<v-btn class="screen-btn-primary" variant="flat" @click="submit">
|
|
30
23
|
Submit
|
|
31
24
|
</v-btn>
|
|
32
|
-
</
|
|
25
|
+
</div>
|
|
33
26
|
</v-card>
|
|
34
27
|
</v-dialog>
|
|
35
28
|
</template>
|
|
@@ -170,3 +163,18 @@ async function onClearDrawing() {
|
|
|
170
163
|
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
|
|
171
164
|
}
|
|
172
165
|
</script>
|
|
166
|
+
|
|
167
|
+
<style scoped>
|
|
168
|
+
/* The design's modal has a title row; this dialog has never had a title, only
|
|
169
|
+
a close - so the row keeps that and just moves the close onto the design's
|
|
170
|
+
borderless 32px square. No copy invented. */
|
|
171
|
+
.draw-image__head {
|
|
172
|
+
display: flex;
|
|
173
|
+
justify-content: flex-end;
|
|
174
|
+
padding: 12px 12px 0;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/* The canvas itself is untouched: its width/height are computed in script from
|
|
178
|
+
its own bounding box, so a layout rule here would quietly move the drawing
|
|
179
|
+
coordinates - a behaviour change no render can prove. */
|
|
180
|
+
</style>
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
v-model="month"
|
|
14
14
|
:items="props.months"
|
|
15
15
|
label="Month"
|
|
16
|
+
class="filter-field"
|
|
16
17
|
density="comfortable"
|
|
17
18
|
:name="props.name + 'custom-input-date-month'"
|
|
18
19
|
hide-details
|
|
@@ -28,6 +29,7 @@
|
|
|
28
29
|
label="Day"
|
|
29
30
|
hide-details
|
|
30
31
|
placeholder="DD"
|
|
32
|
+
class="filter-field"
|
|
31
33
|
density="comfortable"
|
|
32
34
|
:name="props.name + 'custom-input-date-day'"
|
|
33
35
|
:error="!!validationErrMsg"
|
|
@@ -42,6 +44,7 @@
|
|
|
42
44
|
label="Year"
|
|
43
45
|
hide-details
|
|
44
46
|
placeholder="YYYY"
|
|
47
|
+
class="filter-field"
|
|
45
48
|
density="comfortable"
|
|
46
49
|
:name="props.name + 'custom-input-date-year'"
|
|
47
50
|
:error="!!validationErrMsg"
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"
|
|
12
12
|
>
|
|
13
13
|
<div
|
|
14
|
-
class="d-flex align-center justify-center pa-4
|
|
14
|
+
class="file-drop d-flex align-center justify-center pa-4"
|
|
15
15
|
@dragover.prevent
|
|
16
16
|
@drop="handleDrop"
|
|
17
17
|
style="position: relative; z-index: 1"
|
|
@@ -35,12 +35,10 @@
|
|
|
35
35
|
class="d-flex align-center"
|
|
36
36
|
style="z-index: 1; pointer-events: none"
|
|
37
37
|
>
|
|
38
|
-
<v-icon size="28" class="mr-2"
|
|
38
|
+
<v-icon size="28" class="file-drop__icon mr-2"
|
|
39
39
|
>mdi-cloud-upload-outline</v-icon
|
|
40
40
|
>
|
|
41
|
-
<span class="
|
|
42
|
-
>Drag and drop files here</span
|
|
43
|
-
>
|
|
41
|
+
<span class="file-drop__hint">Drag and drop files here</span>
|
|
44
42
|
</div>
|
|
45
43
|
</div>
|
|
46
44
|
</v-col>
|
|
@@ -55,11 +53,10 @@
|
|
|
55
53
|
"
|
|
56
54
|
>
|
|
57
55
|
<v-btn
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
width="55"
|
|
61
|
-
height="55"
|
|
56
|
+
class="screen-btn-primary file-camera"
|
|
57
|
+
variant="flat"
|
|
62
58
|
elevation="0"
|
|
59
|
+
aria-label="Take a photo"
|
|
63
60
|
@click="selectAttachment"
|
|
64
61
|
>
|
|
65
62
|
<v-icon size="20">mdi-camera-outline</v-icon>
|
|
@@ -73,7 +70,7 @@
|
|
|
73
70
|
v-for="(file, index) in attachments"
|
|
74
71
|
:key="index"
|
|
75
72
|
cols="12"
|
|
76
|
-
class="d-flex align-center pa-2 mr-2 mb-2
|
|
73
|
+
class="file-row d-flex align-center pa-2 mr-2 mb-2"
|
|
77
74
|
>
|
|
78
75
|
<div class="mr-3">
|
|
79
76
|
<!-- <v-img
|
|
@@ -108,6 +105,8 @@
|
|
|
108
105
|
|
|
109
106
|
<v-icon
|
|
110
107
|
size="small"
|
|
108
|
+
class="file-row__remove"
|
|
109
|
+
aria-label="Remove file"
|
|
111
110
|
@click.stop="$emit('delete', file)"
|
|
112
111
|
v-if="
|
|
113
112
|
props.createdFrom === 'feedback' && props.attachments.length > 0
|
|
@@ -234,3 +233,49 @@ defineExpose({
|
|
|
234
233
|
},
|
|
235
234
|
});
|
|
236
235
|
</script>
|
|
236
|
+
|
|
237
|
+
<style scoped>
|
|
238
|
+
/* The drop zone was `border-dashed border border-grey` with a `primary` glyph -
|
|
239
|
+
`primary` being the FOREGROUND token, used here as an icon colour, and the
|
|
240
|
+
grey a fixed light-theme hairline. */
|
|
241
|
+
.file-drop {
|
|
242
|
+
border: 1px dashed var(--border);
|
|
243
|
+
border-radius: var(--r-inner);
|
|
244
|
+
position: relative;
|
|
245
|
+
z-index: 1;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
.file-drop__icon {
|
|
249
|
+
color: var(--accent-text);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
.file-drop__hint {
|
|
253
|
+
font-family: var(--font-sans);
|
|
254
|
+
font-size: var(--fs-cell);
|
|
255
|
+
font-weight: 600;
|
|
256
|
+
color: var(--text);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/* Was a 55px square. The design's button is 40px, which is what
|
|
260
|
+
.screen-btn-primary carries; this only keeps it square. */
|
|
261
|
+
.file-camera {
|
|
262
|
+
min-width: var(--btn-h) !important;
|
|
263
|
+
width: var(--btn-h);
|
|
264
|
+
padding: 0 !important;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/* Each attachment row was `bg-white border-sm` - a hard white slab drawn on the
|
|
268
|
+
dark theme as well. */
|
|
269
|
+
.file-row {
|
|
270
|
+
background: var(--card);
|
|
271
|
+
border: 1px solid var(--border);
|
|
272
|
+
border-radius: var(--r-inner);
|
|
273
|
+
font-family: var(--font-sans);
|
|
274
|
+
font-size: var(--fs-cell);
|
|
275
|
+
color: var(--text);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
.file-row__remove {
|
|
279
|
+
color: var(--err);
|
|
280
|
+
}
|
|
281
|
+
</style>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<v-input v-bind="attrs">
|
|
3
|
-
<v-card width="100%" v-bind="attrs">
|
|
3
|
+
<v-card class="perm-list screen-card" elevation="0" width="100%" v-bind="attrs">
|
|
4
4
|
<v-list
|
|
5
5
|
v-model:selected="selected"
|
|
6
6
|
lines="two"
|
|
@@ -18,14 +18,14 @@
|
|
|
18
18
|
<v-list-group :value="permissionKey" fluid>
|
|
19
19
|
<template v-slot:activator="{ props }">
|
|
20
20
|
<v-list-item v-bind="props" density="compact">
|
|
21
|
-
<span class="text-capitalize">
|
|
21
|
+
<span class="perm-list__group text-capitalize">
|
|
22
22
|
{{ formatResourceLabel(String(permissionKey)) }}
|
|
23
23
|
</span>
|
|
24
24
|
|
|
25
25
|
<template #prepend>
|
|
26
|
-
<
|
|
26
|
+
<span class="perm-list__count mr-2">
|
|
27
27
|
{{ selectedActionCount(String(permissionKey)) }}
|
|
28
|
-
</
|
|
28
|
+
</span>
|
|
29
29
|
</template>
|
|
30
30
|
</v-list-item>
|
|
31
31
|
</template>
|
|
@@ -34,13 +34,13 @@
|
|
|
34
34
|
<v-divider></v-divider>
|
|
35
35
|
<v-list-item v-if="attrs.readonly" density="compact">
|
|
36
36
|
<template #title class="pl-2">
|
|
37
|
-
<span class="
|
|
37
|
+
<span class="perm-list__title text-capitalize">
|
|
38
38
|
{{ String(itemKey).replace(/-/g, " ") }}
|
|
39
39
|
</span>
|
|
40
40
|
</template>
|
|
41
41
|
|
|
42
42
|
<template #subtitle class="pl-2">
|
|
43
|
-
<span class="
|
|
43
|
+
<span class="perm-list__sub">{{ item.description }}</span>
|
|
44
44
|
</template>
|
|
45
45
|
</v-list-item>
|
|
46
46
|
|
|
@@ -50,13 +50,13 @@
|
|
|
50
50
|
density="compact"
|
|
51
51
|
>
|
|
52
52
|
<template #title class="pl-2">
|
|
53
|
-
<span class="
|
|
53
|
+
<span class="perm-list__title text-capitalize">
|
|
54
54
|
{{ String(itemKey).replace(/-/g, " ") }}
|
|
55
55
|
</span>
|
|
56
56
|
</template>
|
|
57
57
|
|
|
58
58
|
<template #subtitle class="pl-2">
|
|
59
|
-
<span class="
|
|
59
|
+
<span class="perm-list__sub text-capitalize">
|
|
60
60
|
{{ String(item.description).replace(/-/g, " ") }}
|
|
61
61
|
</span>
|
|
62
62
|
</template>
|
|
@@ -101,3 +101,51 @@ const selectedActionCount = (resource: string) => {
|
|
|
101
101
|
.length;
|
|
102
102
|
};
|
|
103
103
|
</script>
|
|
104
|
+
|
|
105
|
+
<style scoped>
|
|
106
|
+
.perm-list {
|
|
107
|
+
font-family: var(--font-sans);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.perm-list__group {
|
|
111
|
+
font-size: var(--fs-cell);
|
|
112
|
+
font-weight: 600;
|
|
113
|
+
color: var(--text);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* The count beside each permission group. The handoff draws no counter here at
|
|
118
|
+
* all, so this is the neutral chip's own geometry - 999px, 12px/700, the tone
|
|
119
|
+
* wash - rather than a new shape: a `v-chip small`, which is what it was, is
|
|
120
|
+
* 24px of Vuetify grey with its own font.
|
|
121
|
+
*/
|
|
122
|
+
.perm-list__count {
|
|
123
|
+
display: inline-flex;
|
|
124
|
+
align-items: center;
|
|
125
|
+
justify-content: center;
|
|
126
|
+
min-width: 24px;
|
|
127
|
+
height: 20px;
|
|
128
|
+
padding: 0 8px;
|
|
129
|
+
border-radius: var(--r-pill);
|
|
130
|
+
background: var(--hover);
|
|
131
|
+
color: var(--text2);
|
|
132
|
+
font-size: var(--fs-chip);
|
|
133
|
+
font-weight: 700;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/* A ticked row was Vuetify's own rgb(224,224,224) slab - a light-theme grey
|
|
137
|
+
painted on the dark theme too. Same emphasis, on the design's hover wash. */
|
|
138
|
+
.perm-list :deep(.v-list-item--active) {
|
|
139
|
+
background: var(--hover);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.perm-list__title {
|
|
143
|
+
font-size: var(--fs-cell);
|
|
144
|
+
color: var(--text);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.perm-list__sub {
|
|
148
|
+
font-size: var(--fs-cell-dense);
|
|
149
|
+
color: var(--muted);
|
|
150
|
+
}
|
|
151
|
+
</style>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<FormDialog v-model="dialog" @close="closeDialog">
|
|
3
3
|
<template #title>
|
|
4
|
-
<span class="
|
|
4
|
+
<span class="screen-card-title pt-1 text-capitalize">
|
|
5
5
|
{{ isEditMode ? "Edit Work Order" : "Create Work Order" }}
|
|
6
6
|
</span>
|
|
7
7
|
</template>
|
|
@@ -24,8 +24,7 @@
|
|
|
24
24
|
item-props
|
|
25
25
|
label="Subject"
|
|
26
26
|
variant="outlined"
|
|
27
|
-
|
|
28
|
-
class="mb-2"
|
|
27
|
+
class="filter-field mb-2"
|
|
29
28
|
:clearable="
|
|
30
29
|
props.createdFrom === 'feedback' && workOrder.subject !== ''
|
|
31
30
|
? false
|
|
@@ -39,7 +38,7 @@
|
|
|
39
38
|
:custom-filter="customFilter"
|
|
40
39
|
:rules="[requiredRule]"
|
|
41
40
|
>
|
|
42
|
-
<template #label> Subject <span class="
|
|
41
|
+
<template #label> Subject <span class="form-required">*</span> </template>
|
|
43
42
|
</v-autocomplete>
|
|
44
43
|
|
|
45
44
|
<v-autocomplete
|
|
@@ -50,8 +49,7 @@
|
|
|
50
49
|
item-props
|
|
51
50
|
label="Category"
|
|
52
51
|
variant="outlined"
|
|
53
|
-
|
|
54
|
-
class="mb-2"
|
|
52
|
+
class="filter-field mb-2"
|
|
55
53
|
:clearable="
|
|
56
54
|
props.createdFrom === 'feedback' && workOrder.category !== ''
|
|
57
55
|
? false
|
|
@@ -64,12 +62,12 @@
|
|
|
64
62
|
"
|
|
65
63
|
:rules="[requiredRule]"
|
|
66
64
|
>
|
|
67
|
-
<template #label> Category <span class="
|
|
65
|
+
<template #label> Category <span class="form-required">*</span> </template>
|
|
68
66
|
</v-autocomplete>
|
|
69
67
|
|
|
70
68
|
<v-checkbox v-model="workOrder.highPriority" density="compact" class="ma-0">
|
|
71
69
|
<template #label>
|
|
72
|
-
<span class="
|
|
70
|
+
<span class="form-check-label">
|
|
73
71
|
Set work order as High Priority (Optional)
|
|
74
72
|
</span>
|
|
75
73
|
</template>
|
|
@@ -98,14 +96,13 @@
|
|
|
98
96
|
<v-autocomplete
|
|
99
97
|
label="Unit"
|
|
100
98
|
variant="outlined"
|
|
101
|
-
|
|
99
|
+
class="filter-field mt-1"
|
|
102
100
|
v-model="workOrder.unit"
|
|
103
101
|
:items="units"
|
|
104
|
-
class="mt-1"
|
|
105
102
|
clearable
|
|
106
103
|
:rules="[requiredRule]"
|
|
107
104
|
>
|
|
108
|
-
<template #label> Unit <span class="
|
|
105
|
+
<template #label> Unit <span class="form-required">*</span> </template>
|
|
109
106
|
</v-autocomplete>
|
|
110
107
|
|
|
111
108
|
<!-- <v-text-field
|
|
@@ -125,23 +122,21 @@
|
|
|
125
122
|
<v-textarea
|
|
126
123
|
label="Work Order Description"
|
|
127
124
|
variant="outlined"
|
|
128
|
-
|
|
125
|
+
class="filter-field mt-1"
|
|
129
126
|
v-model="workOrder.description"
|
|
130
|
-
class="mt-1"
|
|
131
127
|
rows="4"
|
|
132
128
|
clearable
|
|
133
129
|
auto-grow
|
|
134
130
|
:rules="[requiredRule]"
|
|
135
131
|
>
|
|
136
|
-
<template #label> Description <span class="
|
|
132
|
+
<template #label> Description <span class="form-required">*</span> </template>
|
|
137
133
|
</v-textarea>
|
|
138
134
|
|
|
139
135
|
<template #footer>
|
|
140
136
|
<v-btn
|
|
141
|
-
|
|
142
|
-
|
|
137
|
+
class="screen-btn-primary mb-4"
|
|
138
|
+
variant="flat"
|
|
143
139
|
block
|
|
144
|
-
height="40"
|
|
145
140
|
:loading="loading"
|
|
146
141
|
:disabled="loading || !isFormValid"
|
|
147
142
|
@click="submitWorkOrder"
|
|
@@ -282,3 +277,17 @@ const customFilter = (value: string, query: string, item: any) => {
|
|
|
282
277
|
return title.includes(search) || subtitle.includes(search);
|
|
283
278
|
};
|
|
284
279
|
</script>
|
|
280
|
+
|
|
281
|
+
<style scoped>
|
|
282
|
+
/* The required star was `text-red`, a Vuetify palette word rather than the
|
|
283
|
+
design's error token. */
|
|
284
|
+
.form-required {
|
|
285
|
+
color: var(--err);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
.form-check-label {
|
|
289
|
+
font-family: var(--font-sans);
|
|
290
|
+
font-size: var(--fs-cell);
|
|
291
|
+
color: var(--text);
|
|
292
|
+
}
|
|
293
|
+
</style>
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@7365admin1/layer-common",
|
|
3
3
|
"license": "MIT",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "3.2.2-staging.
|
|
5
|
+
"version": "3.2.2-staging.129",
|
|
6
6
|
"author": "7365admin1",
|
|
7
7
|
"main": "./nuxt.config.ts",
|
|
8
8
|
"//files": "What a consumer extending this layer actually loads. Without this npm ships the whole working tree - the changesets, the CI workflows, the render harness in tools/ and any scratch directory that happened to exist at publish time. Nuxt resolves a layer by directory, so every runtime directory below has to stay listed; adding a new top-level runtime directory means adding it here too.",
|