@chat21/chat21-ionic 3.4.29 → 3.4.30-rc2

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.
Files changed (75) hide show
  1. package/CHANGELOG.md +120 -2
  2. package/angular.json +1 -0
  3. package/package.json +1 -1
  4. package/src/app/app.component.html +3 -1
  5. package/src/app/app.component.ts +71 -12
  6. package/src/app/chatlib/conversation-detail/message/image/image.component.html +1 -0
  7. package/src/app/chatlib/conversation-detail/message/image/image.component.ts +19 -0
  8. package/src/app/components/canned-response/canned-response.component.html +26 -23
  9. package/src/app/components/canned-response/canned-response.component.scss +0 -2
  10. package/src/app/components/canned-response/canned-response.component.ts +3 -1
  11. package/src/app/components/conversation-detail/message-text-area/message-text-area.component.html +24 -1
  12. package/src/app/components/conversation-detail/message-text-area/message-text-area.component.scss +30 -0
  13. package/src/app/components/conversation-detail/message-text-area/message-text-area.component.ts +39 -9
  14. package/src/app/components/conversation-info/info-content/info-content.component.ts +2 -2
  15. package/src/app/components/conversation-info/info-group/info-group.component.ts +23 -21
  16. package/src/app/components/conversations-list/header-conversations-list/header-conversations-list.component.html +1 -1
  17. package/src/app/components/conversations-list/header-conversations-list/header-conversations-list.component.ts +5 -1
  18. package/src/app/components/navbar/navbar.component.html +3 -3
  19. package/src/app/components/navbar/navbar.component.ts +29 -38
  20. package/src/app/components/project-item/project-item.component.ts +11 -11
  21. package/src/app/components/sidebar/sidebar.component.html +65 -45
  22. package/src/app/components/sidebar/sidebar.component.ts +110 -117
  23. package/src/app/components/sidebar-user-details/sidebar-user-details.component.html +2 -2
  24. package/src/app/components/sidebar-user-details/sidebar-user-details.component.ts +10 -7
  25. package/src/app/modals/create-ticket/create-ticket.page.ts +4 -2
  26. package/src/app/pages/conversation-detail/conversation-detail.page.html +7 -3
  27. package/src/app/pages/conversation-detail/conversation-detail.page.ts +95 -7
  28. package/src/app/pages/conversations-list/conversations-list.page.html +2 -0
  29. package/src/app/pages/conversations-list/conversations-list.page.ts +40 -2
  30. package/src/app/services/global-settings/global-settings.service.ts +11 -3
  31. package/src/app/services/nav-proxy.service.ts +0 -1
  32. package/src/app/services/project_users/project-users.service.spec.ts +16 -0
  33. package/src/app/services/project_users/project-users.service.ts +63 -0
  34. package/src/app/services/tiledesk/tiledesk.service.ts +0 -16
  35. package/src/app/services/triggerEvents/triggerEvents.ts +28 -0
  36. package/src/app/services/websocket/websocket-js.ts +59 -534
  37. package/src/app/services/websocket/websocket-js_old.ts +578 -0
  38. package/src/app/services/websocket/websocket.service.ts +9 -10
  39. package/src/app/services/websocket/websocket.worker.ts +242 -0
  40. package/src/app/shared/shared.module.ts +11 -2
  41. package/src/app/utils/globals.ts +2 -0
  42. package/src/app/utils/permissions.constants.ts +138 -0
  43. package/src/app/utils/project-utils.ts +2 -2
  44. package/src/app/utils/utils.ts +18 -1
  45. package/src/assets/i18n/ar.json +11 -1
  46. package/src/assets/i18n/az.json +11 -1
  47. package/src/assets/i18n/de.json +11 -1
  48. package/src/assets/i18n/en.json +11 -1
  49. package/src/assets/i18n/es.json +11 -1
  50. package/src/assets/i18n/fr.json +11 -1
  51. package/src/assets/i18n/it.json +13 -3
  52. package/src/assets/i18n/kk.json +11 -1
  53. package/src/assets/i18n/pt.json +11 -1
  54. package/src/assets/i18n/ru.json +11 -1
  55. package/src/assets/i18n/sr.json +11 -1
  56. package/src/assets/i18n/sv.json +11 -1
  57. package/src/assets/i18n/tr.json +11 -1
  58. package/src/assets/i18n/uk.json +11 -1
  59. package/src/assets/i18n/uz.json +12 -1
  60. package/src/assets/img/no_data_found.png +0 -0
  61. package/src/assets/js/agentDesktop-sdk.js +55 -0
  62. package/src/assets/js/chat21client.js +36 -0
  63. package/src/assets/js/mqtt-keepalive-worker.js +53 -0
  64. package/src/assets/test.html +5 -2
  65. package/src/chat-config-template.json +1 -0
  66. package/src/chat-config.json +1 -0
  67. package/src/chat21-core/models/projectUsers.ts +19 -0
  68. package/src/chat21-core/providers/abstract/upload.service.ts +5 -1
  69. package/src/chat21-core/providers/firebase/firebase-conversation-handler.ts +1 -1
  70. package/src/chat21-core/providers/firebase/firebase-upload.service.ts +136 -9
  71. package/src/chat21-core/providers/mqtt/mqtt-conversation-handler.ts +1 -1
  72. package/src/chat21-core/providers/native/native-image-repo.ts +1 -1
  73. package/src/chat21-core/providers/native/native-upload-service.ts +143 -45
  74. package/src/chat21-core/providers/tiledesk/tiledesk-auth.service.ts +3 -0
  75. package/src/chat21-core/utils/utils.ts +16 -2
