@chat21/chat21-ionic 3.4.32-rc6 → 3.4.32-rc8
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 +13 -0
- package/package.json +1 -1
- package/src/app/components/sidebar-user-details/sidebar-user-details.component.html +48 -10
- package/src/app/components/sidebar-user-details/sidebar-user-details.component.scss +294 -17
- package/src/app/components/sidebar-user-details/sidebar-user-details.component.ts +154 -3
- package/src/app/pages/conversations-list/conversations-list.page.ts +2 -0
- package/src/app/pipe/filter.pipe.spec.ts +8 -0
- package/src/app/pipe/filter.pipe.ts +15 -0
- package/src/app/pipe/find.pipe.spec.ts +8 -0
- package/src/app/pipe/find.pipe.ts +15 -0
- package/src/app/services/triggerEvents/triggerEvents.ts +12 -0
- package/src/app/shared/shared.module.ts +22 -15
- package/src/chat21-core/models/projects.ts +1 -0
- package/src/chat21-core/utils/constants.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,19 @@
|
|
|
8
8
|
### **Copyrigth**:
|
|
9
9
|
*Tiledesk SRL*
|
|
10
10
|
|
|
11
|
+
# 3.4.32-rc8
|
|
12
|
+
- **bug-fixed**: sidebar-user-details — status dropdown not visible when clicking first/last project; moved outside #user-details container to avoid overflow clipping.
|
|
13
|
+
- **bug-fixed**: sidebar-user-details — replaced `transform` on #user-details with `left` animation to fix `position: fixed` containing block (dropdown positioning).
|
|
14
|
+
- **changed**: sidebar-user-details — projects_dropdown_container and status-dropdown now use same colors as ng-select teammate-status-in-drawer.
|
|
15
|
+
- **changed**: sidebar-user-details — projects-dropdown-wrapper styled to match ng-select container.
|
|
16
|
+
- **added**: sidebar-user-details — MPA feature flag in featuresToken: if MPA is true show projects_dropdown_container, else show availability_dropdown_container.
|
|
17
|
+
- **bug-fixed**: RouterModule.forRoot() called twice when clicking conversation — SharedModule now imports RouterModule.forChild([]) instead of AppRoutingModule.
|
|
18
|
+
- **changed**: FindPipe and FilterPipe moved from AppModule to SharedModule for app-wide availability.
|
|
19
|
+
- **added**: conversations-list — postMessage to hosting app on conversation selection (event: `onConversationChanged`, data: full conversation object).
|
|
20
|
+
|
|
21
|
+
# 3.4.32-rc7
|
|
22
|
+
- **addded**: ability to change availability status for each project the logged-in user in sidebar-user-detail
|
|
23
|
+
|
|
11
24
|
# 3.4.32-rc6
|
|
12
25
|
- **bug-fixed**: convertRequestToConversation timestamp wrong unit
|
|
13
26
|
|
package/package.json
CHANGED
|
@@ -71,7 +71,8 @@
|
|
|
71
71
|
</span>
|
|
72
72
|
</mat-slide-toggle> -->
|
|
73
73
|
|
|
74
|
-
<ng-
|
|
74
|
+
<ng-container *ngIf="!isVisibleMPA" id="availability_dropdown_container">
|
|
75
|
+
<ng-select style="text-align: left;"
|
|
75
76
|
(change)="changeAvailabilityStateInUserDetailsSidebar(selectedStatus)"
|
|
76
77
|
[(ngModel)]="selectedStatus"
|
|
77
78
|
class="teammate-status-in-drawer sidebar"
|
|
@@ -79,15 +80,42 @@
|
|
|
79
80
|
bindLabel="name" bindValue="id"
|
|
80
81
|
[clearable]="false"
|
|
81
82
|
[searchable]="false">
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
83
|
+
<ng-template ng-label-tmp let-item="item">
|
|
84
|
+
<img style="width: 15px;height: 15px;position: relative; top: 1px;" height="15" width="15" [src]="item?.avatar" />
|
|
85
|
+
<span id="sidebaravatar_{{item.name}}" style="text-transform: capitalize; margin-left:8px"> {{item.label | translate}} </span>
|
|
86
|
+
</ng-template>
|
|
87
|
+
<ng-template ng-option-tmp let-item="item" let-index="index">
|
|
88
|
+
<img style="width: 15px;height: 15px;position: relative; top: 1px;" height="15" width="15" [src]="item?.avatar" />
|
|
89
|
+
<span id="sidebaravatar_{{item.name}}" style="text-transform: capitalize; margin-left:8px"> {{item.label | translate}} </span>
|
|
90
|
+
</ng-template>
|
|
91
|
+
</ng-select>
|
|
92
|
+
</ng-container>
|
|
93
|
+
|
|
94
|
+
<ng-container *ngIf="isVisibleMPA && projects?.length > 0" id="projects_dropdown_container">
|
|
95
|
+
<div class="projects-dropdown-wrapper">
|
|
96
|
+
<button class="btn projects-dropdown-toggle" (click)="toggleProjectsDropdown()">
|
|
97
|
+
<span class="projects-dropdown-toggle-label">
|
|
98
|
+
{{ project?.name || 'Progetti' }}
|
|
99
|
+
<img style="width: 15px; height: 15px; position: relative; top: 1px; cursor: pointer;" height="15" width="15" [src]="project?.teammateStatus?.avatar" />
|
|
100
|
+
</span>
|
|
101
|
+
<i class="material-icons" style="margin-left: 4px; font-size: 18px;">arrow_drop_down</i>
|
|
102
|
+
</button>
|
|
103
|
+
<div class="ripple-container"></div>
|
|
104
|
+
<div id="projects_dropdown" class="dropdown-menu" [ngClass]="{'open': openDropdownProjects}">
|
|
105
|
+
<li *ngFor="let prjct of projects?.slice() | slice:0:5; let i=index" style="cursor: pointer">
|
|
106
|
+
<a [ngClass]="{'li-selected' : prjct?.id_project?._id === project?.id_project?.id }"
|
|
107
|
+
class="project-item-row">
|
|
108
|
+
<span class="project-item-name">{{ prjct?.id_project?.name }}</span>
|
|
109
|
+
<span class="project-item-status project-item-status-wrapper"
|
|
110
|
+
[attr.title]="translationsMap?.get(prjct?.teammateStatus?.label) || prjct?.teammateStatus?.name"
|
|
111
|
+
(click)="toggleStatusDropdown($event, prjct)">
|
|
112
|
+
<img style="width: 15px; height: 15px; position: relative; top: 1px; cursor: pointer;" height="15" width="15" [src]="prjct?.teammateStatus?.avatar" />
|
|
113
|
+
</span>
|
|
114
|
+
</a>
|
|
115
|
+
</li>
|
|
116
|
+
</div>
|
|
117
|
+
</div>
|
|
118
|
+
</ng-container>
|
|
91
119
|
</section>
|
|
92
120
|
|
|
93
121
|
<hr class="first-divider">
|
|
@@ -140,4 +168,14 @@
|
|
|
140
168
|
<div class="chat-version"> ver {{version}}</div>
|
|
141
169
|
</section>
|
|
142
170
|
|
|
171
|
+
</div>
|
|
172
|
+
|
|
173
|
+
<!-- Status dropdown fuori da #user-details per evitare clipping da overflow -->
|
|
174
|
+
<div class="status-dropdown status-dropdown-fixed status-dropdown-outside" *ngIf="openStatusDropdownProjectId && selectedProjectForStatus" (click)="$event.stopPropagation()"
|
|
175
|
+
[style.top.px]="statusDropdownPosition.top" [style.right.px]="statusDropdownPosition.right">
|
|
176
|
+
<div class="status-dropdown-option" *ngFor="let status of TEAMMATE_STATUS"
|
|
177
|
+
(click)="$event.stopPropagation(); onChangeProjectStatus(selectedProjectForStatus, status.id)">
|
|
178
|
+
<img style="width: 15px; height: 15px; margin-right: 6px;" [src]="status.avatar" />
|
|
179
|
+
<span>{{ translationsMap?.get(status.label) || status.name }}</span>
|
|
180
|
+
</div>
|
|
143
181
|
</div>
|
|
@@ -2,23 +2,13 @@
|
|
|
2
2
|
#user-details {
|
|
3
3
|
background-color: var(--sidebar-background-color);
|
|
4
4
|
color: var(--sidebar-color);
|
|
5
|
-
// height: calc(100% - 60px);
|
|
6
5
|
height: 100%;
|
|
7
6
|
overflow-y: auto;
|
|
8
7
|
padding: 16px 12px 32px;
|
|
9
8
|
position: absolute;
|
|
10
|
-
|
|
11
|
-
// top: 60px;
|
|
12
|
-
// top: 0px;
|
|
13
|
-
// transform: translate(305px);
|
|
14
|
-
// transform: translate(60px);
|
|
15
|
-
transition: transform 0.5s;
|
|
9
|
+
transition: left 0.5s;
|
|
16
10
|
width: 305px;
|
|
17
11
|
left: -245px;
|
|
18
|
-
// z-index: 1029;
|
|
19
|
-
// transform: translateX(-100%);
|
|
20
|
-
// -webkit-transform: translateX(-100%);
|
|
21
|
-
// display: none;
|
|
22
12
|
}
|
|
23
13
|
|
|
24
14
|
// #user-details::-webkit-scrollbar {
|
|
@@ -33,11 +23,8 @@
|
|
|
33
23
|
// }
|
|
34
24
|
|
|
35
25
|
#user-details.active {
|
|
36
|
-
// transform: translate(0);
|
|
37
|
-
transform: translate(60px);
|
|
38
26
|
display: block;
|
|
39
|
-
|
|
40
|
-
left: 10px;
|
|
27
|
+
left: 70px; /* 10px + 60px (equivalente a transform: translate(60px)) - evita containing block per position: fixed */
|
|
41
28
|
}
|
|
42
29
|
|
|
43
30
|
.user-details-btn-close {
|
|
@@ -175,15 +162,305 @@
|
|
|
175
162
|
.availability-section {
|
|
176
163
|
top: 320px;
|
|
177
164
|
text-align: center;
|
|
178
|
-
background-color: var(--user-detail-select-background);
|
|
165
|
+
background-color: var(--sidebar-user-detail-select-background);
|
|
179
166
|
padding: 4px 0px;
|
|
180
|
-
width: 192px;
|
|
181
167
|
border-radius: 4px;
|
|
182
168
|
-webkit-transform: translateX(-50%);
|
|
183
169
|
transform: translateX(-50%);
|
|
184
170
|
left: 50%;
|
|
185
171
|
margin: auto;
|
|
186
172
|
position: absolute;
|
|
173
|
+
z-index: 2;
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
.btn{
|
|
178
|
+
display: flex;
|
|
179
|
+
position: relative;
|
|
180
|
+
flex-flow: row nowrap;
|
|
181
|
+
align-items: center;
|
|
182
|
+
justify-content: center;
|
|
183
|
+
|
|
184
|
+
border: 1px solid transparent;
|
|
185
|
+
transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.dropdown-toggle{
|
|
189
|
+
background-color: transparent;
|
|
190
|
+
color: inherit;
|
|
191
|
+
padding: 0px 15px;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
.project-dropdown,
|
|
195
|
+
.projects-dropdown-toggle {
|
|
196
|
+
// max-width: 180px;
|
|
197
|
+
white-space: nowrap;
|
|
198
|
+
overflow: hidden;
|
|
199
|
+
text-overflow: ellipsis;
|
|
200
|
+
font-family: var(--header-font-family);
|
|
201
|
+
|
|
202
|
+
.material-icons{
|
|
203
|
+
font-size: 20px;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
button.btn.project-dropdown,
|
|
208
|
+
button.btn.projects-dropdown-toggle {
|
|
209
|
+
padding-top: 4px;
|
|
210
|
+
padding-bottom: 4px;
|
|
211
|
+
background-color: var(--sidebar-user-detail-select-background);
|
|
212
|
+
color: var(--sidebar-user-detail-select-color);
|
|
213
|
+
border: 1px solid var(--sidebar-user-detail-select-background);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
.teammate-status-in-drawer {
|
|
217
|
+
width: 190px;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/* projects-dropdown-wrapper - stile come ng-select .ng-select-container (teammate-status-in-drawer) */
|
|
221
|
+
.projects-dropdown-wrapper {
|
|
222
|
+
position: relative;
|
|
223
|
+
min-height: 36px;
|
|
224
|
+
padding: 6px 12px;
|
|
225
|
+
background-color: var(--sidebar-user-detail-select-background);
|
|
226
|
+
color: var(--sidebar-user-detail-select-color);
|
|
227
|
+
border: 1px solid var(--sidebar-user-detail-select-background);
|
|
228
|
+
border-radius: 4px;
|
|
229
|
+
cursor: pointer;
|
|
230
|
+
display: flex;
|
|
231
|
+
align-items: center;
|
|
232
|
+
text-align: left;
|
|
233
|
+
font-size: 14px;
|
|
234
|
+
line-height: 1.4;
|
|
235
|
+
width: 250px;
|
|
236
|
+
|
|
237
|
+
.projects-dropdown-toggle {
|
|
238
|
+
background-color: transparent !important;
|
|
239
|
+
border: none !important;
|
|
240
|
+
padding: 0 !important;
|
|
241
|
+
min-height: auto;
|
|
242
|
+
flex: 1;
|
|
243
|
+
justify-content: flex-start;
|
|
244
|
+
color: inherit;
|
|
245
|
+
font-size: inherit;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
.projects-dropdown-toggle-label {
|
|
249
|
+
text-transform: capitalize;
|
|
250
|
+
overflow: hidden;
|
|
251
|
+
text-overflow: ellipsis;
|
|
252
|
+
white-space: nowrap;
|
|
253
|
+
display: flex;
|
|
254
|
+
align-items: center;
|
|
255
|
+
gap: 8px;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
.dropdown-menu {
|
|
259
|
+
left: 0;
|
|
260
|
+
right: 0;
|
|
261
|
+
min-width: 100%;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
li{
|
|
266
|
+
position: relative;
|
|
267
|
+
display: block
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/* projects_dropdown - stessi colori ng-select (.ng-dropdown-panel) */
|
|
271
|
+
.dropdown-menu {
|
|
272
|
+
border-radius: 4px;
|
|
273
|
+
border: 1px solid var(--sidebar-user-detail-select-background);
|
|
274
|
+
box-shadow: 0 2px 5px 0 rgb(0, 0, 0, 0.26);
|
|
275
|
+
|
|
276
|
+
position: absolute;
|
|
277
|
+
top: 100%;
|
|
278
|
+
right: 0;
|
|
279
|
+
left: auto;
|
|
280
|
+
z-index: 1000;
|
|
281
|
+
display: none;
|
|
282
|
+
float: left;
|
|
283
|
+
min-width: 160px;
|
|
284
|
+
padding: 5px 0;
|
|
285
|
+
margin: 8px 0 0;
|
|
286
|
+
font-size: 14px;
|
|
287
|
+
text-align: left;
|
|
288
|
+
list-style: none;
|
|
289
|
+
background-color: var(--sidebar-user-detail-select-background);
|
|
290
|
+
-webkit-background-clip: padding-box;
|
|
291
|
+
background-clip: padding-box;
|
|
292
|
+
color: var(--sidebar-user-detail-select-color);
|
|
293
|
+
max-height: 240px;
|
|
294
|
+
overflow-y: auto;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
.dropdown-menu:not(.open){
|
|
298
|
+
margin-top: -20px;
|
|
299
|
+
opacity: 0;
|
|
300
|
+
visibility: hidden;
|
|
301
|
+
display: block;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
.dropdown-menu.open{
|
|
305
|
+
margin-top: 12px; //0;
|
|
306
|
+
opacity: 1;
|
|
307
|
+
visibility: visible;
|
|
308
|
+
display: block;
|
|
309
|
+
transition: all 150ms linear;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
.dropdown-menu li {
|
|
313
|
+
position: relative;
|
|
314
|
+
|
|
315
|
+
.li-selected{
|
|
316
|
+
color: var(--sidebar-user-detail-select-color);
|
|
317
|
+
background-color: var(--sidebar-user-detail-select-hover-background);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
&.all-projects,
|
|
321
|
+
&.add-project{
|
|
322
|
+
color: var(--sidebar-user-detail-select-color);
|
|
323
|
+
i{
|
|
324
|
+
padding-right: 5px;
|
|
325
|
+
margin-bottom: 2px;
|
|
326
|
+
font-size: 20px
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
&.section-title{
|
|
331
|
+
padding-left: 24px;
|
|
332
|
+
font-size: 12px;
|
|
333
|
+
color: var(--sidebar-user-detail-color);
|
|
334
|
+
font-weight: 400
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
.dropdown-menu .divider{
|
|
339
|
+
background-color: rgba(255, 255, 255, 0.2);
|
|
340
|
+
margin: 5px 0;
|
|
341
|
+
|
|
342
|
+
height: 1px;
|
|
343
|
+
overflow: hidden;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
.dropdown-menu li>a{
|
|
347
|
+
font-size: 13px;
|
|
348
|
+
padding: 10px 20px;
|
|
349
|
+
border-radius: 2px;
|
|
350
|
+
transition: all 150ms linear;
|
|
351
|
+
|
|
352
|
+
display: block;
|
|
353
|
+
clear: both;
|
|
354
|
+
font-weight: 400;
|
|
355
|
+
line-height: 1.42857143;
|
|
356
|
+
color: var(--sidebar-user-detail-select-color);
|
|
357
|
+
white-space: nowrap;
|
|
358
|
+
text-decoration: none;
|
|
359
|
+
cursor: pointer;
|
|
360
|
+
|
|
361
|
+
.material-icons {
|
|
362
|
+
vertical-align: middle;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
&:hover{
|
|
366
|
+
background-color: var(--sidebar-user-detail-select-hover-background);
|
|
367
|
+
color: var(--sidebar-user-detail-select-color);
|
|
368
|
+
box-shadow: none;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
&.project-item-row {
|
|
372
|
+
display: flex;
|
|
373
|
+
align-items: center;
|
|
374
|
+
justify-content: space-between;
|
|
375
|
+
gap: 8px;
|
|
376
|
+
|
|
377
|
+
.project-item-name {
|
|
378
|
+
flex: 1;
|
|
379
|
+
min-width: 0;
|
|
380
|
+
text-align: left;
|
|
381
|
+
overflow: hidden;
|
|
382
|
+
text-overflow: ellipsis;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
.project-item-status {
|
|
386
|
+
flex: 0 0 10%;
|
|
387
|
+
display: flex;
|
|
388
|
+
justify-content: flex-end;
|
|
389
|
+
align-items: center;
|
|
390
|
+
|
|
391
|
+
&.project-item-status-wrapper {
|
|
392
|
+
position: relative;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
.status-dropdown {
|
|
396
|
+
position: absolute;
|
|
397
|
+
right: 100%;
|
|
398
|
+
top: 50%;
|
|
399
|
+
transform: translateY(-50%);
|
|
400
|
+
margin-right: 4px;
|
|
401
|
+
min-width: 140px;
|
|
402
|
+
padding: 4px 0;
|
|
403
|
+
background-color: var(--sidebar-user-detail-select-background);
|
|
404
|
+
border: 1px solid var(--sidebar-user-detail-select-background);
|
|
405
|
+
border-radius: 4px;
|
|
406
|
+
box-shadow: 0 2px 5px 0 rgb(0, 0, 0, 0.26);
|
|
407
|
+
z-index: 1001;
|
|
408
|
+
list-style: none;
|
|
409
|
+
|
|
410
|
+
&.status-dropdown-fixed {
|
|
411
|
+
right: auto;
|
|
412
|
+
left: auto;
|
|
413
|
+
margin-right: 0;
|
|
414
|
+
transform: translateY(-50%);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
.status-dropdown-option {
|
|
418
|
+
display: flex;
|
|
419
|
+
align-items: center;
|
|
420
|
+
padding: 8px 16px;
|
|
421
|
+
font-size: 13px;
|
|
422
|
+
color: var(--sidebar-user-detail-select-color);
|
|
423
|
+
cursor: pointer;
|
|
424
|
+
white-space: nowrap;
|
|
425
|
+
|
|
426
|
+
&:hover {
|
|
427
|
+
background-color: var(--sidebar-user-detail-select-hover-background);
|
|
428
|
+
color: var(--sidebar-user-detail-select-color);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
/* Status dropdown fuori da #user-details - stessi colori ng-select */
|
|
438
|
+
.status-dropdown-outside {
|
|
439
|
+
position: fixed !important;
|
|
440
|
+
transform: translateY(-50%);
|
|
441
|
+
z-index: 1100;
|
|
442
|
+
min-width: 140px;
|
|
443
|
+
padding: 4px 0;
|
|
444
|
+
background-color: var(--sidebar-user-detail-select-background);
|
|
445
|
+
border: 1px solid var(--sidebar-user-detail-select-background);
|
|
446
|
+
border-radius: 4px;
|
|
447
|
+
box-shadow: 0 2px 5px 0 rgb(0, 0, 0, 0.26);
|
|
448
|
+
list-style: none;
|
|
449
|
+
|
|
450
|
+
.status-dropdown-option {
|
|
451
|
+
display: flex;
|
|
452
|
+
align-items: center;
|
|
453
|
+
padding: 8px 16px;
|
|
454
|
+
font-size: 13px;
|
|
455
|
+
color: var(--sidebar-user-detail-select-color);
|
|
456
|
+
cursor: pointer;
|
|
457
|
+
white-space: nowrap;
|
|
458
|
+
|
|
459
|
+
&:hover {
|
|
460
|
+
background-color: var(--sidebar-user-detail-select-hover-background);
|
|
461
|
+
color: var(--sidebar-user-detail-select-color);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
187
464
|
}
|
|
188
465
|
|
|
189
466
|
.first-divider {
|
|
@@ -17,6 +17,8 @@ import { Project } from 'src/chat21-core/models/projects';
|
|
|
17
17
|
import { BRAND_BASE_INFO } from 'src/app/utils/utils-resources';
|
|
18
18
|
import { getOSCode } from 'src/app/utils/utils';
|
|
19
19
|
import { getUserStatusFromProjectUser } from 'src/chat21-core/utils/utils';
|
|
20
|
+
import { ProjectService } from 'src/app/services/projects/project.service';
|
|
21
|
+
import { ProjectUser } from 'src/chat21-core/models/project_user';
|
|
20
22
|
@Component({
|
|
21
23
|
selector: 'app-sidebar-user-details',
|
|
22
24
|
templateUrl: './sidebar-user-details.component.html',
|
|
@@ -55,6 +57,13 @@ export class SidebarUserDetailsComponent implements OnInit, OnChanges {
|
|
|
55
57
|
selectedStatus: any;
|
|
56
58
|
TEAMMATE_STATUS = TEAMMATE_STATUS;
|
|
57
59
|
|
|
60
|
+
projects: ProjectUser[] = [];
|
|
61
|
+
selectedProjectForStatus: ProjectUser | null = null;
|
|
62
|
+
public openDropdownProjects: boolean = false
|
|
63
|
+
public openStatusDropdownProjectId: string | null = null
|
|
64
|
+
statusDropdownPosition = { top: 0, right: 0 };
|
|
65
|
+
isVisibleMT = false;
|
|
66
|
+
isVisibleMPA = false;
|
|
58
67
|
|
|
59
68
|
translationsMap: Map<string, string> = new Map();
|
|
60
69
|
|
|
@@ -71,7 +80,7 @@ export class SidebarUserDetailsComponent implements OnInit, OnChanges {
|
|
|
71
80
|
public appConfigProvider: AppConfigProvider,
|
|
72
81
|
public events: EventsService,
|
|
73
82
|
private eRef: ElementRef,
|
|
74
|
-
|
|
83
|
+
private projectService: ProjectService,
|
|
75
84
|
) { }
|
|
76
85
|
|
|
77
86
|
ngOnInit() {
|
|
@@ -80,6 +89,7 @@ export class SidebarUserDetailsComponent implements OnInit, OnChanges {
|
|
|
80
89
|
this.subcribeToAuthStateChanged();
|
|
81
90
|
this.listenTocurrentProjectUserUserAvailability$();
|
|
82
91
|
this.listenToCurrentStoredProject();
|
|
92
|
+
this.listenToUserGoOnline();
|
|
83
93
|
this.getOSCODE();
|
|
84
94
|
}
|
|
85
95
|
|
|
@@ -240,6 +250,8 @@ export class SidebarUserDetailsComponent implements OnInit, OnChanges {
|
|
|
240
250
|
.set('LABEL_LOGOUT', text['LABEL_LOGOUT'])
|
|
241
251
|
.set('SubscriptionPaymentProblem', text['SubscriptionPaymentProblem'])
|
|
242
252
|
.set('ThePlanHasExpired', text['ThePlanHasExpired'])
|
|
253
|
+
.set('NAVBAR.RECENT_PROJECTS', text['NAVBAR.RECENT_PROJECTS'])
|
|
254
|
+
.set('NAVBAR.OTHER_PROJECTS', text['NAVBAR.OTHER_PROJECTS'])
|
|
243
255
|
|
|
244
256
|
this.TEAMMATE_STATUS.forEach(element => {
|
|
245
257
|
element.label = this.translationsMap.get(element.label)
|
|
@@ -255,6 +267,36 @@ export class SidebarUserDetailsComponent implements OnInit, OnChanges {
|
|
|
255
267
|
this.logger.log('[SIDEBAR-USER-DETAILS] AppConfigService getAppConfig', this.appConfigProvider.getConfig());
|
|
256
268
|
|
|
257
269
|
this.isVisiblePAY = getOSCode("PAY", this.public_Key);
|
|
270
|
+
this.isVisibleMT = getOSCode("MTT", this.public_Key);
|
|
271
|
+
this.isVisibleMPA = getOSCode("MPA", this.public_Key);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
listenToUserGoOnline() {
|
|
275
|
+
this.events.subscribe('go:online', (isOnline: boolean) => {
|
|
276
|
+
this.logger.log('[SIDEBAR-USER-DETAILS] listen to go:online --> ', isOnline);
|
|
277
|
+
if (isOnline) {
|
|
278
|
+
this.tiledeskToken = this.tiledeskAuthService.getTiledeskToken();
|
|
279
|
+
this.getProjects();
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
getProjects() {
|
|
285
|
+
this.logger.log('[SIDEBAR-USER-DETAILS] calling getProjects ... ');
|
|
286
|
+
this.projectService.getProjects().subscribe((projects: ProjectUser[]) => {
|
|
287
|
+
this.logger.log('[SIDEBAR-USER-DETAILS] getProjects PROJECTS ', projects);
|
|
288
|
+
if (projects) {
|
|
289
|
+
this.projects = projects.filter((prj: ProjectUser) => prj?.id_project?.status === 100);
|
|
290
|
+
this.projects.forEach((prj: ProjectUser) => {
|
|
291
|
+
prj.teammateStatus = getUserStatusFromProjectUser(prj as any);
|
|
292
|
+
});
|
|
293
|
+
this.logger.log('[SIDEBAR-USER-DETAILS] getProjects this.projects ', this.projects);
|
|
294
|
+
}
|
|
295
|
+
}, (error) => {
|
|
296
|
+
this.logger.error('[SIDEBAR-USER-DETAILS] getProjects - ERROR ', error);
|
|
297
|
+
}, () => {
|
|
298
|
+
this.logger.log('[SIDEBAR-USER-DETAILS] getProjects - COMPLETE');
|
|
299
|
+
});
|
|
258
300
|
}
|
|
259
301
|
|
|
260
302
|
listenToCurrentStoredProject() {
|
|
@@ -268,9 +310,9 @@ export class SidebarUserDetailsComponent implements OnInit, OnChanges {
|
|
|
268
310
|
name: projectObjct['id_project']['name'],
|
|
269
311
|
profile: projectObjct['id_project']['profile'],
|
|
270
312
|
isActiveSubscription: projectObjct['id_project']['isActiveSubscription'],
|
|
271
|
-
trialExpired: projectObjct['id_project']['trialExpired']
|
|
313
|
+
trialExpired: projectObjct['id_project']['trialExpired'],
|
|
314
|
+
teammateStatus: getUserStatusFromProjectUser(projectObjct as any)
|
|
272
315
|
}
|
|
273
|
-
|
|
274
316
|
if (this.project.profile.type === 'free') {
|
|
275
317
|
|
|
276
318
|
if (this.project.trialExpired === false) {
|
|
@@ -285,11 +327,17 @@ export class SidebarUserDetailsComponent implements OnInit, OnChanges {
|
|
|
285
327
|
}
|
|
286
328
|
|
|
287
329
|
this.wsService.subscriptionToWsCurrentProjectUserAvailability(this.project._id, projectObjct._id);
|
|
330
|
+
if (this.tiledeskToken) {
|
|
331
|
+
this.getProjects();
|
|
332
|
+
}
|
|
288
333
|
}
|
|
289
334
|
})
|
|
290
335
|
|
|
291
336
|
try {
|
|
292
337
|
this.tiledeskToken = this.appStorageService.getItem('tiledeskToken');
|
|
338
|
+
if (this.tiledeskToken) {
|
|
339
|
+
this.getProjects();
|
|
340
|
+
}
|
|
293
341
|
// this.logger.log('[SIDEBAR-USER-DETAILS] - GET STORED TOKEN ', this.tiledeskToken)
|
|
294
342
|
} catch (err) {
|
|
295
343
|
this.logger.error('[SIDEBAR-USER-DETAILS] - GET STORED TOKEN ', err)
|
|
@@ -350,6 +398,109 @@ export class SidebarUserDetailsComponent implements OnInit, OnChanges {
|
|
|
350
398
|
});
|
|
351
399
|
}
|
|
352
400
|
|
|
401
|
+
getCurrentStatusAvatar(): string {
|
|
402
|
+
const status = this.TEAMMATE_STATUS?.find(s => s.id === this.selectedStatus);
|
|
403
|
+
return status?.avatar || 'assets/img/teammate-status/avaible.svg';
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
getCurrentStatusLabel(): string {
|
|
407
|
+
const status = this.TEAMMATE_STATUS?.find(s => s.id === this.selectedStatus);
|
|
408
|
+
return status?.label || status?.name || '';
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
toggleProjectsDropdown() {
|
|
412
|
+
this.openDropdownProjects = !this.openDropdownProjects;
|
|
413
|
+
if (!this.openDropdownProjects) {
|
|
414
|
+
this.openStatusDropdownProjectId = null;
|
|
415
|
+
this.selectedProjectForStatus = null;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
toggleStatusDropdown(event: Event, prjct: any) {
|
|
420
|
+
event.stopPropagation()
|
|
421
|
+
event.preventDefault()
|
|
422
|
+
const projectId = prjct?.id_project?._id
|
|
423
|
+
const isOpening = this.openStatusDropdownProjectId !== projectId
|
|
424
|
+
if (isOpening) {
|
|
425
|
+
const el = event.currentTarget as HTMLElement
|
|
426
|
+
const rect = el.getBoundingClientRect()
|
|
427
|
+
this.statusDropdownPosition = {
|
|
428
|
+
top: rect.top + rect.height / 2,
|
|
429
|
+
right: window.innerWidth - rect.left + 4
|
|
430
|
+
}
|
|
431
|
+
this.selectedProjectForStatus = prjct
|
|
432
|
+
} else {
|
|
433
|
+
this.selectedProjectForStatus = null
|
|
434
|
+
}
|
|
435
|
+
this.openStatusDropdownProjectId = this.openStatusDropdownProjectId === projectId ? null : projectId
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
onChangeProjectStatus(projectUser: ProjectUser, selectedStatusID: any) {
|
|
439
|
+
this.logger.log('[SIDEBAR-USER-DETAILS] onChangeProjectStatus', projectUser, selectedStatusID)
|
|
440
|
+
this.openStatusDropdownProjectId = null
|
|
441
|
+
this.selectedProjectForStatus = null
|
|
442
|
+
|
|
443
|
+
let IS_AVAILABLE = null
|
|
444
|
+
let profilestatus = ''
|
|
445
|
+
if (selectedStatusID === 1) {
|
|
446
|
+
IS_AVAILABLE = true
|
|
447
|
+
} else if (selectedStatusID === 2) {
|
|
448
|
+
IS_AVAILABLE = false
|
|
449
|
+
} else if (selectedStatusID === 3) {
|
|
450
|
+
IS_AVAILABLE = false
|
|
451
|
+
profilestatus = 'inactive'
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
this.wsService.updateCurrentUserAvailability(this.tiledeskToken, projectUser.id_project._id, IS_AVAILABLE, profilestatus).subscribe((projectUserUpdated: any) => {
|
|
455
|
+
|
|
456
|
+
this.logger.log('[NAVBAR] - PROJECT-USER UPDATED ', projectUser)
|
|
457
|
+
this.projects.find(p => p.id_project._id === projectUser.id_project._id).teammateStatus = getUserStatusFromProjectUser(projectUserUpdated as any);
|
|
458
|
+
|
|
459
|
+
if(projectUser.id_project._id === this.project._id) {
|
|
460
|
+
this.project.teammateStatus = getUserStatusFromProjectUser(projectUserUpdated as any);
|
|
461
|
+
}
|
|
462
|
+
}, (error) => {
|
|
463
|
+
this.logger.error('[NAVBAR] - PROJECT-USER UPDATED - ERROR ', error);
|
|
464
|
+
|
|
465
|
+
}, () => {
|
|
466
|
+
this.logger.log('[NAVBAR] - PROJECT-USER UPDATED * COMPLETE *');
|
|
467
|
+
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
onStatusDropdownOptionClick(status: { id: number; name: string; avatar: string; label: string }, projectUser: ProjectUser | null) {
|
|
472
|
+
if (!projectUser) return;
|
|
473
|
+
this.changeProjectStatus(projectUser, status.id);
|
|
474
|
+
this.openStatusDropdownProjectId = null;
|
|
475
|
+
this.selectedProjectForStatus = null;
|
|
476
|
+
if (projectUser?.id_project?._id === this.project?._id) {
|
|
477
|
+
this.selectedStatus = status.id;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
changeProjectStatus(projectUser: ProjectUser, selectedStatusID: number) {
|
|
482
|
+
this.logger.log('[SIDEBAR-USER-DETAILS] changeProjectStatus projectid', projectUser?.id_project?._id, ' status: ', selectedStatusID);
|
|
483
|
+
let IS_AVAILABLE: boolean | null = null;
|
|
484
|
+
let profilestatus = '';
|
|
485
|
+
if (selectedStatusID === 1) {
|
|
486
|
+
IS_AVAILABLE = true;
|
|
487
|
+
} else if (selectedStatusID === 2) {
|
|
488
|
+
IS_AVAILABLE = false;
|
|
489
|
+
} else if (selectedStatusID === 3) {
|
|
490
|
+
IS_AVAILABLE = false;
|
|
491
|
+
profilestatus = 'inactive';
|
|
492
|
+
}
|
|
493
|
+
this.wsService.updateCurrentUserAvailability(this.tiledeskToken, projectUser.id_project._id, IS_AVAILABLE, profilestatus).subscribe((updated: any) => {
|
|
494
|
+
this.logger.log('[SIDEBAR-USER-DETAILS] - PROJECT-USER UPDATED ', updated);
|
|
495
|
+
const p = this.projects.find(prj => prj?.id_project?._id === projectUser?.id_project?._id);
|
|
496
|
+
if (p) {
|
|
497
|
+
p.teammateStatus = getUserStatusFromProjectUser(updated as any);
|
|
498
|
+
}
|
|
499
|
+
}, (error) => {
|
|
500
|
+
this.logger.error('[SIDEBAR-USER-DETAILS] - PROJECT-USER UPDATED - ERROR ', error);
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
|
|
353
504
|
changeAvailabilityStateInUserDetailsSidebar(selectedStatusID) {
|
|
354
505
|
this.logger.log('[SIDEBAR-USER-DETAILS] - changeAvailabilityState projectid', this.project._id, ' available 1: ', selectedStatusID);
|
|
355
506
|
|
|
@@ -147,6 +147,7 @@ export class ConversationListPage implements OnInit {
|
|
|
147
147
|
public wsService: WebsocketService,
|
|
148
148
|
public g: Globals,
|
|
149
149
|
public appStorageService: AppStorageService,
|
|
150
|
+
private triggerEvents: TriggerEvents,
|
|
150
151
|
) {
|
|
151
152
|
this.checkPlatform();
|
|
152
153
|
this.translations();
|
|
@@ -837,6 +838,7 @@ export class ConversationListPage implements OnInit {
|
|
|
837
838
|
this.logger.log('[CONVS-LIST-PAGE] onConversationSelected active conversation.uid ', conversation.uid)
|
|
838
839
|
this.events.publish('convList:onConversationSelected', conversation)
|
|
839
840
|
}
|
|
841
|
+
this.triggerEvents.triggerOnConversationChanged(conversation)
|
|
840
842
|
}
|
|
841
843
|
|
|
842
844
|
onImageLoaded(conversation: any) {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Pipe, PipeTransform } from '@angular/core';
|
|
2
|
+
|
|
3
|
+
@Pipe({
|
|
4
|
+
name: 'filter'
|
|
5
|
+
})
|
|
6
|
+
export class FilterPipe implements PipeTransform {
|
|
7
|
+
|
|
8
|
+
transform(items: any[], filter: Object): any {
|
|
9
|
+
if (!items || !filter) {
|
|
10
|
+
return items;
|
|
11
|
+
}
|
|
12
|
+
return items.filter(item => item[filter['key']] === filter['value']);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Pipe, PipeTransform } from '@angular/core';
|
|
2
|
+
|
|
3
|
+
@Pipe({
|
|
4
|
+
name: 'find'
|
|
5
|
+
})
|
|
6
|
+
export class FindPipe implements PipeTransform {
|
|
7
|
+
|
|
8
|
+
transform(items: any[], filter: Object): any {
|
|
9
|
+
if (!items || !filter) {
|
|
10
|
+
return items;
|
|
11
|
+
}
|
|
12
|
+
return items.find(item => item[filter['key']] === filter['value']);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
}
|
|
@@ -131,4 +131,16 @@ export class TriggerEvents {
|
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
|
|
134
|
+
public triggerOnConversationChanged(conversation: ConversationModel) {
|
|
135
|
+
this.logger.debug(' ---------------- triggerOnConversationChanged ---------------- ', conversation);
|
|
136
|
+
try {
|
|
137
|
+
const windowContext = this.windowContext;
|
|
138
|
+
if (windowContext) {
|
|
139
|
+
windowContext.postMessage({ type: 'onConversationChanged', data: conversation }, '*');
|
|
140
|
+
}
|
|
141
|
+
} catch (e) {
|
|
142
|
+
this.logger.error('[TRIGGER-HANDLER] > Error triggerOnConversationChanged:' + e);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
134
146
|
}
|
|
@@ -25,6 +25,9 @@ import { SafeHtmlPipe } from '../directives/safe-html.pipe';
|
|
|
25
25
|
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
|
26
26
|
import { createTranslateLoader } from 'src/chat21-core/utils/utils';
|
|
27
27
|
import { HttpClient } from '@angular/common/http';
|
|
28
|
+
import { RouterModule } from '@angular/router';
|
|
29
|
+
import { FindPipe } from '../pipe/find.pipe';
|
|
30
|
+
import { FilterPipe } from '../pipe/filter.pipe';
|
|
28
31
|
|
|
29
32
|
@NgModule({
|
|
30
33
|
declarations: [
|
|
@@ -67,12 +70,13 @@ import { HttpClient } from '@angular/common/http';
|
|
|
67
70
|
SidebarUserDetailsComponent,
|
|
68
71
|
|
|
69
72
|
//DIRECTIVES
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
73
|
+
AutofocusDirective,
|
|
74
|
+
TooltipDirective,
|
|
75
|
+
MarkedPipe,
|
|
76
|
+
HtmlEntitiesEncodePipe,
|
|
77
|
+
SafeHtmlPipe,
|
|
78
|
+
FindPipe,
|
|
79
|
+
FilterPipe,
|
|
76
80
|
|
|
77
81
|
|
|
78
82
|
AvatarProfileComponent,
|
|
@@ -123,6 +127,10 @@ import { HttpClient } from '@angular/common/http';
|
|
|
123
127
|
MarkedPipe,
|
|
124
128
|
HtmlEntitiesEncodePipe,
|
|
125
129
|
SafeHtmlPipe,
|
|
130
|
+
FindPipe,
|
|
131
|
+
FilterPipe,
|
|
132
|
+
|
|
133
|
+
RouterModule,
|
|
126
134
|
|
|
127
135
|
//COMMON COMPONENTS
|
|
128
136
|
AvatarProfileComponent,
|
|
@@ -140,16 +148,15 @@ import { HttpClient } from '@angular/common/http';
|
|
|
140
148
|
MomentModule,
|
|
141
149
|
NgSelectModule,
|
|
142
150
|
FormsModule,
|
|
143
|
-
|
|
144
151
|
TranslateModule.forChild({
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
})
|
|
151
|
-
|
|
152
|
-
|
|
152
|
+
loader: {
|
|
153
|
+
provide: TranslateLoader,
|
|
154
|
+
useFactory: (createTranslateLoader),
|
|
155
|
+
deps: [HttpClient]
|
|
156
|
+
}
|
|
157
|
+
}),
|
|
158
|
+
RouterModule.forChild([])
|
|
159
|
+
],
|
|
153
160
|
schemas: [
|
|
154
161
|
CUSTOM_ELEMENTS_SCHEMA,
|
|
155
162
|
NO_ERRORS_SCHEMA
|
|
@@ -153,6 +153,6 @@ export const TEAMMATE_STATUS = [
|
|
|
153
153
|
{ id: 1, name: 'Available', avatar: 'assets/img/teammate-status/avaible.svg', label: "LABEL_AVAILABLE" },
|
|
154
154
|
{ id: 2, name: 'Unavailable', avatar: 'assets/img/teammate-status/unavaible.svg', label: "LABEL_NOT_AVAILABLE" },
|
|
155
155
|
{ id: 3, name: 'Inactive', avatar: 'assets/img/teammate-status/inactive.svg', label: "LABEL_INACTIVE" },
|
|
156
|
-
|
|
156
|
+
];
|
|
157
157
|
|
|
158
158
|
|