@escalated-dev/escalated 0.7.1 → 0.9.0
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/LICENSE +21 -21
- package/README.md +380 -357
- package/package.json +85 -81
- package/src/components/ActiveChatsPanel.vue +246 -246
- package/src/components/AdminDashboard.stories.js +1423 -1423
- package/src/components/AttachmentList.vue +65 -65
- package/src/components/ChatActionBar.vue +226 -226
- package/src/components/ChatBubble.vue +162 -162
- package/src/components/ChatComposer.vue +308 -308
- package/src/components/ChatQueue.vue +222 -222
- package/src/components/ChatThread.vue +197 -197
- package/src/components/CustomTicketActions.stories.js +71 -0
- package/src/components/CustomTicketActions.vue +101 -0
- package/src/components/EscalatedLayout.vue +619 -598
- package/src/components/FollowButton.vue +20 -1
- package/src/components/MentionDropdown.vue +154 -154
- package/src/components/MetricComparison.vue +89 -89
- package/src/components/PercentileChart.vue +67 -67
- package/src/components/PeriodSelector.vue +98 -98
- package/src/components/PresenceIndicator.vue +228 -213
- package/src/components/ReplyComposer.vue +336 -336
- package/src/components/ReplyThread.vue +153 -153
- package/src/components/ReportChart.vue +395 -395
- package/src/components/ReportExportButton.vue +108 -108
- package/src/components/SaveViewDialog.vue +172 -172
- package/src/components/SavedViewSidebar.vue +208 -208
- package/src/components/SkillTagManager.vue +29 -22
- package/src/components/SnoozeButton.vue +247 -247
- package/src/components/TicketFilters.vue +270 -270
- package/src/components/TicketList.vue +655 -655
- package/src/components/TicketSidebar.vue +4 -0
- package/src/components/TicketSplitDialog.vue +98 -98
- package/src/components/TicketSubjects.stories.js +63 -0
- package/src/components/TicketSubjects.vue +107 -0
- package/src/components/TwoFactorSetup.vue +1 -37
- package/src/components/VariableTokenInput.vue +111 -111
- package/src/components/WorkflowActionConfig.vue +287 -287
- package/src/components/WorkflowActionList.vue +350 -350
- package/src/components/WorkflowConditionBuilder.vue +265 -265
- package/src/components/WorkflowTriggerSelector.vue +125 -125
- package/src/components/admin/newsletters/AnalyticsTiles.stories.js +14 -0
- package/src/components/admin/newsletters/AnalyticsTiles.vue +55 -0
- package/src/components/admin/newsletters/DeliveriesTable.stories.js +28 -0
- package/src/components/admin/newsletters/DeliveriesTable.vue +104 -0
- package/src/components/admin/newsletters/DynamicFilterBuilder.stories.js +11 -0
- package/src/components/admin/newsletters/DynamicFilterBuilder.vue +53 -0
- package/src/components/admin/newsletters/ListMemberTable.stories.js +12 -0
- package/src/components/admin/newsletters/ListMemberTable.vue +53 -0
- package/src/components/admin/newsletters/MarkdownEditor.stories.js +6 -0
- package/src/components/admin/newsletters/MarkdownEditor.vue +53 -0
- package/src/components/admin/newsletters/MergeFieldDropdown.stories.js +6 -0
- package/src/components/admin/newsletters/MergeFieldDropdown.vue +84 -0
- package/src/components/admin/newsletters/PreviewIframe.stories.js +7 -0
- package/src/components/admin/newsletters/PreviewIframe.vue +40 -0
- package/src/components/admin/newsletters/SummaryTiles.stories.js +8 -0
- package/src/components/admin/newsletters/SummaryTiles.vue +63 -0
- package/src/composables/useChat.js +187 -187
- package/src/composables/useI18n.js +30 -8
- package/src/composables/useMentions.js +134 -134
- package/src/composables/usePermissions.js +31 -0
- package/src/composables/useRealtime.js +182 -182
- package/src/index.js +85 -84
- package/src/locales/README.md +13 -0
- package/src/locales/ar.json +727 -727
- package/src/locales/de.json +690 -690
- package/src/locales/en.json +889 -729
- package/src/locales/es.json +691 -691
- package/src/locales/fr.json +691 -691
- package/src/locales/index.js +16 -16
- package/src/locales/it.json +727 -727
- package/src/locales/ja.json +727 -727
- package/src/locales/ko.json +727 -727
- package/src/locales/nl.json +727 -727
- package/src/locales/pl.json +727 -727
- package/src/locales/pt-BR.json +727 -727
- package/src/locales/ru.json +727 -727
- package/src/locales/tr.json +727 -727
- package/src/locales/zh-CN.json +727 -727
- package/src/pages/Admin/Newsletters/Compose.vue +192 -0
- package/src/pages/Admin/Newsletters/Edit.vue +24 -0
- package/src/pages/Admin/Newsletters/Index.vue +141 -0
- package/src/pages/Admin/Newsletters/Lists/Create.vue +64 -0
- package/src/pages/Admin/Newsletters/Lists/Index.vue +59 -0
- package/src/pages/Admin/Newsletters/Lists/Show.vue +53 -0
- package/src/pages/Admin/Newsletters/Settings.vue +85 -0
- package/src/pages/Admin/Newsletters/Show.vue +140 -0
- package/src/pages/Admin/Newsletters/Templates/Create.vue +11 -0
- package/src/pages/Admin/Newsletters/Templates/Index.vue +54 -0
- package/src/pages/Admin/Newsletters/Templates/Show.vue +65 -0
- package/src/pages/Admin/Newsletters/usePreview.js +44 -0
- package/src/pages/Admin/Reports/AgentDetail.vue +132 -132
- package/src/pages/Admin/Reports/AgentRanking.vue +246 -246
- package/src/pages/Admin/Reports/Cohorts.vue +180 -180
- package/src/pages/Admin/Reports/Comparison.vue +141 -141
- package/src/pages/Admin/Reports/Dashboard.vue +226 -226
- package/src/pages/Admin/Reports/ResolutionTimes.vue +164 -164
- package/src/pages/Admin/Reports/ResponseTimes.vue +164 -164
- package/src/pages/Admin/Reports/SlaTrends.vue +183 -183
- package/src/pages/Admin/Settings/SsoSettings.vue +157 -4
- package/src/pages/Admin/Settings/TwoFactor.vue +32 -6
- package/src/pages/Admin/Settings.vue +1008 -1008
- package/src/pages/Admin/Skills/Form.vue +164 -4
- package/src/pages/Admin/Skills/Index.vue +14 -3
- package/src/pages/Admin/Tickets/Index.vue +126 -126
- package/src/pages/Admin/Tickets/Show.vue +254 -249
- package/src/pages/Admin/Users/Index.vue +145 -0
- package/src/pages/Admin/Workflows/Builder.vue +207 -207
- package/src/pages/Admin/Workflows/Index.vue +235 -235
- package/src/pages/Admin/Workflows/Logs.vue +286 -286
- package/src/pages/Agent/TicketIndex.vue +112 -112
- package/src/pages/Agent/TicketShow.vue +547 -494
- package/src/pages/Customer/Index.vue +26 -1
- package/src/pages/Customer/KnowledgeBase/Article.vue +129 -129
- package/src/plugin.js +175 -175
- package/src/utils/mentionHighlight.js +24 -24
- package/src/widget/EscalatedWidget.vue +804 -804
- package/src/widget/index.js +254 -254
|
@@ -1,111 +1,111 @@
|
|
|
1
|
-
<script setup>
|
|
2
|
-
import { ref } from 'vue';
|
|
3
|
-
|
|
4
|
-
const props = defineProps({
|
|
5
|
-
modelValue: { type: String, default: '' },
|
|
6
|
-
placeholder: { type: String, default: '' },
|
|
7
|
-
multiline: { type: Boolean, default: false },
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
const emit = defineEmits(['update:modelValue']);
|
|
11
|
-
|
|
12
|
-
const showDropdown = ref(false);
|
|
13
|
-
const inputRef = ref(null);
|
|
14
|
-
|
|
15
|
-
const variables = [
|
|
16
|
-
{ token: '{{ticket.reference}}', label: 'Ticket Reference' },
|
|
17
|
-
{ token: '{{ticket.subject}}', label: 'Ticket Subject' },
|
|
18
|
-
{ token: '{{ticket.status}}', label: 'Ticket Status' },
|
|
19
|
-
{ token: '{{agent.name}}', label: 'Agent Name' },
|
|
20
|
-
{ token: '{{requester.name}}', label: 'Requester Name' },
|
|
21
|
-
{ token: '{{requester.email}}', label: 'Requester Email' },
|
|
22
|
-
{ token: '{{department.name}}', label: 'Department Name' },
|
|
23
|
-
];
|
|
24
|
-
|
|
25
|
-
function insertVariable(token) {
|
|
26
|
-
const el = inputRef.value;
|
|
27
|
-
if (!el) {
|
|
28
|
-
emit('update:modelValue', (props.modelValue || '') + token);
|
|
29
|
-
showDropdown.value = false;
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
const start = el.selectionStart || 0;
|
|
33
|
-
const end = el.selectionEnd || 0;
|
|
34
|
-
const text = props.modelValue || '';
|
|
35
|
-
const newText = text.substring(0, start) + token + text.substring(end);
|
|
36
|
-
emit('update:modelValue', newText);
|
|
37
|
-
showDropdown.value = false;
|
|
38
|
-
// Restore cursor position after Vue updates
|
|
39
|
-
requestAnimationFrame(() => {
|
|
40
|
-
el.focus();
|
|
41
|
-
const pos = start + token.length;
|
|
42
|
-
el.setSelectionRange(pos, pos);
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function onInput(event) {
|
|
47
|
-
emit('update:modelValue', event.target.value);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const inputClass =
|
|
51
|
-
'w-full rounded-lg border border-[var(--esc-panel-border-input)] bg-[var(--esc-panel-surface-alt)] px-3 py-2 text-sm text-[var(--esc-panel-text-secondary)] focus:border-[var(--esc-panel-border-input)] focus:outline-none focus:ring-1 focus:ring-[var(--esc-panel-border-input)]';
|
|
52
|
-
</script>
|
|
53
|
-
|
|
54
|
-
<template>
|
|
55
|
-
<div class="relative">
|
|
56
|
-
<textarea
|
|
57
|
-
v-if="multiline"
|
|
58
|
-
ref="inputRef"
|
|
59
|
-
:value="modelValue"
|
|
60
|
-
:placeholder="placeholder"
|
|
61
|
-
rows="3"
|
|
62
|
-
:class="inputClass + ' resize-y'"
|
|
63
|
-
@input="onInput"
|
|
64
|
-
/>
|
|
65
|
-
<input
|
|
66
|
-
v-else
|
|
67
|
-
ref="inputRef"
|
|
68
|
-
:value="modelValue"
|
|
69
|
-
:placeholder="placeholder"
|
|
70
|
-
type="text"
|
|
71
|
-
:class="inputClass"
|
|
72
|
-
@input="onInput"
|
|
73
|
-
/>
|
|
74
|
-
|
|
75
|
-
<!-- Insert Variable button -->
|
|
76
|
-
<div class="mt-1.5 flex justify-end">
|
|
77
|
-
<div class="relative">
|
|
78
|
-
<button
|
|
79
|
-
type="button"
|
|
80
|
-
class="flex items-center gap-1 rounded-md px-2 py-1 text-[10px] font-medium text-[var(--esc-panel-text-muted)] transition-colors hover:bg-[var(--esc-panel-hover)] hover:text-[var(--esc-panel-text-secondary)]"
|
|
81
|
-
@click="showDropdown = !showDropdown"
|
|
82
|
-
>
|
|
83
|
-
<svg class="h-3 w-3" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
84
|
-
<path
|
|
85
|
-
stroke-linecap="round"
|
|
86
|
-
stroke-linejoin="round"
|
|
87
|
-
d="M17.25 6.75L22.5 12l-5.25 5.25m-10.5 0L1.5 12l5.25-5.25m7.5-3l-4.5 16.5"
|
|
88
|
-
/>
|
|
89
|
-
</svg>
|
|
90
|
-
Insert Variable
|
|
91
|
-
</button>
|
|
92
|
-
<div
|
|
93
|
-
v-if="showDropdown"
|
|
94
|
-
class="absolute right-0 bottom-full z-10 mb-1 w-48 rounded-lg border border-[var(--esc-panel-border)] bg-[var(--esc-panel-surface)] py-1 shadow-xl"
|
|
95
|
-
>
|
|
96
|
-
<button
|
|
97
|
-
v-for="v in variables"
|
|
98
|
-
:key="v.token"
|
|
99
|
-
type="button"
|
|
100
|
-
class="flex w-full items-center gap-2 px-3 py-1.5 text-left text-xs transition-colors hover:bg-[var(--esc-panel-hover)]"
|
|
101
|
-
@click="insertVariable(v.token)"
|
|
102
|
-
>
|
|
103
|
-
<span class="rounded bg-cyan-500/10 px-1.5 py-0.5 font-mono text-[10px] text-cyan-400">{{
|
|
104
|
-
v.token
|
|
105
|
-
}}</span>
|
|
106
|
-
</button>
|
|
107
|
-
</div>
|
|
108
|
-
</div>
|
|
109
|
-
</div>
|
|
110
|
-
</div>
|
|
111
|
-
</template>
|
|
1
|
+
<script setup>
|
|
2
|
+
import { ref } from 'vue';
|
|
3
|
+
|
|
4
|
+
const props = defineProps({
|
|
5
|
+
modelValue: { type: String, default: '' },
|
|
6
|
+
placeholder: { type: String, default: '' },
|
|
7
|
+
multiline: { type: Boolean, default: false },
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
const emit = defineEmits(['update:modelValue']);
|
|
11
|
+
|
|
12
|
+
const showDropdown = ref(false);
|
|
13
|
+
const inputRef = ref(null);
|
|
14
|
+
|
|
15
|
+
const variables = [
|
|
16
|
+
{ token: '{{ticket.reference}}', label: 'Ticket Reference' },
|
|
17
|
+
{ token: '{{ticket.subject}}', label: 'Ticket Subject' },
|
|
18
|
+
{ token: '{{ticket.status}}', label: 'Ticket Status' },
|
|
19
|
+
{ token: '{{agent.name}}', label: 'Agent Name' },
|
|
20
|
+
{ token: '{{requester.name}}', label: 'Requester Name' },
|
|
21
|
+
{ token: '{{requester.email}}', label: 'Requester Email' },
|
|
22
|
+
{ token: '{{department.name}}', label: 'Department Name' },
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
function insertVariable(token) {
|
|
26
|
+
const el = inputRef.value;
|
|
27
|
+
if (!el) {
|
|
28
|
+
emit('update:modelValue', (props.modelValue || '') + token);
|
|
29
|
+
showDropdown.value = false;
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const start = el.selectionStart || 0;
|
|
33
|
+
const end = el.selectionEnd || 0;
|
|
34
|
+
const text = props.modelValue || '';
|
|
35
|
+
const newText = text.substring(0, start) + token + text.substring(end);
|
|
36
|
+
emit('update:modelValue', newText);
|
|
37
|
+
showDropdown.value = false;
|
|
38
|
+
// Restore cursor position after Vue updates
|
|
39
|
+
requestAnimationFrame(() => {
|
|
40
|
+
el.focus();
|
|
41
|
+
const pos = start + token.length;
|
|
42
|
+
el.setSelectionRange(pos, pos);
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function onInput(event) {
|
|
47
|
+
emit('update:modelValue', event.target.value);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const inputClass =
|
|
51
|
+
'w-full rounded-lg border border-[var(--esc-panel-border-input)] bg-[var(--esc-panel-surface-alt)] px-3 py-2 text-sm text-[var(--esc-panel-text-secondary)] focus:border-[var(--esc-panel-border-input)] focus:outline-none focus:ring-1 focus:ring-[var(--esc-panel-border-input)]';
|
|
52
|
+
</script>
|
|
53
|
+
|
|
54
|
+
<template>
|
|
55
|
+
<div class="relative">
|
|
56
|
+
<textarea
|
|
57
|
+
v-if="multiline"
|
|
58
|
+
ref="inputRef"
|
|
59
|
+
:value="modelValue"
|
|
60
|
+
:placeholder="placeholder"
|
|
61
|
+
rows="3"
|
|
62
|
+
:class="inputClass + ' resize-y'"
|
|
63
|
+
@input="onInput"
|
|
64
|
+
/>
|
|
65
|
+
<input
|
|
66
|
+
v-else
|
|
67
|
+
ref="inputRef"
|
|
68
|
+
:value="modelValue"
|
|
69
|
+
:placeholder="placeholder"
|
|
70
|
+
type="text"
|
|
71
|
+
:class="inputClass"
|
|
72
|
+
@input="onInput"
|
|
73
|
+
/>
|
|
74
|
+
|
|
75
|
+
<!-- Insert Variable button -->
|
|
76
|
+
<div class="mt-1.5 flex justify-end">
|
|
77
|
+
<div class="relative">
|
|
78
|
+
<button
|
|
79
|
+
type="button"
|
|
80
|
+
class="flex items-center gap-1 rounded-md px-2 py-1 text-[10px] font-medium text-[var(--esc-panel-text-muted)] transition-colors hover:bg-[var(--esc-panel-hover)] hover:text-[var(--esc-panel-text-secondary)]"
|
|
81
|
+
@click="showDropdown = !showDropdown"
|
|
82
|
+
>
|
|
83
|
+
<svg class="h-3 w-3" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
84
|
+
<path
|
|
85
|
+
stroke-linecap="round"
|
|
86
|
+
stroke-linejoin="round"
|
|
87
|
+
d="M17.25 6.75L22.5 12l-5.25 5.25m-10.5 0L1.5 12l5.25-5.25m7.5-3l-4.5 16.5"
|
|
88
|
+
/>
|
|
89
|
+
</svg>
|
|
90
|
+
Insert Variable
|
|
91
|
+
</button>
|
|
92
|
+
<div
|
|
93
|
+
v-if="showDropdown"
|
|
94
|
+
class="absolute right-0 bottom-full z-10 mb-1 w-48 rounded-lg border border-[var(--esc-panel-border)] bg-[var(--esc-panel-surface)] py-1 shadow-xl"
|
|
95
|
+
>
|
|
96
|
+
<button
|
|
97
|
+
v-for="v in variables"
|
|
98
|
+
:key="v.token"
|
|
99
|
+
type="button"
|
|
100
|
+
class="flex w-full items-center gap-2 px-3 py-1.5 text-left text-xs transition-colors hover:bg-[var(--esc-panel-hover)]"
|
|
101
|
+
@click="insertVariable(v.token)"
|
|
102
|
+
>
|
|
103
|
+
<span class="rounded bg-cyan-500/10 px-1.5 py-0.5 font-mono text-[10px] text-cyan-400">{{
|
|
104
|
+
v.token
|
|
105
|
+
}}</span>
|
|
106
|
+
</button>
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
</div>
|
|
111
|
+
</template>
|