@@ -0,0 +1,242 @@
1
+ /// websocket.worker.ts
2
+
3
+ interface WSMessage {
4
+ action?: string;
5
+ event?: { topic: string; method: string };
6
+ payload?: any;
7
+ }
8
+
9
+ interface Subscription {
10
+ topic: string;
11
+ label?: string;
12
+ onCreate?: (msg: any) => void;
13
+ onUpdate?: (msg: any) => void;
14
+ onData?: (msg: any) => void;
15
+ }
16
+
17
+ let ws: WebSocket | null = null;
18
+ let url = '';
19
+ let reconnectInterval = 5000;
20
+ let subscriptions: Subscription[] = [];
21
+ let pendingMessages: any[] = [];
22
+
23
+
24
+ let pingMsg = { action: "heartbeat", payload: { message: { text: "ping" } } }
25
+ let pongMsg = { action: "heartbeat", payload: { message: { text: "pong" } } }
26
+ const pongTimeout = 10000;
27
+ const pingTimeout = 15000;
28
+ let pingTimeoutId;
29
+ let pongTimeoutId;
30
+
31
+ let reconnectAttempts = 0;
32
+ const maxReconnectDelay = 30000;
33
+ let manuallyClosed = false;
34
+ let pageHidden = false;
35
+
36
+ onmessage = (e: MessageEvent) => {
37
+ const { action, data } = e.data;
38
+
39
+ switch (action) {
40
+ case 'init':
41
+ url = data.url;
42
+ connect();
43
+ break;
44
+ case 'subscribe':
45
+ const topic = data.topic || data.label;
46
+ subscriptions.push({ topic });
47
+ if (ws && ws.readyState === WebSocket.OPEN) {
48
+ ws.send(JSON.stringify({
49
+ action: 'subscribe',
50
+ payload: {
51
+ topic: topic,
52
+ message: undefined,
53
+ method: undefined
54
+ }
55
+ }));
56
+ }
57
+ break;
58
+ case 'unsubscribe':
59
+ subscriptions = subscriptions.filter(s => s.topic !== data.topic);
60
+ if (ws && ws.readyState === WebSocket.OPEN) {
61
+ // Unsubscribe
62
+ ws.send(JSON.stringify({
63
+ action: 'unsubscribe',
64
+ payload: {
65
+ topic: data.topic,
66
+ message: undefined,
67
+ method: undefined
68
+ }
69
+ }));
70
+ }
71
+ break;
72
+ case 'visibility': // ✅ Nuovo
73
+ pageHidden = data.hidden;
74
+ break;
75
+ case 'send':
76
+ sendMessage(data.message);
77
+ break;
78
+ case 'close': // ✅ Nuovo
79
+ closeConnection();
80
+ break;
81
+ }
82
+ };
83
+
84
+ function connect() {
85
+ ws = new WebSocket(url);
86
+ ws.onopen = () => {
87
+ console.log('[Worker] WebSocket connected',subscriptions);
88
+ // Risottiamo pending subscriptions
89
+ subscriptions.forEach(s => {
90
+ ws!.send(JSON.stringify({
91
+ action: 'subscribe',
92
+ payload: {
93
+ topic: s.topic,
94
+ message: undefined,
95
+ method: undefined
96
+ }
97
+ }));
98
+ }
99
+ );
100
+ // Invia messaggi in coda
101
+ pendingMessages.forEach(msg => ws!.send(JSON.stringify(msg)));
102
+ pendingMessages = [];
103
+
104
+ // Inizializza heartbeat
105
+ heartCheck();
106
+ reconnectAttempts = 0;
107
+ };
108
+
109
+ ws.onmessage = (event) => {
110
+ try {
111
+ const msg: WSMessage = JSON.parse(event.data);
112
+ handleMessage(msg);
113
+ } catch (err) {
114
+ console.error('[Worker] Invalid message', err);
115
+ }
116
+ };
117
+
118
+ ws.onclose = () => {
119
+ heartReset();
120
+ if(!manuallyClosed){
121
+ reconnectAttempts++;
122
+ const delay = Math.min(reconnectAttempts * 1000, maxReconnectDelay);
123
+ console.log('[Worker] WebSocket disconnected, retry in', delay, 'ms');
124
+ setTimeout(connect, delay);
125
+ }
126
+ };
127
+
128
+ ws.onerror = (err) => {
129
+ console.error('[Worker] WebSocket error', err);
130
+ ws?.close();
131
+ };
132
+ }
133
+
134
+ function handleMessage(msg: WSMessage) {
135
+ console.log('[Worker] Received message:', msg);
136
+ // --- GESTIONE PING/PONG ---
137
+ if (msg.action === 'heartbeat' && msg.payload?.message?.text === 'ping') {
138
+ console.log('[Worker] Received ping, sending pong');
139
+ if (ws && ws.readyState === WebSocket.OPEN) {
140
+ ws.send(JSON.stringify(pongMsg));
141
+ }
142
+ return; // Non processare ulteriormente il ping
143
+ }
144
+
145
+ // Solo formato "publish"
146
+ if (msg.action !== "publish") return;
147
+
148
+ const topic = msg.payload?.topic;
149
+ const method = msg.payload?.method;
150
+ const payload = msg.payload?.message;
151
+
152
+ if (!topic) return;
153
+
154
+ // --- GESTIONE ARRAY DI MESSAGGI ---
155
+ const messages = Array.isArray(msg.payload.message) ? msg.payload.message : [msg.payload.message];
156
+ // Notifica solo le subscription che matchano
157
+ subscriptions.forEach(sub => {
158
+ if (sub.topic === topic) {
159
+ messages.forEach(element => {
160
+ postMessage({
161
+ topic,
162
+ method,
163
+ payload: element, // singolo elemento
164
+ data: msg // payload completo per eventuali onData globali
165
+ }, undefined);
166
+ });
167
+ }
168
+ });
169
+
170
+ }
171
+
172
+ function sendMessage(message: any) {
173
+ if (ws && ws.readyState === WebSocket.OPEN) {
174
+ ws.send(JSON.stringify(message));
175
+ } else {
176
+ pendingMessages.push(message);
177
+ }
178
+ }
179
+
180
+
181
+ // -----------------------------------------------------------------------------------------------------
182
+ // @ HeartCheck
183
+ // -----------------------------------------------------------------------------------------------------
184
+ function heartCheck() {
185
+ heartReset();
186
+ heartStart();
187
+ }
188
+
189
+ // -----------------------------------------------------------------------------------------------------
190
+ // @ HeartStart
191
+ // -----------------------------------------------------------------------------------------------------
192
+ function heartStart() {
193
+ // this.getRemainingTime();
194
+
195
+ // usa intervallo adattivo se tab è in background (Chrome throtla i timer)
196
+ const adaptivePing = pageHidden ? pingTimeout * 3 : pingTimeout;
197
+
198
+ // // pianifica invio ping
199
+ pingTimeoutId = setTimeout(() => {
200
+ if (!ws || ws.readyState !== WebSocket.OPEN) return;
201
+ console.log("[WEBSOCKET-JS] - HEART-START - SENDING PING ");
202
+
203
+ // Qui viene inviato un battito cardiaco. Dopo averlo ricevuto, viene restituito un messaggio di battito cardiaco.
204
+ // onmessage Ottieni il battito cardiaco restituito per indicare che la connessione è normale
205
+ ws.send(JSON.stringify(pingMsg));
206
+
207
+ // Se non viene ripristinato dopo un determinato periodo di tempo, il backend viene attivamente disconnesso
208
+ pongTimeoutId = setTimeout(() => {
209
+ console.log("[WEBSOCKET-JS] - HEART-START - PONG-TIMEOUT-ID - CLOSE WS ");
210
+ // se onclose Si esibirà reconnect,Eseguiamo ws.close() Bene, se lo esegui direttamente reconnect Si innescherà onclose Causa riconnessione due volte
211
+ ws.close();
212
+ }, pongTimeout) as unknown as number;
213
+ }, adaptivePing);
214
+
215
+ }
216
+
217
+ // -----------------------------------------------------------------------------------------------------
218
+ // @ heartReset
219
+ // -----------------------------------------------------------------------------------------------------
220
+ function heartReset() {
221
+ if (pongTimeoutId !== undefined) {
222
+ clearTimeout(pongTimeoutId);
223
+ pongTimeoutId = undefined;
224
+ }
225
+
226
+ if (pingTimeoutId !== undefined) {
227
+ clearTimeout(pingTimeoutId);
228
+ pingTimeoutId = undefined;
229
+ }
230
+ }
231
+
232
+ function closeConnection() {
233
+ if (ws) {
234
+ ws.close();
235
+ ws = null;
236
+ }
237
+ heartReset();
238
+ pendingMessages = [];
239
+ subscriptions = [];
240
+ manuallyClosed = true;
241
+ console.log('[Worker] WebSocket closed manually');
242
+ }
@@ -22,8 +22,9 @@ import { MatTooltipModule } from '@angular/material/tooltip';
22
22
  import { MatSnackBarModule } from '@angular/material/snack-bar';
