@chat21/chat21-ionic 3.4.30 → 3.4.32-rc1
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 +131 -2
- package/angular.json +1 -0
- package/package.json +1 -1
- package/src/app/app.component.html +3 -1
- package/src/app/app.component.ts +72 -13
- package/src/app/chatlib/conversation-detail/message/image/image.component.html +1 -0
- package/src/app/chatlib/conversation-detail/message/image/image.component.ts +19 -0
- package/src/app/chatlib/list-conversations-component/ion-list-conversations/ion-list-conversations.component.html +14 -2
- package/src/app/chatlib/list-conversations-component/ion-list-conversations/ion-list-conversations.component.scss +39 -2
- package/src/app/chatlib/list-conversations-component/list-conversations.module.ts +14 -0
- package/src/app/components/canned-response/canned-response.component.html +26 -23
- package/src/app/components/canned-response/canned-response.component.scss +0 -2
- package/src/app/components/canned-response/canned-response.component.ts +3 -1
- package/src/app/components/conversation-detail/message-text-area/message-text-area.component.html +24 -1
- package/src/app/components/conversation-detail/message-text-area/message-text-area.component.scss +30 -0
- package/src/app/components/conversation-detail/message-text-area/message-text-area.component.ts +39 -9
- package/src/app/components/conversation-info/info-content/info-content.component.ts +2 -2
- package/src/app/components/conversation-info/info-group/info-group.component.ts +23 -21
- package/src/app/components/conversations-list/header-conversations-list/header-conversations-list.component.html +1 -1
- package/src/app/components/conversations-list/header-conversations-list/header-conversations-list.component.ts +5 -1
- package/src/app/components/navbar/navbar.component.html +35 -9
- package/src/app/components/navbar/navbar.component.scss +64 -0
- package/src/app/components/navbar/navbar.component.ts +100 -42
- package/src/app/components/project-item/project-item.component.ts +79 -51
- package/src/app/components/sidebar/sidebar.component.html +65 -45
- package/src/app/components/sidebar/sidebar.component.ts +110 -117
- package/src/app/components/sidebar-user-details/sidebar-user-details.component.html +3 -3
- package/src/app/components/sidebar-user-details/sidebar-user-details.component.ts +15 -22
- package/src/app/directives/html-entities-encode.pipe.ts +20 -5
- package/src/app/modals/create-ticket/create-ticket.page.ts +4 -2
- package/src/app/pages/conversation-detail/conversation-detail.page.html +7 -3
- package/src/app/pages/conversation-detail/conversation-detail.page.ts +95 -7
- package/src/app/pages/conversations-list/conversations-list.module.ts +3 -5
- package/src/app/pages/conversations-list/conversations-list.page.html +2 -0
- package/src/app/pages/conversations-list/conversations-list.page.ts +51 -11
- package/src/app/pages/unassigned-conversations/unassigned-conversations.module.ts +16 -4
- package/src/app/pages/unassigned-conversations/unassigned-conversations.page.html +41 -17
- package/src/app/pages/unassigned-conversations/unassigned-conversations.page.scss +10 -1
- package/src/app/pages/unassigned-conversations/unassigned-conversations.page.ts +114 -9
- package/src/app/services/global-settings/global-settings.service.ts +11 -3
- package/src/app/services/nav-proxy.service.ts +0 -1
- package/src/app/services/project_users/project-users.service.spec.ts +16 -0
- package/src/app/services/project_users/project-users.service.ts +63 -0
- package/src/app/services/projects/project.service.ts +2 -1
- package/src/app/services/tiledesk/tiledesk.service.ts +21 -16
- package/src/app/services/triggerEvents/triggerEvents.ts +28 -0
- package/src/app/services/websocket/websocket-js.ts +59 -534
- package/src/app/services/websocket/websocket-js_old.ts +578 -0
- package/src/app/services/websocket/websocket.service.ts +59 -10
- package/src/app/services/websocket/websocket.worker.ts +242 -0
- package/src/app/shared/shared.module.ts +11 -2
- package/src/app/utils/globals.ts +2 -0
- package/src/app/utils/permissions.constants.ts +138 -0
- package/src/app/utils/project-utils.ts +2 -2
- package/src/app/utils/utils.ts +18 -1
- package/src/assets/i18n/ar.json +11 -1
- package/src/assets/i18n/az.json +11 -1
- package/src/assets/i18n/de.json +11 -1
- package/src/assets/i18n/en.json +11 -1
- package/src/assets/i18n/es.json +11 -1
- package/src/assets/i18n/fr.json +11 -1
- package/src/assets/i18n/it.json +13 -3
- package/src/assets/i18n/kk.json +11 -1
- package/src/assets/i18n/pt.json +11 -1
- package/src/assets/i18n/ru.json +11 -1
- package/src/assets/i18n/sr.json +11 -1
- package/src/assets/i18n/sv.json +11 -1
- package/src/assets/i18n/tr.json +11 -1
- package/src/assets/i18n/uk.json +11 -1
- package/src/assets/i18n/uz.json +12 -1
- package/src/assets/img/no_data_found.png +0 -0
- package/src/assets/js/agentDesktop-sdk.js +55 -0
- package/src/assets/js/chat21client.js +36 -0
- package/src/assets/js/mqtt-keepalive-worker.js +53 -0
- package/src/assets/test.html +5 -2
- package/src/chat-config-template.json +1 -0
- package/src/chat-config.json +1 -0
- package/src/chat21-core/models/projectUsers.ts +19 -0
- package/src/chat21-core/models/project_user.ts +2 -1
- package/src/chat21-core/providers/abstract/upload.service.ts +5 -1
- package/src/chat21-core/providers/firebase/firebase-conversation-handler.ts +1 -1
- package/src/chat21-core/providers/firebase/firebase-upload.service.ts +136 -9
- package/src/chat21-core/providers/mqtt/mqtt-conversation-handler.ts +1 -1
- package/src/chat21-core/providers/native/native-image-repo.ts +1 -1
- package/src/chat21-core/providers/native/native-upload-service.ts +143 -45
- package/src/chat21-core/providers/tiledesk/tiledesk-auth.service.ts +3 -0
- package/src/chat21-core/utils/constants.ts +5 -0
- package/src/chat21-core/utils/convertRequestToConversation.ts +1 -1
- package/src/chat21-core/utils/utils.ts +53 -3
- package/src/variables.scss +3 -0
|
@@ -9,6 +9,7 @@ import { TiledeskAuthService } from 'src/chat21-core/providers/tiledesk/tiledesk
|
|
|
9
9
|
import { compareValues, htmlEntities } from 'src/chat21-core/utils/utils';
|
|
10
10
|
import { getProjectIdSelectedConversation } from 'src/chat21-core/utils/utils-message';
|
|
11
11
|
import { PLAN_NAME } from 'src/chat21-core/utils/constants';
|
|
12
|
+
import { PERMISSIONS } from 'src/app/utils/permissions.constants';
|
|
12
13
|
|
|
13
14
|
@Component({
|
|
14
15
|
selector: 'app-canned-response',
|
|
@@ -21,7 +22,7 @@ export class CannedResponseComponent implements OnInit {
|
|
|
21
22
|
@Input() conversationWith: string;
|
|
22
23
|
@Input() conversationWithFullname: string;
|
|
23
24
|
@Input() currentString: string;
|
|
24
|
-
@Input()
|
|
25
|
+
@Input() roles: Array<string>;
|
|
25
26
|
@Input() stylesMap: Map<string, string>;
|
|
26
27
|
@Input() translationMap: Map<string, string>;
|
|
27
28
|
@Output() onLoadedCannedResponses = new EventEmitter<[any]>();
|
|
@@ -36,6 +37,7 @@ export class CannedResponseComponent implements OnInit {
|
|
|
36
37
|
|
|
37
38
|
public arrowkeyLocation = -1
|
|
38
39
|
|
|
40
|
+
PERMISSIONS = PERMISSIONS
|
|
39
41
|
|
|
40
42
|
private logger: LoggerService = LoggerInstance.getInstance();
|
|
41
43
|
constructor(
|
package/src/app/components/conversation-detail/message-text-area/message-text-area.component.html
CHANGED
|
@@ -22,6 +22,13 @@
|
|
|
22
22
|
{{translationMap?.get('WHATSAPP.LABEL_TEMPLATES')}}
|
|
23
23
|
</ion-button>
|
|
24
24
|
</div>
|
|
25
|
+
<!-- OPEN TICKET -->
|
|
26
|
+
<div *ngIf="ticketSection" class="section-option" id="template" tooltip="{{translationMap?.get('TICKET.OPEN_TICKET')}}" placement="top">
|
|
27
|
+
<ion-button fill="clear" [class.active]="section==='ticket'" (click)="onOpenSection('ticket')" [disabled]="channelType === 'direct'">
|
|
28
|
+
<ion-icon name="ticket"></ion-icon>
|
|
29
|
+
{{translationMap?.get('TICKET.OPEN_TICKET')}}
|
|
30
|
+
</ion-button>
|
|
31
|
+
</div>
|
|
25
32
|
</div>
|
|
26
33
|
|
|
27
34
|
<div class="footerContainerAlert">
|
|
@@ -50,6 +57,22 @@
|
|
|
50
57
|
</ion-col>
|
|
51
58
|
</ion-row>
|
|
52
59
|
|
|
60
|
+
<ion-row id="ticket" [style.display]="section==='ticket'? 'flex': 'none'">
|
|
61
|
+
<ion-col col-auto>
|
|
62
|
+
<div class="placeholder">{{translationMap.get('TICKET.DESCRIPTION')}}</div>
|
|
63
|
+
<div class="buttons-container">
|
|
64
|
+
<ion-button name="add" size="small" (click)="onClickTicket('open')">
|
|
65
|
+
<ion-icon name="add"></ion-icon>
|
|
66
|
+
{{translationMap?.get('TICKET.CONFIRM')}}
|
|
67
|
+
</ion-button>
|
|
68
|
+
<ion-button size="small" color="danger" (click)="onClickTicket('close')">
|
|
69
|
+
<ion-icon name="close"></ion-icon>
|
|
70
|
+
{{translationMap?.get('TICKET.CLOSE')}}
|
|
71
|
+
</ion-button>
|
|
72
|
+
</div>
|
|
73
|
+
</ion-col>
|
|
74
|
+
</ion-row>
|
|
75
|
+
|
|
53
76
|
<ion-row id="message-text-area" [style.display]="section==='chat' || section ==='templates' || section ==='copilot'? 'flex': 'none'">
|
|
54
77
|
|
|
55
78
|
<ion-col col-auto style="display: flex;">
|
|
@@ -57,7 +80,7 @@
|
|
|
57
80
|
<div class="buttons-left">
|
|
58
81
|
|
|
59
82
|
<!-- CANNED RESPONSES -->
|
|
60
|
-
<ng-container *ngIf="areVisibleCAR && supportMode">
|
|
83
|
+
<ng-container *ngIf="areVisibleCAR && supportMode && cannedSection">
|
|
61
84
|
<div class="canned-responses-btn-wpr" tooltip="{{translationMap?.get('CANNED_RESPONSES')}}" placement="top">
|
|
62
85
|
<ion-button ion-button fill="clear" class="canned-responses-btn" (click)="openCannedResponses()"
|
|
63
86
|
[disabled]="!conversationWith?.startsWith(CHANNEL_TYPE.SUPPORT_GROUP) || disableTextarea">
|
package/src/app/components/conversation-detail/message-text-area/message-text-area.component.scss
CHANGED
|
@@ -183,6 +183,36 @@
|
|
|
183
183
|
}
|
|
184
184
|
}
|
|
185
185
|
|
|
186
|
+
#ticket{
|
|
187
|
+
text-align: center;
|
|
188
|
+
font-size: 12px;
|
|
189
|
+
|
|
190
|
+
.buttons-container{
|
|
191
|
+
display: flex;
|
|
192
|
+
justify-content: center;
|
|
193
|
+
gap: 10px;
|
|
194
|
+
|
|
195
|
+
ion-button{
|
|
196
|
+
font-size: 12px;
|
|
197
|
+
--padding-top: 4px;
|
|
198
|
+
--padding-bottom: 4px;
|
|
199
|
+
--padding-start: 6px;
|
|
200
|
+
--padding-end: 6px;
|
|
201
|
+
--ripple-color: transparent;
|
|
202
|
+
text-transform: unset;
|
|
203
|
+
height: auto;
|
|
204
|
+
|
|
205
|
+
ion-icon{
|
|
206
|
+
margin-right: 4px;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
&[name="add"]{
|
|
210
|
+
--background: var(--basic-blue);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
186
216
|
#fileInput {
|
|
187
217
|
position: absolute;
|
|
188
218
|
opacity: 0;
|
package/src/app/components/conversation-detail/message-text-area/message-text-area.component.ts
CHANGED
|
@@ -12,7 +12,7 @@ import { LoaderPreviewPage } from 'src/app/modals/loader-preview/loader-preview.
|
|
|
12
12
|
// Services
|
|
13
13
|
import { UploadService } from 'src/chat21-core/providers/abstract/upload.service';
|
|
14
14
|
// utils
|
|
15
|
-
import { TYPE_MSG_EMAIL, TYPE_MSG_TEXT, CHANNEL_TYPE } from 'src/chat21-core/utils/constants';
|
|
15
|
+
import { TYPE_MSG_EMAIL, TYPE_MSG_TEXT, CHANNEL_TYPE, TYPE_DIRECT } from 'src/chat21-core/utils/constants';
|
|
16
16
|
// Models
|
|
17
17
|
import { UploadModel } from 'src/chat21-core/models/upload';
|
|
18
18
|
|
|
@@ -26,6 +26,7 @@ import { CopilotService } from 'src/app/services/copilot/copilot.service';
|
|
|
26
26
|
import { BRAND_BASE_INFO } from 'src/app/utils/utils-resources';
|
|
27
27
|
import { ProjectService } from 'src/app/services/projects/project.service';
|
|
28
28
|
import { Project } from 'src/chat21-core/models/projects';
|
|
29
|
+
import { ProjectUser } from 'src/chat21-core/models/projectUsers';
|
|
29
30
|
|
|
30
31
|
|
|
31
32
|
@Component({
|
|
@@ -49,6 +50,7 @@ export class MessageTextAreaComponent implements OnInit, AfterViewInit, OnChange
|
|
|
49
50
|
@ViewChild('fileInput', { static: false }) fileInput: any;
|
|
50
51
|
|
|
51
52
|
@Input() loggedUser: UserModel;
|
|
53
|
+
@Input() projectUser: ProjectUser;
|
|
52
54
|
@Input() conversationWith: string;
|
|
53
55
|
@Input() channelType: string;
|
|
54
56
|
@Input() channel: string;
|
|
@@ -61,16 +63,20 @@ export class MessageTextAreaComponent implements OnInit, AfterViewInit, OnChange
|
|
|
61
63
|
@Input() emailSection: boolean;
|
|
62
64
|
@Input() offlineMsgEmail: boolean;
|
|
63
65
|
@Input() whatsappTemplatesSection: boolean;
|
|
66
|
+
@Input() ticketSection: boolean
|
|
64
67
|
@Input() isOpenInfoConversation: boolean;
|
|
68
|
+
@Input() cannedSection: boolean;
|
|
65
69
|
@Input() stylesMap: Map<string, string>;
|
|
66
70
|
@Input() translationMap: Map<string, string>;
|
|
67
71
|
@Input() dropEvent: any;
|
|
68
72
|
@Input() disableTextarea: boolean;
|
|
73
|
+
@Input() roles: Array<string>;
|
|
69
74
|
@Output() eventChangeTextArea = new EventEmitter<{msg: string, offsetHeight: number}>();
|
|
70
75
|
@Output() eventSendMessage = new EventEmitter<{msg: string, type: string, metadata?: Object, attributes?: Object}>();
|
|
71
76
|
@Output() onClickOpenCannedResponses = new EventEmitter<boolean>();
|
|
72
77
|
@Output() onPresentModalScrollToBottom = new EventEmitter<boolean>();
|
|
73
78
|
@Output() onOpenFooterSection = new EventEmitter<string>();
|
|
79
|
+
@Output() onOpenTicket = new EventEmitter<boolean>();
|
|
74
80
|
|
|
75
81
|
public project: Project;
|
|
76
82
|
public conversationEnabled = false;
|
|
@@ -162,6 +168,11 @@ export class MessageTextAreaComponent implements OnInit, AfterViewInit, OnChange
|
|
|
162
168
|
|
|
163
169
|
this.project = this.projectService.getProject();
|
|
164
170
|
this.logger.log('[CONVS-DETAIL] - returnChangeTextArea ngOnChanges in [MSG-TEXT-AREA] project', this.project)
|
|
171
|
+
if (this.channelType === TYPE_DIRECT) {
|
|
172
|
+
this.uploadService.initialize();
|
|
173
|
+
} else {
|
|
174
|
+
this.uploadService.initialize(this.project?._id);
|
|
175
|
+
}
|
|
165
176
|
// use case drop
|
|
166
177
|
if (this.dropEvent) {
|
|
167
178
|
this.presentModal(this.dropEvent)
|
|
@@ -288,6 +299,17 @@ export class MessageTextAreaComponent implements OnInit, AfterViewInit, OnChange
|
|
|
288
299
|
this.prensentTemplateModal();
|
|
289
300
|
}
|
|
290
301
|
|
|
302
|
+
onClickTicket(option: "open" | "close"){
|
|
303
|
+
this.logger.log('[CONVS-DETAIL][MSG-TEXT-AREA] - onClickTicket', option);
|
|
304
|
+
switch(option){
|
|
305
|
+
case "open":
|
|
306
|
+
this.onOpenTicket.emit();
|
|
307
|
+
case "close":
|
|
308
|
+
this.section = 'chat'
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
}
|
|
312
|
+
|
|
291
313
|
|
|
292
314
|
/**
|
|
293
315
|
*
|
|
@@ -384,7 +406,10 @@ export class MessageTextAreaComponent implements OnInit, AfterViewInit, OnChange
|
|
|
384
406
|
this.logger.log('[CONVS-DETAIL][MSG-TEXT-AREA] FIREBASE-UPLOAD presentModal onDidDismiss currentUpload', currentUpload);
|
|
385
407
|
this.logger.log('[CONVS-DETAIL][MSG-TEXT-AREA] FIREBASE-UPLOAD presentModal onDidDismiss detail.data', detail.data);
|
|
386
408
|
|
|
387
|
-
|
|
409
|
+
const uploadPromise = (that.channelType === TYPE_DIRECT)
|
|
410
|
+
? that.uploadService.upload(that.loggedUser.uid, currentUpload)
|
|
411
|
+
: that.uploadService.uploadFile(that.loggedUser.uid, currentUpload)
|
|
412
|
+
uploadPromise.then((data) => {
|
|
388
413
|
metadata.src = data.src;
|
|
389
414
|
metadata.downloadURL = data.downloadURL;
|
|
390
415
|
this.logger.log('[CONVS-DETAIL][MSG-TEXT-AREA] FIREBASE-UPLOAD presentModal invio msg metadata::: ', metadata);
|
|
@@ -567,8 +592,10 @@ export class MessageTextAreaComponent implements OnInit, AfterViewInit, OnChange
|
|
|
567
592
|
if (!text.includes("/")) {
|
|
568
593
|
this.logger.log('[CONVS-DETAIL][MSG-TEXT-AREA] onKeydown - SEND MESSAGE 1 message: ', message);
|
|
569
594
|
this.logger.log("[CONVS-DETAIL] replaceTagInMessage onKeydown in msg-texarea SEND MESSAGE 1 message: ", message);
|
|
570
|
-
|
|
595
|
+
|
|
571
596
|
this.sendMessage(text);
|
|
597
|
+
// this.messageString = '';
|
|
598
|
+
|
|
572
599
|
this.countClicks = 0
|
|
573
600
|
} else if (text.includes("/") && pos === 0 && this.countClicks > 1 && this.tagsCannedFilter.length > 0) {
|
|
574
601
|
this.logger.log('[CONVS-DETAIL][MSG-TEXT-AREA] onKeydown - tagsCannedFilter.length 2: ', this.tagsCannedFilter.length);
|
|
@@ -580,9 +607,10 @@ export class MessageTextAreaComponent implements OnInit, AfterViewInit, OnChange
|
|
|
580
607
|
this.logger.log("[CONVS-DETAIL] replaceTagInMessage onKeydown in msg-texarea SEND MESSAGE 2 this.countClicks: ", this.countClicks);
|
|
581
608
|
this.logger.log("[CONVS-DETAIL][MSG-TEXT-AREA] onKeydown in msg-texarea SEND MESSAGE 2 this.countClicks: ", this.countClicks);
|
|
582
609
|
this.logger.log('[CONVS-DETAIL][MSG-TEXT-AREA] onKeydown - SEND MESSAGE 2 message: ', message);
|
|
583
|
-
|
|
584
|
-
|
|
610
|
+
|
|
585
611
|
this.sendMessage(text);
|
|
612
|
+
// this.messageString = '';
|
|
613
|
+
|
|
586
614
|
this.countClicks = 0
|
|
587
615
|
} else if (text.includes("/") && pos > 0 && this.countClicks > 1 && this.tagsCannedFilter.length > 0 && text.substr(-1) !== '/') {
|
|
588
616
|
this.logger.log('[CONVS-DETAIL][MSG-TEXT-AREA] onKeydown - tagsCannedFilter.length 3: ', this.tagsCannedFilter.length);
|
|
@@ -594,17 +622,19 @@ export class MessageTextAreaComponent implements OnInit, AfterViewInit, OnChange
|
|
|
594
622
|
this.logger.log("[CONVS-DETAIL] replaceTagInMessage onKeydown in msg-texarea SEND MESSAGE 2 this.countClicks: ", this.countClicks);
|
|
595
623
|
this.logger.log("[CONVS-DETAIL][MSG-TEXT-AREA] onKeydown in msg-texarea SEND MESSAGE 2 this.countClicks: ", this.countClicks);
|
|
596
624
|
this.logger.log('[CONVS-DETAIL][MSG-TEXT-AREA] onKeydown - SEND MESSAGE 2 message: ', message);
|
|
597
|
-
|
|
598
|
-
|
|
625
|
+
|
|
599
626
|
this.sendMessage(text);
|
|
627
|
+
// this.messageString = '';
|
|
628
|
+
|
|
600
629
|
this.countClicks = 0
|
|
601
630
|
} else if (text.includes("/") && this.tagsCannedFilter.length === 0) {
|
|
602
631
|
this.logger.log('[CONVS-DETAIL][MSG-TEXT-AREA] onKeydown - tagsCannedFilter.length 3: ', this.tagsCannedFilter.length);
|
|
603
632
|
this.logger.log('[CONVS-DETAIL][MSG-TEXT-AREA] onKeydown - SEND MESSAGE 3 message: ', message);
|
|
604
633
|
this.logger.log("[CONVS-DETAIL] replaceTagInMessage onKeydown in msg-texarea SEND MESSAGE 3 message: ", message);
|
|
605
|
-
|
|
606
|
-
|
|
634
|
+
|
|
607
635
|
this.sendMessage(text);
|
|
636
|
+
// this.messageString = '';
|
|
637
|
+
|
|
608
638
|
this.countClicks = 0
|
|
609
639
|
|
|
610
640
|
}
|
|
@@ -70,8 +70,8 @@ export class InfoContentComponent implements OnInit {
|
|
|
70
70
|
this.route.paramMap.subscribe(params => {
|
|
71
71
|
this.logger.log('[INFO-CONTENT-COMP] initialize params: ', params);
|
|
72
72
|
this.conversationWith = params.get('IDConv');
|
|
73
|
-
this.conversationWithFullname = params.get('FullNameConv');
|
|
74
|
-
this.conv_type = params.get('Convtype');
|
|
73
|
+
this.conversationWithFullname = decodeURIComponent(params.get('FullNameConv'));
|
|
74
|
+
this.conv_type = decodeURIComponent(params.get('Convtype'));
|
|
75
75
|
|
|
76
76
|
const conversationWith_segments = this.conversationWith.split('-');
|
|
77
77
|
|
|
@@ -151,27 +151,29 @@ export class InfoGroupComponent implements OnInit, AfterViewInit, OnChanges {
|
|
|
151
151
|
});
|
|
152
152
|
|
|
153
153
|
this.contactsService.loadContactDetail(key).pipe(takeUntil(this.unsubscribe$)).subscribe(user => {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
154
|
+
if(user){
|
|
155
|
+
this.logger.log('InfoGroupComponent group detail loadContactDetail RES', user);
|
|
156
|
+
// this.logger.log('InfoGroupComponent group detail this.presenceService.BSIsOnline.value()', this.presenceService.BSIsOnline.getValue);
|
|
157
|
+
|
|
158
|
+
user.imageurl = this.imageRepoService.getImagePhotoUrl(key)
|
|
159
|
+
// this.member_array.push({ userid: user.uid, avatar: user.avatar, color: user.color, email: user.email, fullname: user.fullname, imageurl: user.imageurl, userOnline: isOnline })
|
|
160
|
+
var index = this.member_array.findIndex(m => m.userid === user.uid);
|
|
161
|
+
this.logger.log('InfoGroupComponent member_array first of push index', index);
|
|
162
|
+
this.logger.log('InfoGroupComponent member_array first of push', this.member_array);
|
|
163
|
+
if (index === -1) {
|
|
164
|
+
this.member_array.push(
|
|
165
|
+
{
|
|
166
|
+
userid: user.uid,
|
|
167
|
+
avatar: user.avatar,
|
|
168
|
+
color: user.color,
|
|
169
|
+
email: user.email,
|
|
170
|
+
fullname: user.fullname,
|
|
171
|
+
imageurl: user.imageurl,
|
|
172
|
+
userOnline: members_isonline_array[user.uid]['isSignin']
|
|
173
|
+
})
|
|
174
|
+
} else {
|
|
175
|
+
this.logger.log('InfoGroupComponent member already exist in member_array');
|
|
176
|
+
}
|
|
175
177
|
}
|
|
176
178
|
}, (error) => {
|
|
177
179
|
this.logger.error('InfoGroupComponent group detail loadContactDetail - ERROR ', error);
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
<!-- <ion-icon name="file-tray-full-outline"></ion-icon> -->
|
|
35
35
|
</ion-button>
|
|
36
36
|
|
|
37
|
-
<ion-button *ngIf="writeto_btn" ion-button fill="clear" (click)="onOpenContactsDirectory($event)"
|
|
37
|
+
<ion-button *ngIf="writeto_btn && isVisibleCNT && roles?.[PERMISSIONS.LEADS_READ]" ion-button fill="clear" (click)="onOpenContactsDirectory($event)"
|
|
38
38
|
tooltip="{{translationMap?.get('ViewContactsList')}}" placement="bottom">
|
|
39
39
|
<ion-icon slot="icon-only" name="create-outline"></ion-icon>
|
|
40
40
|
<!-- <ion-icon slot="icon-only" name="people-outline"></ion-icon> -->
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { PERMISSIONS } from 'src/app/utils/permissions.constants';
|
|
1
2
|
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'
|
|
2
3
|
import { ModalController } from '@ionic/angular'
|
|
3
4
|
import { EventsService } from 'src/app/services/events-service'
|
|
@@ -17,6 +18,8 @@ export class HeaderConversationsList implements OnInit {
|
|
|
17
18
|
@Input() sound_btn: string;
|
|
18
19
|
@Input() isMobile: boolean;
|
|
19
20
|
@Input() isVisibleTKT: boolean = true;
|
|
21
|
+
@Input() isVisibleCNT: boolean = true;;
|
|
22
|
+
@Input() roles: Array<string>;
|
|
20
23
|
@Output() onSoundChange = new EventEmitter<string>()
|
|
21
24
|
@Output() openContactsDirectory = new EventEmitter()
|
|
22
25
|
@Output() openProfileInfo = new EventEmitter()
|
|
@@ -24,6 +27,7 @@ export class HeaderConversationsList implements OnInit {
|
|
|
24
27
|
createTicketModal = null
|
|
25
28
|
public translationMap: Map<string, string>;
|
|
26
29
|
|
|
30
|
+
PERMISSIONS = PERMISSIONS;
|
|
27
31
|
constructor(
|
|
28
32
|
public events: EventsService,
|
|
29
33
|
public modalController: ModalController,
|
|
@@ -62,7 +66,7 @@ export class HeaderConversationsList implements OnInit {
|
|
|
62
66
|
// }
|
|
63
67
|
|
|
64
68
|
ngOnInit() {
|
|
65
|
-
|
|
69
|
+
console.log('DDP HEADER SUPPORT MODE ', this.roles)
|
|
66
70
|
}
|
|
67
71
|
|
|
68
72
|
// START @Output() //
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
</div>
|
|
6
6
|
<div class="navbar-right">
|
|
7
7
|
<!-- test site -->
|
|
8
|
-
<ng-container *ngIf="project">
|
|
8
|
+
<ng-container *ngIf="project && roles?.[PERMISSIONS.SIMULATE_CONV]">
|
|
9
9
|
<button class="btn simulate-visitor-btn" (click)="testWidgetPage()">
|
|
10
10
|
<i class="material-icons">play_arrow</i>
|
|
11
11
|
<!-- {{translationsMap?.get('NAVBAR.SIMULATE_VISITOR')}} -->
|
|
@@ -23,9 +23,9 @@
|
|
|
23
23
|
</ng-container>
|
|
24
24
|
|
|
25
25
|
<!-- ------ PROJECTS DROPDOWN ------ -->
|
|
26
|
-
<ng-container *ngIf="project">
|
|
26
|
+
<ng-container *ngIf="project && roles?.[PERMISSIONS.CHANGE_PROJECT]">
|
|
27
27
|
<li>
|
|
28
|
-
<button class="btn dropdown-toggle project-dropdown" (click)="
|
|
28
|
+
<button class="btn dropdown-toggle project-dropdown" (click)="toggleProjectsDropdown()">
|
|
29
29
|
<span class="project-dropdown" style="text-transform: none"> {{ project?.id_project?.name }} </span>
|
|
30
30
|
<i class="material-icons" style="margin-right: 3px;">arrow_drop_down</i>
|
|
31
31
|
</button>
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
</li>
|
|
50
50
|
|
|
51
51
|
<!-- ADD PROJECT -->
|
|
52
|
-
<li id="navbar_create_prjct" *ngIf="
|
|
52
|
+
<li id="navbar_create_prjct" *ngIf="isVisibleMT" (click)="onClickDropdownOption('addProject')" class="add-project">
|
|
53
53
|
<a>
|
|
54
54
|
<i class="material-icons">add_circle_outline </i>
|
|
55
55
|
{{translationsMap?.get('NAVBAR.ADD_PROJECT')}}
|
|
@@ -71,9 +71,22 @@
|
|
|
71
71
|
<!-- *ngFor="let prjct of projects?.slice().reverse() | slice:0:5; let i=index" -->
|
|
72
72
|
<li *ngFor="let prjct of projects?.slice() | slice:0:5; let i=index" style="cursor: pointer">
|
|
73
73
|
<a (click)="goToHome(prjct?.id_project?._id, prjct?.id_project?.name)"
|
|
74
|
-
[ngClass]="{'li-selected' : prjct?.id_project?._id === project?.id_project?.id }"
|
|
75
|
-
|
|
76
|
-
<span>
|
|
74
|
+
[ngClass]="{'li-selected' : prjct?.id_project?._id === project?.id_project?.id }"
|
|
75
|
+
class="project-item-row">
|
|
76
|
+
<span class="project-item-name">{{ prjct?.id_project?.name }}</span>
|
|
77
|
+
<span class="project-item-status project-item-status-wrapper"
|
|
78
|
+
[attr.title]="translationsMap?.get(prjct?.teammateStatus?.label) || prjct?.teammateStatus?.name"
|
|
79
|
+
(click)="toggleStatusDropdown($event, prjct)">
|
|
80
|
+
<img style="width: 15px; height: 15px; position: relative; top: 1px; cursor: pointer;" height="15" width="15" [src]="prjct?.teammateStatus?.avatar" />
|
|
81
|
+
<div class="status-dropdown status-dropdown-fixed" *ngIf="openStatusDropdownProjectId === prjct?.id_project?._id" (click)="$event.stopPropagation()"
|
|
82
|
+
[style.top.px]="statusDropdownPosition.top" [style.right.px]="statusDropdownPosition.right">
|
|
83
|
+
<div class="status-dropdown-option" *ngFor="let status of TEAMMATE_STATUS"
|
|
84
|
+
(click)="$event.stopPropagation(); onChangeProjectStatus(prjct, status.id)">
|
|
85
|
+
<img style="width: 15px; height: 15px; margin-right: 6px;" [src]="status.avatar" />
|
|
86
|
+
<span>{{ translationsMap?.get(status.label) || status.name }}</span>
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
89
|
+
</span>
|
|
77
90
|
</a>
|
|
78
91
|
</li>
|
|
79
92
|
|
|
@@ -85,8 +98,21 @@
|
|
|
85
98
|
|
|
86
99
|
<!-- *ngFor="let prjct of projects?.slice().reverse() | slice:5:10; let i=index" -->
|
|
87
100
|
<li *ngFor="let prjct of projects?.slice() | slice:5:10; let i=index" style="cursor: pointer">
|
|
88
|
-
<a (click)="goToHome(prjct?.id_project?._id, prjct?.id_project?.name)">
|
|
89
|
-
{{ prjct?.id_project?.name }}
|
|
101
|
+
<a (click)="goToHome(prjct?.id_project?._id, prjct?.id_project?.name)" class="project-item-row">
|
|
102
|
+
<span class="project-item-name">{{ prjct?.id_project?.name }}</span>
|
|
103
|
+
<span class="project-item-status project-item-status-wrapper"
|
|
104
|
+
[attr.title]="translationsMap?.get(prjct?.teammateStatus?.label) || prjct?.teammateStatus?.name"
|
|
105
|
+
(click)="toggleStatusDropdown($event, prjct)">
|
|
106
|
+
<img style="width: 15px; height: 15px; position: relative; top: 1px; cursor: pointer;" height="15" width="15" [src]="prjct?.teammateStatus?.avatar" />
|
|
107
|
+
<div class="status-dropdown status-dropdown-fixed" *ngIf="openStatusDropdownProjectId === prjct?.id_project?._id" (click)="$event.stopPropagation()"
|
|
108
|
+
[style.top.px]="statusDropdownPosition.top" [style.right.px]="statusDropdownPosition.right">
|
|
109
|
+
<div class="status-dropdown-option" *ngFor="let status of TEAMMATE_STATUS"
|
|
110
|
+
(click)="$event.stopPropagation(); onChangeProjectStatus(prjct, status.id)">
|
|
111
|
+
<img style="width: 15px; height: 15px; margin-right: 6px;" [src]="status.avatar" />
|
|
112
|
+
<span>{{ translationsMap?.get(status.label) || status.name }}</span>
|
|
113
|
+
</div>
|
|
114
|
+
</div>
|
|
115
|
+
</span>
|
|
90
116
|
</a>
|
|
91
117
|
</li>
|
|
92
118
|
</ng-container>
|
|
@@ -204,6 +204,70 @@ li{
|
|
|
204
204
|
color: var(--dropdown-menu-hover-color);
|
|
205
205
|
box-shadow: 0 12px 20px -10px rgba(var(--dropdown-menu-hover-color), 0.28), 0 4px 20px 0 rgba(0, 0, 0, 0.12), 0 7px 8px -5px rgba(var(--dropdown-menu-hover-color), 0.2);
|
|
206
206
|
}
|
|
207
|
+
|
|
208
|
+
&.project-item-row {
|
|
209
|
+
display: flex;
|
|
210
|
+
align-items: center;
|
|
211
|
+
justify-content: space-between;
|
|
212
|
+
gap: 8px;
|
|
213
|
+
|
|
214
|
+
.project-item-name {
|
|
215
|
+
flex: 1;
|
|
216
|
+
min-width: 0;
|
|
217
|
+
text-align: left;
|
|
218
|
+
overflow: hidden;
|
|
219
|
+
text-overflow: ellipsis;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.project-item-status {
|
|
223
|
+
flex: 0 0 10%;
|
|
224
|
+
display: flex;
|
|
225
|
+
justify-content: flex-end;
|
|
226
|
+
align-items: center;
|
|
227
|
+
|
|
228
|
+
&.project-item-status-wrapper {
|
|
229
|
+
position: relative;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.status-dropdown {
|
|
233
|
+
position: absolute;
|
|
234
|
+
right: 100%;
|
|
235
|
+
top: 50%;
|
|
236
|
+
transform: translateY(-50%);
|
|
237
|
+
margin-right: 4px;
|
|
238
|
+
min-width: 140px;
|
|
239
|
+
padding: 4px 0;
|
|
240
|
+
background-color: var(--dropdown-menu-background);
|
|
241
|
+
border-radius: 3px;
|
|
242
|
+
box-shadow: 0 2px 5px 0 rgb(0, 0, 0, 0.26);
|
|
243
|
+
z-index: 1001;
|
|
244
|
+
list-style: none;
|
|
245
|
+
|
|
246
|
+
&.status-dropdown-fixed {
|
|
247
|
+
position: fixed;
|
|
248
|
+
right: auto;
|
|
249
|
+
left: auto;
|
|
250
|
+
margin-right: 0;
|
|
251
|
+
transform: translateY(-50%);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
.status-dropdown-option {
|
|
255
|
+
display: flex;
|
|
256
|
+
align-items: center;
|
|
257
|
+
padding: 8px 16px;
|
|
258
|
+
font-size: 13px;
|
|
259
|
+
color: var(--dropdown-menu-color);
|
|
260
|
+
cursor: pointer;
|
|
261
|
+
white-space: nowrap;
|
|
262
|
+
|
|
263
|
+
&:hover {
|
|
264
|
+
background-color: var(--dropdown-menu-hover-background);
|
|
265
|
+
color: var(--dropdown-menu-hover-color);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
207
271
|
}
|
|
208
272
|
|
|
209
273
|
|