@rkosafo/cai.components 0.0.39 → 0.0.41
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/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/layout/Chat/CategorySelector.svelte +52 -0
- package/dist/layout/Chat/CategorySelector.svelte.d.ts +4 -0
- package/dist/layout/Chat/ChatEntry.svelte +246 -0
- package/dist/layout/Chat/ChatEntry.svelte.d.ts +4 -0
- package/dist/layout/Chat/ChatEntrySkeleton.svelte +81 -0
- package/dist/layout/Chat/ChatEntrySkeleton.svelte.d.ts +4 -0
- package/dist/layout/Chat/ChatHeader.svelte +172 -0
- package/dist/layout/Chat/ChatHeader.svelte.d.ts +4 -0
- package/dist/layout/Chat/ChatInput.svelte +205 -0
- package/dist/layout/Chat/ChatInput.svelte.d.ts +4 -0
- package/dist/layout/Chat/DraggableWindow.svelte +230 -0
- package/dist/layout/Chat/DraggableWindow.svelte.d.ts +28 -0
- package/dist/layout/Chat/PreviewPage.svelte +182 -0
- package/dist/layout/Chat/PreviewPage.svelte.d.ts +4 -0
- package/dist/layout/Chat/RichText.svelte +215 -0
- package/dist/layout/Chat/RichText.svelte.d.ts +4 -0
- package/dist/layout/Chat/index.d.ts +9 -0
- package/dist/layout/Chat/index.js +9 -0
- package/dist/layout/Chat/types.d.ts +139 -0
- package/dist/layout/Chat/types.js +1 -0
- package/dist/ui/datatable/Datatable.svelte +10 -8
- package/dist/utils/index.d.ts +10 -0
- package/dist/utils/index.js +79 -0
- package/package.json +2 -1
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { clickOutsideAction, IconifyIcon } from '../../index.js';
|
|
3
|
+
import type { CommandListType, IMentionableItem, ISlashCommand, RichTextProps } from './index.js';
|
|
4
|
+
|
|
5
|
+
let {
|
|
6
|
+
value = $bindable(''),
|
|
7
|
+
placeholder = 'Type a new message',
|
|
8
|
+
loading = false,
|
|
9
|
+
slashCommands = [],
|
|
10
|
+
mentionableItems = [],
|
|
11
|
+
onMention,
|
|
12
|
+
onSend,
|
|
13
|
+
onSlash
|
|
14
|
+
}: RichTextProps = $props();
|
|
15
|
+
|
|
16
|
+
let showCommandList = $state(false);
|
|
17
|
+
let commandListPosition = $state(0);
|
|
18
|
+
let commandListType = $state<CommandListType>('slash');
|
|
19
|
+
let filteredItems = $state<Array<ISlashCommand | IMentionableItem>>([]);
|
|
20
|
+
let textareaElement = $state<HTMLTextAreaElement | undefined>(undefined);
|
|
21
|
+
let lastTriggerPosition = $state(-1);
|
|
22
|
+
|
|
23
|
+
function onKeyUp(e: KeyboardEvent) {
|
|
24
|
+
if (e.code === 'Enter' && value && !e.shiftKey) {
|
|
25
|
+
if (showCommandList) {
|
|
26
|
+
e.preventDefault();
|
|
27
|
+
selectCommand();
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
onSend?.();
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (showCommandList) {
|
|
35
|
+
if (e.code === 'ArrowUp') {
|
|
36
|
+
e.preventDefault();
|
|
37
|
+
commandListPosition = Math.max(0, commandListPosition - 1);
|
|
38
|
+
} else if (e.code === 'ArrowDown') {
|
|
39
|
+
e.preventDefault();
|
|
40
|
+
commandListPosition = Math.min(filteredItems.length - 1, commandListPosition + 1);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function onKeyDown(e: KeyboardEvent) {
|
|
46
|
+
const cursorPos = textareaElement!.selectionStart;
|
|
47
|
+
const textBeforeCursor = value.substring(0, cursorPos);
|
|
48
|
+
|
|
49
|
+
if (e.key === '/' && !showCommandList) {
|
|
50
|
+
lastTriggerPosition = cursorPos;
|
|
51
|
+
showCommandList = true;
|
|
52
|
+
commandListType = 'slash';
|
|
53
|
+
filteredItems = slashCommands;
|
|
54
|
+
commandListPosition = 0;
|
|
55
|
+
} else if (e.key === '@' && !showCommandList) {
|
|
56
|
+
lastTriggerPosition = cursorPos;
|
|
57
|
+
showCommandList = true;
|
|
58
|
+
commandListType = 'mention';
|
|
59
|
+
filteredItems = mentionableItems;
|
|
60
|
+
commandListPosition = 0;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (e.key === 'Backspace') {
|
|
64
|
+
const textUntilCursor = value.substring(0, cursorPos);
|
|
65
|
+
const lastAtPos = textUntilCursor.lastIndexOf('@');
|
|
66
|
+
|
|
67
|
+
if (lastAtPos !== -1) {
|
|
68
|
+
const textAfterAt = value.substring(lastAtPos);
|
|
69
|
+
const spacePos = textAfterAt.indexOf(' ');
|
|
70
|
+
const mentionText = spacePos === -1 ? textAfterAt : textAfterAt.substring(0, spacePos);
|
|
71
|
+
|
|
72
|
+
const mentionMatch = mentionableItems.find(
|
|
73
|
+
(item) => `@${item.name.replaceAll(' ', '_')}` === mentionText
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
if (mentionMatch && cursorPos > lastAtPos && cursorPos <= lastAtPos + mentionText.length) {
|
|
77
|
+
e.preventDefault();
|
|
78
|
+
|
|
79
|
+
const textBeforeMention = value.substring(0, lastAtPos);
|
|
80
|
+
const textAfterMention = value.substring(lastAtPos + mentionText.length);
|
|
81
|
+
value = textBeforeMention + textAfterMention;
|
|
82
|
+
|
|
83
|
+
setTimeout(() => {
|
|
84
|
+
textareaElement!.setSelectionRange(lastAtPos, lastAtPos);
|
|
85
|
+
});
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (showCommandList && cursorPos <= lastTriggerPosition) {
|
|
91
|
+
showCommandList = false;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (showCommandList) {
|
|
96
|
+
const textAfterTrigger = textBeforeCursor.substring(lastTriggerPosition);
|
|
97
|
+
|
|
98
|
+
if (commandListType === 'slash') {
|
|
99
|
+
filteredItems = slashCommands.filter((cmd) =>
|
|
100
|
+
cmd.cmdK.includes(textAfterTrigger.toLowerCase())
|
|
101
|
+
);
|
|
102
|
+
} else {
|
|
103
|
+
filteredItems = mentionableItems.filter((item) =>
|
|
104
|
+
item.name.toLowerCase().includes(textAfterTrigger.toLowerCase())
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
commandListPosition = Math.min(commandListPosition, filteredItems.length - 1);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function selectCommand() {
|
|
113
|
+
if (filteredItems.length === 0) return;
|
|
114
|
+
|
|
115
|
+
const selectedItem = filteredItems[commandListPosition];
|
|
116
|
+
const cursorPos = textareaElement!.selectionStart;
|
|
117
|
+
const textBeforeTrigger = value.substring(0, lastTriggerPosition);
|
|
118
|
+
const textAfterSelection = value.substring(cursorPos);
|
|
119
|
+
|
|
120
|
+
if (commandListType === 'slash') {
|
|
121
|
+
value = '';
|
|
122
|
+
onSlash?.(selectedItem as ISlashCommand);
|
|
123
|
+
} else {
|
|
124
|
+
value =
|
|
125
|
+
textBeforeTrigger +
|
|
126
|
+
`@${(selectedItem as IMentionableItem).name.replaceAll(' ', '_')}` +
|
|
127
|
+
textAfterSelection;
|
|
128
|
+
onMention?.(selectedItem as IMentionableItem);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const newCursorPos =
|
|
132
|
+
textBeforeTrigger.length +
|
|
133
|
+
(commandListType === 'slash'
|
|
134
|
+
? (selectedItem as ISlashCommand).cmdK.length + 1
|
|
135
|
+
: `@${(selectedItem as IMentionableItem).name.replaceAll(' ', '_')}`.length);
|
|
136
|
+
|
|
137
|
+
setTimeout(() => {
|
|
138
|
+
textareaElement!.setSelectionRange(newCursorPos, newCursorPos);
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
showCommandList = false;
|
|
142
|
+
commandListPosition = 0;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function closeCommandList() {
|
|
146
|
+
showCommandList = false;
|
|
147
|
+
commandListPosition = 0;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function autoExpandTextarea(event: any) {
|
|
151
|
+
event.target.style.height = 'auto';
|
|
152
|
+
event.target.style.height = event.target.scrollHeight + 'px';
|
|
153
|
+
}
|
|
154
|
+
</script>
|
|
155
|
+
|
|
156
|
+
<div class="flex flex-col gap-2" use:clickOutsideAction onclickoutside={closeCommandList}>
|
|
157
|
+
<div class="relative px-2">
|
|
158
|
+
<div class="flex">
|
|
159
|
+
<textarea
|
|
160
|
+
bind:value
|
|
161
|
+
bind:this={textareaElement}
|
|
162
|
+
oninput={autoExpandTextarea}
|
|
163
|
+
onkeyup={onKeyUp}
|
|
164
|
+
onkeydown={onKeyDown}
|
|
165
|
+
rows="1"
|
|
166
|
+
class="mt-1 flex-grow rounded-md bg-transparent p-2 focus:outline-none"
|
|
167
|
+
{placeholder}
|
|
168
|
+
></textarea>
|
|
169
|
+
{#if loading}
|
|
170
|
+
<div class="absolute right-5 pt-4">
|
|
171
|
+
<IconifyIcon icon="svg-spinners:3-dots-move" style="font-size: 20px;" />
|
|
172
|
+
</div>
|
|
173
|
+
{/if}
|
|
174
|
+
</div>
|
|
175
|
+
|
|
176
|
+
{#if showCommandList && filteredItems.length > 0}
|
|
177
|
+
<div
|
|
178
|
+
class="absolute bottom-12 left-2 z-[3500] w-64 rounded-md border border-gray-200 bg-white shadow-lg"
|
|
179
|
+
>
|
|
180
|
+
<ul class="py-1">
|
|
181
|
+
{#each filteredItems as item, index}
|
|
182
|
+
<li
|
|
183
|
+
class="cursor-pointer px-4 py-2 hover:bg-gray-100 {index === commandListPosition
|
|
184
|
+
? 'bg-gray-100'
|
|
185
|
+
: ''}"
|
|
186
|
+
onclick={() => {
|
|
187
|
+
commandListPosition = index;
|
|
188
|
+
selectCommand();
|
|
189
|
+
}}
|
|
190
|
+
>
|
|
191
|
+
{#if commandListType === 'slash'}
|
|
192
|
+
<div class="font-medium text-blue-600">{item?.name}</div>
|
|
193
|
+
<div class="text-xs text-gray-500">{item?.hint}</div>
|
|
194
|
+
{:else}
|
|
195
|
+
<div class="flex items-center gap-2">
|
|
196
|
+
{#if item?.avatar}
|
|
197
|
+
<img src={item?.avatar} alt={item?.name} class="h-6 w-6 rounded-full" />
|
|
198
|
+
{/if}
|
|
199
|
+
<div class="font-medium text-blue-600">{item?.name}</div>
|
|
200
|
+
</div>
|
|
201
|
+
{/if}
|
|
202
|
+
</li>
|
|
203
|
+
{/each}
|
|
204
|
+
</ul>
|
|
205
|
+
</div>
|
|
206
|
+
{/if}
|
|
207
|
+
</div>
|
|
208
|
+
</div>
|
|
209
|
+
|
|
210
|
+
<style>
|
|
211
|
+
textarea {
|
|
212
|
+
resize: none;
|
|
213
|
+
overflow: hidden;
|
|
214
|
+
}
|
|
215
|
+
</style>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from './types.js';
|
|
2
|
+
export { default as ChatEntrySkeleton } from './ChatEntrySkeleton.svelte';
|
|
3
|
+
export { default as ChatHeader } from './ChatHeader.svelte';
|
|
4
|
+
export { default as RichTextEditor } from './RichText.svelte';
|
|
5
|
+
export { default as PreviewPage } from './PreviewPage.svelte';
|
|
6
|
+
export { default as CategorySelector } from './CategorySelector.svelte';
|
|
7
|
+
export { default as DraggableWindow } from './DraggableWindow.svelte';
|
|
8
|
+
export { default as ChatInput } from './ChatInput.svelte';
|
|
9
|
+
export { default as ChatEntry } from './ChatEntry.svelte';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from './types.js';
|
|
2
|
+
export { default as ChatEntrySkeleton } from './ChatEntrySkeleton.svelte';
|
|
3
|
+
export { default as ChatHeader } from './ChatHeader.svelte';
|
|
4
|
+
export { default as RichTextEditor } from './RichText.svelte';
|
|
5
|
+
export { default as PreviewPage } from './PreviewPage.svelte';
|
|
6
|
+
export { default as CategorySelector } from './CategorySelector.svelte';
|
|
7
|
+
export { default as DraggableWindow } from './DraggableWindow.svelte';
|
|
8
|
+
export { default as ChatInput } from './ChatInput.svelte';
|
|
9
|
+
export { default as ChatEntry } from './ChatEntry.svelte';
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
export interface ChatEntrySkeletonProps {
|
|
3
|
+
isMobile?: boolean;
|
|
4
|
+
messageCount?: number;
|
|
5
|
+
}
|
|
6
|
+
export interface ChatHeaderOverflowAction {
|
|
7
|
+
id: string;
|
|
8
|
+
label: string;
|
|
9
|
+
icon?: string;
|
|
10
|
+
}
|
|
11
|
+
export type CaseToggleType = 'follow' | 'unfollow';
|
|
12
|
+
export interface ChatHeaderProps {
|
|
13
|
+
logoUrl?: string;
|
|
14
|
+
caseTitle?: string;
|
|
15
|
+
user?: {
|
|
16
|
+
name: string;
|
|
17
|
+
profileImageUrl?: string;
|
|
18
|
+
initials: string;
|
|
19
|
+
};
|
|
20
|
+
caseTypes?: string;
|
|
21
|
+
assignedTo?: string;
|
|
22
|
+
showAssignedTo?: boolean;
|
|
23
|
+
showFollowCaseButton?: boolean;
|
|
24
|
+
showBackArrow?: boolean;
|
|
25
|
+
overflowActionsList?: ChatHeaderOverflowAction[];
|
|
26
|
+
showOverflowActionButton?: boolean;
|
|
27
|
+
caseStatus?: string;
|
|
28
|
+
isFollowingCase?: boolean;
|
|
29
|
+
showDefaultCaseOveflowActions?: boolean;
|
|
30
|
+
showCloseOverflowAction?: boolean;
|
|
31
|
+
onCloseCase?: () => void;
|
|
32
|
+
onOverflowActionClicked?: (val: ChatHeaderOverflowAction) => void;
|
|
33
|
+
onToggleFollowCase?: (val: CaseToggleType) => void;
|
|
34
|
+
onBackArrowClicked?: () => void;
|
|
35
|
+
leadingWidget?: Snippet;
|
|
36
|
+
trailingWidget?: Snippet;
|
|
37
|
+
caseDetailsWidget?: Snippet;
|
|
38
|
+
}
|
|
39
|
+
export interface ISlashCommand {
|
|
40
|
+
name: string;
|
|
41
|
+
cmdK: string;
|
|
42
|
+
hint: string;
|
|
43
|
+
viewer: string;
|
|
44
|
+
}
|
|
45
|
+
export interface IMentionableItem {
|
|
46
|
+
id: string | number;
|
|
47
|
+
name: string;
|
|
48
|
+
avatar?: string;
|
|
49
|
+
}
|
|
50
|
+
export interface RichTextProps {
|
|
51
|
+
value?: string;
|
|
52
|
+
placeholder?: string;
|
|
53
|
+
loading?: boolean;
|
|
54
|
+
slashCommands?: ISlashCommand[];
|
|
55
|
+
mentionableItems?: IMentionableItem[];
|
|
56
|
+
onSend?: () => void;
|
|
57
|
+
onSlash?: (val: ISlashCommand) => void;
|
|
58
|
+
onMention?: (val: IMentionableItem) => void;
|
|
59
|
+
}
|
|
60
|
+
export type CommandListType = 'slash' | 'mention';
|
|
61
|
+
export interface PreviewPageSrc {
|
|
62
|
+
name: string;
|
|
63
|
+
content: string;
|
|
64
|
+
file: string;
|
|
65
|
+
}
|
|
66
|
+
export interface PreviewPageProps {
|
|
67
|
+
open: boolean;
|
|
68
|
+
fullImage?: boolean;
|
|
69
|
+
showActions?: boolean;
|
|
70
|
+
title: string;
|
|
71
|
+
src?: PreviewPageSrc;
|
|
72
|
+
onGetImage?: (val: PreviewPageSrc) => void;
|
|
73
|
+
}
|
|
74
|
+
export interface ICaseCategory {
|
|
75
|
+
id: number;
|
|
76
|
+
name: string;
|
|
77
|
+
description: string;
|
|
78
|
+
assignedTo: number[];
|
|
79
|
+
visibleTo: number[];
|
|
80
|
+
canClose: number[];
|
|
81
|
+
autoAssign: boolean;
|
|
82
|
+
parentId?: number;
|
|
83
|
+
items?: ICaseCategory[];
|
|
84
|
+
}
|
|
85
|
+
export interface CategorySelectorClicked {
|
|
86
|
+
selected: ICaseCategory;
|
|
87
|
+
list: string[] | null;
|
|
88
|
+
}
|
|
89
|
+
export interface CategorySelectorProps {
|
|
90
|
+
items?: ICaseCategory[];
|
|
91
|
+
options?: ICaseCategory[];
|
|
92
|
+
onClick?: (val: CategorySelectorClicked) => void;
|
|
93
|
+
}
|
|
94
|
+
export interface DraggableWindowProps {
|
|
95
|
+
title: string;
|
|
96
|
+
isOpen: boolean;
|
|
97
|
+
isCollapsed: boolean;
|
|
98
|
+
width?: string;
|
|
99
|
+
height?: string;
|
|
100
|
+
x?: number;
|
|
101
|
+
y?: number;
|
|
102
|
+
minWidth?: string;
|
|
103
|
+
minHeight?: string;
|
|
104
|
+
zIndex?: number;
|
|
105
|
+
onBringToFront?: () => void;
|
|
106
|
+
}
|
|
107
|
+
export interface ChatInputMessage {
|
|
108
|
+
content: string;
|
|
109
|
+
contentType: 'text';
|
|
110
|
+
files: File[];
|
|
111
|
+
mentions: any[];
|
|
112
|
+
}
|
|
113
|
+
export interface ChatInputProps {
|
|
114
|
+
clearMessage?: boolean;
|
|
115
|
+
hideLoad?: boolean;
|
|
116
|
+
slashCommands?: ISlashCommand[];
|
|
117
|
+
mentionableItems?: IMentionableItem[];
|
|
118
|
+
onMessage?: (val: ChatInputMessage) => void;
|
|
119
|
+
onSlash?: (val: ISlashCommand) => void;
|
|
120
|
+
previewPageTitle?: string;
|
|
121
|
+
}
|
|
122
|
+
export interface ChatEntryMessage {
|
|
123
|
+
mine: boolean;
|
|
124
|
+
message: string;
|
|
125
|
+
files?: string[];
|
|
126
|
+
user?: {
|
|
127
|
+
firstName: string;
|
|
128
|
+
id: number | string;
|
|
129
|
+
surname: string;
|
|
130
|
+
otherNames?: string;
|
|
131
|
+
staffNumber?: string;
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
export interface ChatEntryPageProps {
|
|
135
|
+
message: ChatEntryMessage;
|
|
136
|
+
time: string;
|
|
137
|
+
userId: number | string;
|
|
138
|
+
textBorder?: boolean;
|
|
139
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
Select,
|
|
25
25
|
Table,
|
|
26
26
|
TableLoader,
|
|
27
|
+
toast,
|
|
27
28
|
type DatatableProps,
|
|
28
29
|
type IFormChangeProp,
|
|
29
30
|
type TableFilter
|
|
@@ -136,6 +137,7 @@
|
|
|
136
137
|
});
|
|
137
138
|
if (!ret?.success) {
|
|
138
139
|
// showError(ret?.message || 'Failed to load data');
|
|
140
|
+
toast.error(ret?.message || 'Failed to load data');
|
|
139
141
|
return true;
|
|
140
142
|
}
|
|
141
143
|
const xs = ret.data;
|
|
@@ -145,7 +147,7 @@
|
|
|
145
147
|
pageInfo.setHasPrevPage(xs.pageInfo.hasPreviousPage);
|
|
146
148
|
tableData = xs.items;
|
|
147
149
|
} catch (e: any) {
|
|
148
|
-
|
|
150
|
+
toast.error(e.message || e);
|
|
149
151
|
} finally {
|
|
150
152
|
busy = false;
|
|
151
153
|
}
|
|
@@ -285,7 +287,7 @@
|
|
|
285
287
|
? 'Successfully updated record'
|
|
286
288
|
: 'Successfully added record'
|
|
287
289
|
: '';
|
|
288
|
-
|
|
290
|
+
toast.success(ret.message || successMessage);
|
|
289
291
|
allowLoadAfterCreate && (await fetchData(pageNumber, { search: query }));
|
|
290
292
|
|
|
291
293
|
allowDispatchAfterAction &&
|
|
@@ -296,10 +298,10 @@
|
|
|
296
298
|
activeEntry = {};
|
|
297
299
|
closeSideModal();
|
|
298
300
|
} else {
|
|
299
|
-
|
|
301
|
+
toast.error(ret?.message || 'Failed');
|
|
300
302
|
}
|
|
301
|
-
} catch (error) {
|
|
302
|
-
|
|
303
|
+
} catch (error: any) {
|
|
304
|
+
toast.error(error?.message || 'failed');
|
|
303
305
|
} finally {
|
|
304
306
|
isLoading = false;
|
|
305
307
|
}
|
|
@@ -316,14 +318,14 @@
|
|
|
316
318
|
deleteLoading = true;
|
|
317
319
|
const ret = await deleteEntry(id);
|
|
318
320
|
if (!ret?.success) {
|
|
319
|
-
|
|
321
|
+
toast.error(ret?.message || 'Failed to delete');
|
|
320
322
|
return;
|
|
321
323
|
}
|
|
322
|
-
|
|
324
|
+
toast.success(ret.message);
|
|
323
325
|
closeAlert();
|
|
324
326
|
await fetchData(pageNumber, { search: query });
|
|
325
327
|
} catch (error: any) {
|
|
326
|
-
|
|
328
|
+
toast.error(error?.message || error);
|
|
327
329
|
} finally {
|
|
328
330
|
deleteLoading = false;
|
|
329
331
|
}
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { type ClassValue } from 'clsx';
|
|
|
2
2
|
export { default as Popper } from './Popper.svelte';
|
|
3
3
|
export * from './closeButton/index.js';
|
|
4
4
|
export { trapFocus } from './action.js';
|
|
5
|
+
import type { ICaseCategory } from '../index.js';
|
|
5
6
|
export declare function cn(...inputs: ClassValue[]): string;
|
|
6
7
|
export declare function saveToLocalStorage<T>(key: string, data: T): void;
|
|
7
8
|
export declare function loadFromLocalStorage<T>(key: string): T | undefined;
|
|
@@ -11,3 +12,12 @@ export declare const send: (node: any, params: import("svelte/transition").Cross
|
|
|
11
12
|
}) => () => import("svelte/transition").TransitionConfig, receive: (node: any, params: import("svelte/transition").CrossfadeParams & {
|
|
12
13
|
key: any;
|
|
13
14
|
}) => () => import("svelte/transition").TransitionConfig;
|
|
15
|
+
export declare function getInitials(val?: string): string;
|
|
16
|
+
export declare function findTicketCategoryParents(selectedItem: ICaseCategory, data: ICaseCategory[]): string[] | null;
|
|
17
|
+
export declare function formatTicketDate(x: any): string;
|
|
18
|
+
export declare function formatTicketHeader(x: any): string;
|
|
19
|
+
export declare function isImage(path: string): boolean;
|
|
20
|
+
export declare function isPdf(path: string): boolean;
|
|
21
|
+
export declare function isWord(path: string): boolean;
|
|
22
|
+
export declare function isPPT(path: string): boolean;
|
|
23
|
+
export declare function isExcel(path: string): boolean;
|
package/dist/utils/index.js
CHANGED
|
@@ -6,6 +6,7 @@ import { twMerge } from 'tailwind-merge';
|
|
|
6
6
|
export { default as Popper } from './Popper.svelte';
|
|
7
7
|
export * from './closeButton/index.js';
|
|
8
8
|
export { trapFocus } from './action.js';
|
|
9
|
+
import dayjs from 'dayjs';
|
|
9
10
|
export function cn(...inputs) {
|
|
10
11
|
return twMerge(clsx(inputs));
|
|
11
12
|
}
|
|
@@ -50,3 +51,81 @@ export const [send, receive] = crossfade({
|
|
|
50
51
|
};
|
|
51
52
|
}
|
|
52
53
|
});
|
|
54
|
+
export function getInitials(val) {
|
|
55
|
+
if (!val)
|
|
56
|
+
return '';
|
|
57
|
+
return val
|
|
58
|
+
.split(' ')
|
|
59
|
+
.filter((x) => x.length > 1)
|
|
60
|
+
.map((x) => x[0])
|
|
61
|
+
.join('');
|
|
62
|
+
}
|
|
63
|
+
export function findTicketCategoryParents(selectedItem, data) {
|
|
64
|
+
function findParentsRecursive(category, categories) {
|
|
65
|
+
for (const item of categories) {
|
|
66
|
+
if (item === category) {
|
|
67
|
+
return [item.name];
|
|
68
|
+
}
|
|
69
|
+
else if (item.items) {
|
|
70
|
+
const parents = findParentsRecursive(category, item.items);
|
|
71
|
+
if (parents) {
|
|
72
|
+
return [item.name, ...parents];
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
const parentStack = findParentsRecursive(selectedItem, data);
|
|
79
|
+
return parentStack;
|
|
80
|
+
}
|
|
81
|
+
export function formatTicketDate(x) {
|
|
82
|
+
let today = dayjs();
|
|
83
|
+
let date = dayjs(x);
|
|
84
|
+
if (today.isSame(date, 'day')) {
|
|
85
|
+
return date.format('hh:mm a');
|
|
86
|
+
}
|
|
87
|
+
else if (date.add(7, 'day').isSame(today)) {
|
|
88
|
+
return date.format('ddd');
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
return date.format('ddd DD,MM,YYYY');
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
export function formatTicketHeader(x) {
|
|
95
|
+
let today = dayjs();
|
|
96
|
+
let date = dayjs(x);
|
|
97
|
+
// const yesterday = today.subtract(1, 'day');
|
|
98
|
+
const difference = today.diff(date, 'day');
|
|
99
|
+
const isDateInCurrentWeek = today.startOf('week').isSame(date.startOf('week'), 'day');
|
|
100
|
+
// console.log(difference);
|
|
101
|
+
if (today.isSame(date, 'day')) {
|
|
102
|
+
return 'Today';
|
|
103
|
+
}
|
|
104
|
+
else if (difference === 0) {
|
|
105
|
+
return 'Yesterday';
|
|
106
|
+
}
|
|
107
|
+
else if (isDateInCurrentWeek) {
|
|
108
|
+
return date.format('dddd');
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
return date.format('ddd DD,MMM,YYYY');
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
export function isImage(path) {
|
|
115
|
+
return (path?.toLowerCase().includes('jpeg') ||
|
|
116
|
+
path?.toLowerCase().includes('png') ||
|
|
117
|
+
path?.toLowerCase().includes('webq') ||
|
|
118
|
+
path?.toLowerCase().includes('jpg'));
|
|
119
|
+
}
|
|
120
|
+
export function isPdf(path) {
|
|
121
|
+
return path.toLowerCase().endsWith('.pdf');
|
|
122
|
+
}
|
|
123
|
+
export function isWord(path) {
|
|
124
|
+
return path.toLowerCase().includes('docs');
|
|
125
|
+
}
|
|
126
|
+
export function isPPT(path) {
|
|
127
|
+
return path.toLowerCase().includes('pptx');
|
|
128
|
+
}
|
|
129
|
+
export function isExcel(path) {
|
|
130
|
+
return path?.toLowerCase().includes('csv') || path?.toLowerCase().includes('xlsx');
|
|
131
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rkosafo/cai.components",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.41",
|
|
4
4
|
"files": [
|
|
5
5
|
"dist",
|
|
6
6
|
"!dist/**/*.test.*",
|
|
@@ -57,6 +57,7 @@
|
|
|
57
57
|
"cl-editor": "^2.3.0",
|
|
58
58
|
"clsx": "^2.1.1",
|
|
59
59
|
"date-fns": "^4.1.0",
|
|
60
|
+
"dayjs": "^1.11.18",
|
|
60
61
|
"felte": "^1.3.0",
|
|
61
62
|
"iconify-icon": "^3.0.0",
|
|
62
63
|
"keycloak-js": "^26.2.0",
|