23
23
  import { MatSlideToggleModule } from '@angular/material/slide-toggle';
24
24
  import { SafeHtmlPipe } from '../directives/safe-html.pipe';
25
-
26
- // import { MessageTextAreaComponent } from '../components/conversation-detail/message-text-area/message-text-area.component'; // MessageTextAreaComponent is part of the declarations ConversationDetailPageModule
25
+ import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
26
+ import { createTranslateLoader } from 'src/chat21-core/utils/utils';
27
+ import { HttpClient } from '@angular/common/http';
27
28
 
28
29
  @NgModule({
29
30
  declarations: [
@@ -140,6 +141,14 @@ import { SafeHtmlPipe } from '../directives/safe-html.pipe';
140
141
  NgSelectModule,
141
142
  FormsModule,
142
143
 
144
+ TranslateModule.forChild({
145
+ loader: {
146
+ provide: TranslateLoader,
147
+ useFactory: (createTranslateLoader),
148
+ deps: [HttpClient]
149
+ }
150
+ })
151
+
143
152
  ],
144
153
  schemas: [
145
154
  CUSTOM_ELEMENTS_SCHEMA,
@@ -15,6 +15,7 @@ export class Globals {
15
15
  jwt: string;
16
16
  fileUploadAccept: string;
17
17
  projectID: string;
18
+ logOut: boolean
18
19
 
19
20
  constructor(
20
21
  ) { }
@@ -36,6 +37,7 @@ export class Globals {
36
37
  this.lang = 'en'
37
38
  this.fileUploadAccept = 'image/*,.pdf,.txt'
38
39
  this.projectID = null;
40
+ this.logOut = true;
39
41
 
40
42
  }
41
43
 
@@ -0,0 +1,138 @@
1
+
2
+ export const PERMISSIONS = {
3
+ REQUEST_READ_ALL: 'request_read_all',
4
+ REQUEST_READ_GROUP: 'request_read_group',
5
+ REQUEST_READ_MY: 'request_read_my',
6
+
7
+ HOME_READ: 'home_read',
8
+
9
+ INBOX_READ: 'inbox_read',
10
+ REQUEST_UPDATE: 'request_update',
11
+ REQUEST_SEND: 'request_send',
12
+ REQUEST_CREATE_TICKET: 'request_create_ticket',
13
+ REQUEST_CLOSE: 'request_close',
14
+ REQUEST_JOIN: 'request_join',
15
+ REQUEST_REOPEN: 'request_reopen',
16
+ REQUEST_DELETE: 'request_delete',
17
+ REQUEST_UPDATE_STATUS: 'request_update_status',
18
+ REQUEST_UPDATE_PRIORITY: 'request_update_priority',
19
+ REQUEST_UPDATE_FOLLOWERS: 'request_update_followers',
20
+ REQUEST_UPDATE_SMART_ASSIGNMENT: 'request_update_smart_assignment',
21
+ REQUEST_UPDATE_TAGS: 'request_update_tags',
22
+ REQUEST_UPDATE_NOTES: 'request_update_notes',
23
+ REQUEST_REASSIGN:'request_reassign',
24
+ REQUEST_ADD:'request_add',
25
+ REQUEST_LEFT: 'request_left',
26
+ REQUEST_TRANSCRIPT_SEND: 'request_transcript_send',
27
+
28
+ HISTORY_READ: 'history_read',
29
+
30
+ RATING_READ:'rating_read',
31
+
32
+ AUTOMATIONSLOG_READ: "automationslog_read",
33
+ AUTOMATIONSLOG_CREATE: "automationslog_create",
34
+
35
+ KB_READ: 'kb_read',
36
+ KB_CONTENTS_ADD:'kb_contents_add',
37
+ KB_CONTENT_UPDATE: 'kb_content_update',
38
+ KB_CONTENT_REINDEX: 'kb_content_reindex',
39
+ KB_CONTENT_CHECK_STATUS: 'kb_content_check_status',
40
+ KB_NAMESPACE_ADD:'kb_namespace_add',
41
+ KB_SETTINGS_EDIT:'kb_settings_edit',
42
+ KB_DELETE: 'kb_delete',
43
+ KB_CONTENTS_EXPORT: 'kb_contents_export',
44
+ // KB_NAMESPACE_DELETE:'kb_namespace_delete',
45
+ // KB_CONTENTS_DELETE:'kb_contents_delete',
46
+
47
+
48
+
49
+ FLOWS_READ: 'flows_read',
50
+ FLOW_ADD: 'flow_add',
51
+ FLOW_EDIT: 'flow_edit',
52
+ FLOW_TEST: 'flow_test',
53
+ FLOW_DUPLICATE: 'flow_duplicate',
54
+ FLOW_DELETE: 'flow_delete',
55
+ FLOW_SHARE: 'flow_share',
56
+ FLOW_EXPORT: 'flow_export',
57
+ FLOW_WEBHOOK_COPY:"flow_webhook_copy",
58
+ FLOW_WEBHOOK_EDIT:"flow_webhook_edit",
59
+ FLOW_WEBHOOK_DELETE:"flow_webhook_delete",
60
+ // FLOW_VIEW_MESSAGE_GRAPH: 'flow_view_message_graph',
61
+
62
+ LEADS_READ: 'leads_read',
63
+ LEAD_UPDATE: 'lead_update',
64
+ LEAD_RESTORE: 'lead_restore',
65
+ LEAD_TRASH: 'lead_trash',
66
+ LEAD_DELETE: 'lead_delete',
67
+ LEADS_EXPORT: 'leads_export',
68
+ LEAD_BAN: 'lead_ban',
69
+ LEAD_UNBAN: 'lead_unban',
70
+
71
+ ANALYTICS_READ: 'analytics_read',
72
+ ACTIVITIES_READ: 'activities_read',
73
+
74
+ WIDGETSETUP_READ: 'widgetsetup_read',
75
+ INSTALLATION_READ: 'installation_read',
76
+ TRANSLATIONS_READ: 'translations_read',
77
+ WIDGETSETUP_UPDATE: 'widgetsetup_update',
78
+
79
+
80
+
81
+ DEPARTMENTS_LIST_READ: 'department_list_read',
82
+ DEPARTMENT_DETAIL_READ: 'department_detail_read',
83
+ DEPARTMENT_CREATE_READ: 'department_create_read',
84
+
85
+ TEAMMATES_READ: 'teammates_read',
86
+ TEAMMATE_UPDATE: 'teammate_update',
87
+ TEAMMATES_CREATE: 'teammates_create',
88
+ ROLES_READ: 'roles_read',
89
+ GROUPS_READ: 'groups_read',
90
+
91
+
92
+
93
+ EMAIL_TICKETING_READ:'email_ticketing_read',
94
+ EMAIL_TICKETING_UPDATE:'email_ticketing_update',
95
+
96
+ CANNED_RESPONSES_READ:'canned_responses_read',
97
+ CANNED_RESPONSES_UPDATE:'canned_responses_update',
98
+ CANNED_RESPONSES_CREATE:'canned_responses_create',
99
+ CANNED_RESPONSES_DELETE:'canned_responses_delete',
100
+
101
+ TAGS_READ:'tags_read',
102
+ TAG_CREATE:'tag_create',
103
+ TAG_DELETE:'tag_delete',
104
+ TAG_UPDATE:'tag_update',
105
+
106
+ HOURS_READ: 'hours_read',
107
+ HOURS_UPDATE: 'hours_update',
108
+ HOURS_DELETE: 'hours_delete',
109
+ HOURS_CREATE: 'hours_create',
110
+
111
+ INTEGRATIONS_READ: 'integrations_read',
112
+ INTEGRATIONS_UPDATE: 'integrations_update',
113
+
114
+ APPS_READ:'apps_read',
115
+ APPS_UPDATE:'apps_update',
116
+
117
+ SETTINGS_READ: 'settings_read',
118
+ PROJECTSETTINGS_GENERAL_READ: 'projectsettings_general_read',
119
+ PROJECTSETTINGS_GENERAL_UPDATE: 'projectsettings_general_update',
120
+ PROJECTSETTINGS_SUBSCRIPTION_READ: 'projectsettings_subscription_read',
121
+ PROJECTSETTINGS_DEVELOPER_READ: 'projectsettings_developer_read',
122
+ PROJECTSETTINGS_DEVELOPER_UPDATE: 'projectsettings_developer_update',
123
+ PROJECTSETTINGS_SMARTASSIGNMENT_READ: 'projectsettings_smartassignment_read',
124
+ PROJECTSETTINGS_SMARTASSIGNMENT_UPDATE: 'projectsettings_smartassignment_update',
125
+ PROJECTSETTINGS_NOTIFICATION_READ: 'projectsettings_notification_read',
126
+ PROJECTSETTINGS_SECURITY_READ: 'projectsettings_security_read',
127
+ PROJECTSETTINGS_BANNED_READ: 'projectsettings_banned_read',
128
+ PROJECTSETTINGS_ADVANCED_READ: 'projectsettings_advanced_read',
129
+
130
+ ACCESS_LISTS: 'accessLists',
131
+ PROFILE_PAGES: 'profilePages',
132
+ LEAD_DATA: 'leadData',
133
+ IMPORT_DATA: 'importData',
134
+ MANAGE_TAGS: 'manageTags',
135
+
136
+ CHANGE_PROJECT:'change_project',
137
+ SIMULATE_CONV:'simulate_conv',
138
+ };
@@ -129,9 +129,9 @@ export class ProjectPlanUtils {
129
129
 
130
130
  //case PAYMENT plan
131
131
  if(project && project.isActiveSubscription && project.profile.type=== 'payment'){
132
- check = true
133
- }else if(project && !project.isActiveSubscription && project.profile.type=== 'payment'){
134
132
  check = false
133
+ }else if(project && !project.isActiveSubscription && project.profile.type=== 'payment'){
134
+ check = true
135
135
  }
136
136
 
137
137
  return check
@@ -1,10 +1,12 @@
1
+ import { ProjectUser } from "src/chat21-core/models/projectUsers";
2
+
1
3
  export function getOSCode(key: string, token: string): boolean {
2
4
 
3
5
  if (token) {
4
6
  const keys: String[] = token.split("-");
5
7
 
6
8
  let element = keys.find(el => el.includes(key))
7
- console.log('keys', keys)
9
+ // console.log('keys', keys)
8
10
  if(element){
9
11
  element = element.split(":")[1]
10
12
  if(element && element === "F"){
@@ -21,4 +23,19 @@ export function getOSCode(key: string, token: string): boolean {
21
23
  }
22
24
 
23
25
  return false
26
+ }
27
+
28
+
29
+ export function hasRole(projectUser: ProjectUser, role: string ): boolean {
30
+ let roles = ['owner', 'admin', 'agent'];
31
+ if(roles.includes(projectUser.role)){
32
+ return true
33
+ }
34
+
35
+ if(Array.isArray(projectUser.rolePermissions) && projectUser.rolePermissions.includes(role)){
36
+ return true
37
+ }
38
+
39
+ return false
40
+
24
41
  }
@@ -225,6 +225,10 @@
225
225
  "admin": "مدير",
226
226
  "agent": "وكيل",
227
227
  "Conversations": "المحادثات",
228
+ "Monitor": "شاشة",
229
+ "Flows": "التدفّقات",
230
+ "Knowledgebases": "قواعد المعرفة",
231
+ "Whatsappbroadcasts": "نشرات WhatsApp",
228
232
  "Apps": "تطبيقات",
229
233
  "Analytics": "تحليلات",
230
234
  "Activities": "أنشطة",
@@ -306,5 +310,11 @@
306
310
  "SEND_EMAIL_SUCCESS_OFFLINE_MESSAGE":"تم إرسال الرسالة أيضًا عبر البريد الإلكتروني 📩"
307
311
  },
308
312
  "EMOJI_NOT_ELLOWED": "الرموز التعبيرية غير مسموح بها",
309
- "DOMAIN_NOT_ALLOWED": "يحتوي الرابط على نطاق غير مسموح"
313
+ "DOMAIN_NOT_ALLOWED": "يحتوي الرابط على نطاق غير مسموح",
314
+ "TICKET": {
315
+ "OPEN_TICKET": "افتح تذكرة",
316
+ "DESCRIPTION": "هل تؤكد أنك تريد فتح تذكرة لهذه المحادثة؟",
317
+ "CONFIRM": "تأكيد",
318
+ "CLOSE": "إغلاق"
319
+ }
310
320
  }
@@ -225,6 +225,10 @@
225
225
  "admin": "Administrator",
226
226
  "agent": "Agent",
227
227
  "Conversations": "Söhbətlər",
228
+ "Monitor": "Monitor",
229
+ "Flows": "Axınlar",
230
+ "Knowledgebases": "Bilik bazaları",
231
+ "Whatsappbroadcasts": "WhatsApp Yayınları",
228
232
  "Apps": "Proqramlar",
229
233
  "Analytics": "Analitika",
230
234
  "Activities": "Fəaliyyətlər",
@@ -306,5 +310,11 @@
306
310
  "SEND_EMAIL_SUCCESS_OFFLINE_MESSAGE":"Mesaj e-poçt vasitəsilə də göndərilib 📩"
307
311
  },
308
312
  "EMOJI_NOT_ELLOWED": "Emoji icazə verilmir",
309
- "DOMAIN_NOT_ALLOWED": "URL icazə verilməyən domeni ehtiva edir"
313
+ "DOMAIN_NOT_ALLOWED": "URL icazə verilməyən domeni ehtiva edir",
314
+ "TICKET": {
315
+ "OPEN_TICKET": "Bilet aç",
316
+ "DESCRIPTION": "Bu söhbət üçün bilet açmaq istədiyinizi təsdiqləyirsinizmi?",
317
+ "CONFIRM": "Təsdiqlə",
318
+ "CLOSE": "Bağla"
319
+ }
310
320
  }
@@ -225,6 +225,10 @@
225
225
  "admin": "Administrator",
226
226
  "agent": "Agent",
227
227
  "Conversations": "Gespräche",
228
+ "Monitor": "Monitor",
229
+ "Flows": "Flows",
230
+ "Knowledgebases": "Wissensdatenbanken",
231
+ "Whatsappbroadcasts": "WhatsApp-Broadcasts",
228
232
  "Apps": "Anwendungen",
229
233
  "Analytics": "Analytik",
230
234
  "Activities": "Aktivitäten",
@@ -306,5 +310,11 @@
306
310
  "SEND_EMAIL_SUCCESS_OFFLINE_MESSAGE":"Nachricht auch per E-Mail gesendet 📩"
307
311
  },
308
312
  "EMOJI_NOT_ELLOWED": "Emoji nicht erlaubt",
309
- "DOMAIN_NOT_ALLOWED": "Die URL enthält eine nicht erlaubte Domain"
313
+ "DOMAIN_NOT_ALLOWED": "Die URL enthält eine nicht erlaubte Domain",
314
+ "TICKET": {
315
+ "OPEN_TICKET": "Ticket öffnen",
316
+ "DESCRIPTION": "Bestätigen Sie, dass Sie ein Ticket für dieses Gespräch eröffnen möchten?",
317
+ "CONFIRM": "Bestätigen",
318
+ "CLOSE": "Schließen"
319
+ }
310
320
  }
@@ -225,6 +225,10 @@
225
225
  "admin": "Administrator",
226
226
  "agent": "Agent",
227
227
  "Conversations": "Conversations",
228
+ "Monitor":"Monitor",
229
+ "Flows": "Flows",
230
+ "Knowledgebases": "Knowledge Bases",
231
+ "Whatsappbroadcasts": "WhatsApp Broadcasts",
228
232
  "Apps": "Apps",
229
233
  "Analytics": "Analytics",
230
234
  "Activities": "Activities",
@@ -314,5 +318,11 @@
314
318
  "HOW_CAN_I_HELP_YOU":"How can i help you?"
315
319
  },
316
320
  "EMOJI_NOT_ELLOWED":"Emoji not allowed",
317
- "DOMAIN_NOT_ALLOWED":"URL contains a non-allowed domain"
321
+ "DOMAIN_NOT_ALLOWED":"URL contains a non-allowed domain",
322
+ "TICKET": {
323
+ "OPEN_TICKET": "Open Ticket",
324
+ "DESCRIPTION": "Do you confirm you want to open a ticket for this conversation?",
325
+ "CONFIRM": "Confirm",
326
+ "CLOSE": "Close"
327
+ }
318
328
  }
