@finema/finework-layer 0.2.140 → 0.2.142
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/CHANGELOG.md +8 -0
- package/app/components/Notifications/index.vue +112 -59
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.2.142](https://gitlab.finema.co/finema/finework/finework-frontend-layer/compare/0.2.141...0.2.142) (2026-02-19)
|
|
4
|
+
|
|
5
|
+
## [0.2.141](https://gitlab.finema.co/finema/finework/finework-frontend-layer/compare/0.2.140...0.2.141) (2026-02-19)
|
|
6
|
+
|
|
7
|
+
### Bug Fixes
|
|
8
|
+
|
|
9
|
+
* improve noti ([cb22978](https://gitlab.finema.co/finema/finework/finework-frontend-layer/commit/cb22978810ab73bdabb21bf0f49c35aaa19ed282))
|
|
10
|
+
|
|
3
11
|
## [0.2.140](https://gitlab.finema.co/finema/finework/finework-frontend-layer/compare/0.2.139...0.2.140) (2026-02-17)
|
|
4
12
|
|
|
5
13
|
### Features
|
|
@@ -31,53 +31,54 @@
|
|
|
31
31
|
v-else
|
|
32
32
|
:loading="notification.fetch.status.isLoading"
|
|
33
33
|
>
|
|
34
|
-
<div
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
<div
|
|
35
|
+
v-for="item in notification.fetch.items"
|
|
36
|
+
:key="item.id"
|
|
37
|
+
>
|
|
38
|
+
<Separator />
|
|
39
|
+
<NuxtLink
|
|
40
|
+
:to="getLink(item)"
|
|
41
|
+
:target="getLink(item) === '#' ? '_self' : '_blank'"
|
|
42
|
+
:class="['flex cursor-pointer items-start gap-2 rounded-lg p-4 hover:bg-gray-100']"
|
|
38
43
|
>
|
|
39
|
-
<
|
|
40
|
-
:to="getLink(item)"
|
|
41
|
-
:target="getLink(item) === '#' ? '_self' : '_blank'"
|
|
42
|
-
:class="['mb-2 flex cursor-pointer items-start gap-2 rounded-lg p-4 hover:bg-gray-100']"
|
|
43
|
-
>
|
|
44
|
-
<Chip
|
|
45
|
-
v-if="getImage(item)"
|
|
44
|
+
<!-- <Chip
|
|
46
45
|
position="bottom-right"
|
|
47
46
|
size="3xl"
|
|
48
47
|
inset
|
|
49
48
|
:color="getNotificationColor(item)"
|
|
50
|
-
>
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
49
|
+
> -->
|
|
50
|
+
<div
|
|
51
|
+
v-if="item.actor?.avatar_url"
|
|
52
|
+
class="relative"
|
|
53
|
+
>
|
|
54
|
+
<Avatar
|
|
55
|
+
class="min-h-12 min-w-12"
|
|
56
|
+
:src="item.actor?.avatar_url"
|
|
57
|
+
:alt="item.actor?.display_name"
|
|
58
|
+
/>
|
|
59
|
+
<img
|
|
60
|
+
:src="getImage(item)!"
|
|
61
|
+
class="absolute -right-1 -bottom-1 w-5 rounded-full bg-white p-0.25"
|
|
62
|
+
/>
|
|
63
|
+
</div>
|
|
64
|
+
<img
|
|
65
|
+
v-else
|
|
66
|
+
:src="getImage(item)!"
|
|
67
|
+
class="h-12 min-h-12 w-12 min-w-12"
|
|
68
|
+
/>
|
|
69
|
+
<!-- </Chip> -->
|
|
70
|
+
|
|
71
|
+
<div class="flex flex-1 flex-col gap-0">
|
|
72
|
+
<p
|
|
73
|
+
class="text-gray line-clamp-2 text-sm"
|
|
74
|
+
v-html="getMessage(item)"
|
|
75
|
+
/>
|
|
76
|
+
<FormatTimeFromNow
|
|
77
|
+
class="text-xs font-medium whitespace-nowrap text-gray-600"
|
|
78
|
+
:value="item.sent_at"
|
|
79
|
+
/>
|
|
80
|
+
</div>
|
|
81
|
+
</NuxtLink>
|
|
81
82
|
</div>
|
|
82
83
|
</Loader>
|
|
83
84
|
</template>
|
|
@@ -101,24 +102,41 @@ onMounted(() => {
|
|
|
101
102
|
})
|
|
102
103
|
|
|
103
104
|
const getLink = (item: INotificationItem) => {
|
|
104
|
-
if (item.data?.url)
|
|
105
|
-
return item.data.url
|
|
106
|
-
}
|
|
105
|
+
if (item.data?.url) return item.data.url
|
|
107
106
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
107
|
+
switch (item.source_type) {
|
|
108
|
+
case 'PMO_PROJECT':
|
|
109
|
+
return `/pmo/projects/${item.source_id}`
|
|
110
|
+
|
|
111
|
+
case 'NEWSLETTER':
|
|
112
|
+
return `/announcement/${item.source_id}`
|
|
113
|
+
|
|
114
|
+
case 'TODO': {
|
|
115
|
+
const boardSlug = item.data?.todo_board_slug
|
|
116
|
+
const cardSlug = item.data?.todo_slug
|
|
117
|
+
|
|
118
|
+
switch (item.action_type) {
|
|
119
|
+
case 'TODO_ASSIGN_CARD':
|
|
120
|
+
case 'TODO_COMMENT_ADD':
|
|
121
|
+
case 'TODO_DUE_DATE_CHANGE':
|
|
122
|
+
case 'TODO_STATUS_CHANGE':
|
|
123
|
+
return `/todo/boards/${boardSlug}/cards/${cardSlug}`
|
|
124
|
+
|
|
125
|
+
case 'TODO_REMOVE_CARD':
|
|
126
|
+
case 'TODO_ASSIGN_BOARD':
|
|
127
|
+
return `/todo/boards/${boardSlug}`
|
|
119
128
|
|
|
120
|
-
|
|
121
|
-
|
|
129
|
+
case 'TODO_REMOVE_BOARD':
|
|
130
|
+
return `/todo/cards`
|
|
131
|
+
|
|
132
|
+
default:
|
|
133
|
+
return '#'
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
default:
|
|
138
|
+
return '#'
|
|
139
|
+
}
|
|
122
140
|
}
|
|
123
141
|
|
|
124
142
|
const getImage = (item: INotificationItem): string | null => {
|
|
@@ -159,7 +177,42 @@ const getNotificationColor = (item: INotificationItem): string => {
|
|
|
159
177
|
}
|
|
160
178
|
|
|
161
179
|
const getMessage = (item: INotificationItem): string => {
|
|
162
|
-
|
|
180
|
+
let message = item.message
|
|
181
|
+
|
|
182
|
+
// ตรวจหาวันที่ในรูปแบบ yyyy-mm-dd และแปลงเป็น text
|
|
183
|
+
const datePattern = /\b(\d{4})-(\d{2})-(\d{2})\b/g
|
|
184
|
+
|
|
185
|
+
message = message.replace(datePattern, (match) => {
|
|
186
|
+
try {
|
|
187
|
+
const date = new Date(match)
|
|
188
|
+
|
|
189
|
+
return TimeHelper.displayDate(date)
|
|
190
|
+
? `<span class="text-primary font-medium"> ${TimeHelper.displayDate(date)}</span>`
|
|
191
|
+
: match
|
|
192
|
+
} catch {
|
|
193
|
+
return match
|
|
194
|
+
}
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
if (item.data) {
|
|
198
|
+
Object.entries(item.data).forEach(([key, value]) => {
|
|
199
|
+
if (key.endsWith('_slug') && typeof value === 'string' && value) {
|
|
200
|
+
// หา slug ในข้อความและครอบด้วย <strong>
|
|
201
|
+
const slugPattern = new RegExp(`\\b${value}\\b`, 'g')
|
|
202
|
+
|
|
203
|
+
message = message.replace(slugPattern, `<span class="text-primary font-medium">${value}</span>`)
|
|
204
|
+
}
|
|
205
|
+
})
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// ตรวจหาคำที่อยู่ระหว่าง "from" และ "to" และทำให้เป็น bold + text-primary font-semibold
|
|
209
|
+
const fromToPattern = /\bfrom\s+(\S+)\s+to\s+(\S+)/gi
|
|
210
|
+
|
|
211
|
+
message = message.replace(fromToPattern, (_match, from, to) => {
|
|
212
|
+
return `from <span class="text-primary font-medium">${from}</span> to <span class="text-primary font-semibold">${to}</span>`
|
|
213
|
+
})
|
|
214
|
+
|
|
215
|
+
return message
|
|
163
216
|
}
|
|
164
217
|
|
|
165
218
|
useWatchTrue(() => markAllRead.status.value.isSuccess, () => {
|