@@ -225,6 +225,10 @@
225
225
  "admin": "Administrador",
226
226
  "agent": "Agente",
227
227
  "Conversations": "Conversaciones",
228
+ "Monitor": "Monitor",
229
+ "Flows": "Flujos",
230
+ "Knowledgebases": "Bases de Conocimiento",
231
+ "Whatsappbroadcasts": "Difusiones de WhatsApp",
228
232
  "Apps":"Aplicaciones",
229
233
  "Analytics":"Analíticas",
230
234
  "Activities": "Actividades",
@@ -306,5 +310,11 @@
306
310
  "SEND_EMAIL_SUCCESS_OFFLINE_MESSAGE":"Mensaje también enviado por correo electrónico 📩"
307
311
  },
308
312
  "EMOJI_NOT_ELLOWED": "Emoji no permitido",
309
- "DOMAIN_NOT_ALLOWED": "La URL contiene un dominio no permitido"
313
+ "DOMAIN_NOT_ALLOWED": "La URL contiene un dominio no permitido",
314
+ "TICKET": {
315
+ "OPEN_TICKET": "Abrir Ticket",
316
+ "DESCRIPTION": "¿Confirmas que deseas abrir un ticket para esta conversación?",
317
+ "CONFIRM": "Confirmar",
318
+ "CLOSE": "Cerrar"
319
+ }
310
320
  }
@@ -225,6 +225,10 @@
225
225
  "admin": "Administrateur",
226
226
  "agent": "Agent",
227
227
  "Conversations": "Conversations",
228
+ "Monitor": "Moniteur",
229
+ "Flows": "Flux",
230
+ "Knowledgebases": "Bases de Connaissances",
231
+ "Whatsappbroadcasts": "Diffusions WhatsApp",
228
232
  "Apps":"Applications",
229
233
  "Analytics":"Analytique",
230
234
  "Activities": "Activités",
@@ -306,5 +310,11 @@
306
310
  "SEND_EMAIL_SUCCESS_OFFLINE_MESSAGE":"Message également envoyé par mail 📩"
307
311
  },
308
312
  "EMOJI_NOT_ELLOWED": "Emoji non autorisé",
309
- "DOMAIN_NOT_ALLOWED": "L'URL contient un domaine non autorisé"
313
+ "DOMAIN_NOT_ALLOWED": "L'URL contient un domaine non autorisé",
314
+ "TICKET": {
315
+ "OPEN_TICKET": "Ouvrir un Ticket",
316
+ "DESCRIPTION": "Confirmez-vous vouloir ouvrir un ticket pour cette conversation ?",
317
+ "CONFIRM": "Confirmer",
318
+ "CLOSE": "Fermer"
319
+ }
310
320
  }
@@ -225,6 +225,10 @@
225
225
  "admin": "Amministratore",
226
226
  "agent": "Agente",
227
227
  "Conversations": "Conversazioni",
228
+ "Monitor": "Monitor",
229
+ "Flows": "Flussi",
230
+ "Knowledgebases": "Basi di Conoscenza",
231
+ "Whatsappbroadcasts": "Trasmissioni WhatsApp",
228
232
  "Apps":"App",
229
233
  "Analytics":"Analitica",
230
234
  "Activities": "Attività",
@@ -312,7 +316,13 @@
312
316
  "NO_SUGGESTIONS_PRESENT":"Nessun suggerimento trovato",
313
317
  "INSERT_PROMPT_HERE":"Inserisci un prompt qui",
314
318
  "HOW_CAN_I_HELP_YOU":"Come posso aiutarti?"
315
- },
316
- "EMOJI_NOT_ELLOWED": "Emoji non consentite",
317
- "DOMAIN_NOT_ALLOWED": "L'URL contiene un dominio non consentito"
319
+ },
320
+ "EMOJI_NOT_ELLOWED": "Emoji non consentite",
321
+ "DOMAIN_NOT_ALLOWED": "L'URL contiene un dominio non consentito",
322
+ "TICKET": {
323
+ "OPEN_TICKET": "Apri Ticket",
324
+ "DESCRIPTION": "Confermi di voler aprire un ticket per questa conversazione?",
325
+ "CONFIRM": "Conferma",
326
+ "CLOSE": "Chiudi"
327
+ }
318
328
  }
@@ -225,6 +225,10 @@
225
225
  "admin": "Әкімші",
226
226
  "agent": "Агент",
227
227
  "Conversations": "Әңгімелер",
228
+ "Monitor": "Монитор",
229
+ "Flows": "Ағындар",
230
+ "Knowledgebases": "Білім базалары",
231
+ "Whatsappbroadcasts": "WhatsApp хабарламалары",
228
232
  "Apps": "Қолданбалар",
229
233
  "Analytics": "Аналитика",
230
234
  "Activities": "Іс-шаралар",
@@ -306,5 +310,11 @@
306
310
  "SEND_EMAIL_SUCCESS_OFFLINE_MESSAGE":"Хабарлама электрондық пошта арқылы да жіберілді 📩"
307
311
  },
308
312
  "EMOJI_NOT_ELLOWED": "Эмодзи рұқсат етілмеген",
309
- "DOMAIN_NOT_ALLOWED": "URL рұқсат етілмеген доменді қамтиды"
313
+ "DOMAIN_NOT_ALLOWED": "URL рұқсат етілмеген доменді қамтиды",
314
+ "TICKET": {
315
+ "OPEN_TICKET": "Тапсырма ашу",
316
+ "DESCRIPTION": "Осы әңгіме үшін тапсырма ашқыңыз келетінін растайсыз ба?",
317
+ "CONFIRM": "Растау",
318
+ "CLOSE": "Жабу"
319
+ }
310
320
  }