@senior-gestao-relacionamento/angular-components 2.0.0-master-d6f488bf → 2.0.0-master-eb758aaf
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/esm2022/lib/components/schedule/entities/participant-lookup.interface.mjs +2 -0
- package/esm2022/lib/components/schedule/entities/schedule-type.interface.mjs +2 -0
- package/esm2022/lib/components/schedule/entities/schedule.interface.mjs +2 -0
- package/esm2022/lib/components/schedule/enums/schedule.enums.mjs +65 -0
- package/esm2022/lib/components/schedule/helpers/schedule-date.helpers.mjs +109 -0
- package/esm2022/lib/components/schedule/helpers/schedule-display.helpers.mjs +108 -0
- package/esm2022/lib/components/schedule/schedule-detail/schedule-detail.component.mjs +79 -0
- package/esm2022/lib/components/schedule/schedule-form/schedule-form.component.mjs +731 -0
- package/esm2022/lib/components/schedule/services/schedule-type.service.mjs +23 -10
- package/esm2022/lib/components/schedule/services/schedule.service.mjs +30 -33
- package/esm2022/public-api.mjs +7 -5
- package/fesm2022/senior-gestao-relacionamento-angular-components.mjs +797 -739
- package/fesm2022/senior-gestao-relacionamento-angular-components.mjs.map +1 -1
- package/lib/components/schedule/entities/participant-lookup.interface.d.ts +38 -0
- package/lib/components/schedule/entities/schedule-type.interface.d.ts +10 -0
- package/lib/components/schedule/{models → entities}/schedule.interface.d.ts +19 -15
- package/lib/components/schedule/{models → enums}/schedule.enums.d.ts +5 -0
- package/lib/components/schedule/helpers/schedule-date.helpers.d.ts +9 -0
- package/lib/components/schedule/helpers/schedule-display.helpers.d.ts +17 -0
- package/lib/components/schedule/schedule-detail/schedule-detail.component.d.ts +43 -0
- package/lib/components/schedule/schedule-form/schedule-form.component.d.ts +139 -0
- package/lib/components/schedule/services/schedule-type.service.d.ts +14 -6
- package/lib/components/schedule/services/schedule.service.d.ts +21 -51
- package/package.json +3 -3
- package/public-api.d.ts +8 -5
- package/esm2022/lib/components/schedule/components/index.mjs +0 -3
- package/esm2022/lib/components/schedule/components/schedule-detail.component.mjs +0 -204
- package/esm2022/lib/components/schedule/components/schedule-form.component.mjs +0 -780
- package/esm2022/lib/components/schedule/index.mjs +0 -6
- package/esm2022/lib/components/schedule/models/index.mjs +0 -2
- package/esm2022/lib/components/schedule/models/schedule.enums.mjs +0 -59
- package/esm2022/lib/components/schedule/models/schedule.interface.mjs +0 -2
- package/esm2022/lib/components/schedule/services/index.mjs +0 -3
- package/lib/components/schedule/components/index.d.ts +0 -2
- package/lib/components/schedule/components/schedule-detail.component.d.ts +0 -53
- package/lib/components/schedule/components/schedule-form.component.d.ts +0 -98
- package/lib/components/schedule/index.d.ts +0 -5
- package/lib/components/schedule/models/index.d.ts +0 -2
- package/lib/components/schedule/services/index.d.ts +0 -2
|
@@ -1,39 +1,37 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { NgModule, Injectable, EventEmitter, Component, Input, Output, ViewChild } from '@angular/core';
|
|
3
|
-
import * as
|
|
3
|
+
import * as i6 from '@angular/common';
|
|
4
4
|
import { CommonModule } from '@angular/common';
|
|
5
|
-
import { BehaviorSubject, of, tap, Subject, debounceTime } from 'rxjs';
|
|
5
|
+
import { BehaviorSubject, of, tap, Subject, debounceTime, switchMap } from 'rxjs';
|
|
6
6
|
import * as i1 from '@angular/common/http';
|
|
7
|
+
import { HttpParams } from '@angular/common/http';
|
|
7
8
|
import * as i1$1 from '@angular/forms';
|
|
8
9
|
import { Validators, FormsModule, ReactiveFormsModule } from '@angular/forms';
|
|
9
|
-
import * as
|
|
10
|
-
import { DrawerModule } from 'primeng/drawer';
|
|
11
|
-
import * as i8 from 'primeng/button';
|
|
10
|
+
import * as i7 from 'primeng/button';
|
|
12
11
|
import { ButtonModule } from 'primeng/button';
|
|
13
|
-
import * as
|
|
12
|
+
import * as i4 from 'primeng/dialog';
|
|
13
|
+
import { DialogModule } from 'primeng/dialog';
|
|
14
|
+
import * as i9 from 'primeng/drawer';
|
|
15
|
+
import { DrawerModule } from 'primeng/drawer';
|
|
16
|
+
import * as i10 from 'primeng/dropdown';
|
|
14
17
|
import { DropdownModule } from 'primeng/dropdown';
|
|
15
|
-
import * as
|
|
18
|
+
import * as i11 from 'primeng/inputnumber';
|
|
16
19
|
import { InputNumberModule } from 'primeng/inputnumber';
|
|
17
|
-
import * as
|
|
20
|
+
import * as i12 from 'primeng/multiselect';
|
|
18
21
|
import { MultiSelectModule } from 'primeng/multiselect';
|
|
19
|
-
import * as
|
|
22
|
+
import * as i7$1 from 'primeng/tag';
|
|
23
|
+
import { TagModule } from 'primeng/tag';
|
|
24
|
+
import * as i13 from 'primeng/tooltip';
|
|
25
|
+
import { TooltipModule } from 'primeng/tooltip';
|
|
26
|
+
import * as i14 from 'primeng/divider';
|
|
20
27
|
import { DividerModule } from 'primeng/divider';
|
|
21
|
-
import * as
|
|
28
|
+
import * as i15 from 'primeng/table';
|
|
22
29
|
import { TableModule } from 'primeng/table';
|
|
23
|
-
import * as
|
|
30
|
+
import * as i16 from 'primeng/autocomplete';
|
|
24
31
|
import { AutoCompleteModule } from 'primeng/autocomplete';
|
|
25
|
-
import * as
|
|
26
|
-
import {
|
|
27
|
-
import * as
|
|
28
|
-
import { EntityService, TranslatePipe, LoadingComponent, DynamicFormComponent } from '@seniorsistemas/components-ai';
|
|
29
|
-
import * as i2$1 from 'primeng/api';
|
|
30
|
-
import { ConfirmationService } from 'primeng/api';
|
|
31
|
-
import * as i4 from 'primeng/dialog';
|
|
32
|
-
import { DialogModule } from 'primeng/dialog';
|
|
33
|
-
import * as i6$1 from 'primeng/tag';
|
|
34
|
-
import { TagModule } from 'primeng/tag';
|
|
35
|
-
import * as i8$1 from 'primeng/confirmdialog';
|
|
36
|
-
import { ConfirmDialogModule } from 'primeng/confirmdialog';
|
|
32
|
+
import * as i5 from '@seniorsistemas/components-ai';
|
|
33
|
+
import { TranslatePipe, DynamicFormComponent } from '@seniorsistemas/components-ai';
|
|
34
|
+
import * as i8 from 'primeng/api';
|
|
37
35
|
|
|
38
36
|
/**
|
|
39
37
|
* Módulo principal da biblioteca @senior-gestao-relacionamento/angular-components
|
|
@@ -305,279 +303,445 @@ var ParticipantConfirmation;
|
|
|
305
303
|
ParticipantConfirmation["Pending"] = "PENDING";
|
|
306
304
|
ParticipantConfirmation["No"] = "NO";
|
|
307
305
|
})(ParticipantConfirmation || (ParticipantConfirmation = {}));
|
|
306
|
+
var Status;
|
|
307
|
+
(function (Status) {
|
|
308
|
+
Status["Active"] = "ACTIVE";
|
|
309
|
+
Status["Inactive"] = "INACTIVE";
|
|
310
|
+
Status["Deleted"] = "DELETED";
|
|
311
|
+
})(Status || (Status = {}));
|
|
308
312
|
|
|
309
|
-
|
|
313
|
+
const MINUTES_HALF_HOUR = 30;
|
|
314
|
+
const DAYS_IN_WEEK = 7;
|
|
315
|
+
const ORDINAL_THIRD_WEEK = 3;
|
|
316
|
+
const HOURS_IN_DAY = 24;
|
|
317
|
+
const MINUTES_IN_HOUR = 60;
|
|
318
|
+
const DATE_STRING_LENGTH = 10;
|
|
319
|
+
const TIME_SHORT_LENGTH = 5;
|
|
320
|
+
function formatDateToString(d) {
|
|
321
|
+
return d.toISOString().split('T')[0];
|
|
322
|
+
}
|
|
323
|
+
function toDateString(v) {
|
|
324
|
+
if (!v) {
|
|
325
|
+
return '';
|
|
326
|
+
}
|
|
327
|
+
if (v instanceof Date) {
|
|
328
|
+
return formatDateToString(v);
|
|
329
|
+
}
|
|
330
|
+
const s = String(v);
|
|
331
|
+
return s.length > DATE_STRING_LENGTH ? s.substring(0, DATE_STRING_LENGTH) : s;
|
|
332
|
+
}
|
|
333
|
+
function toTimeString(v) {
|
|
334
|
+
if (!v) {
|
|
335
|
+
return '';
|
|
336
|
+
}
|
|
337
|
+
if (v instanceof Date) {
|
|
338
|
+
return formatTime(v.getHours(), v.getMinutes());
|
|
339
|
+
}
|
|
340
|
+
const s = String(v);
|
|
341
|
+
if (s.includes('T')) {
|
|
342
|
+
const d = new Date(s);
|
|
343
|
+
return formatTime(d.getHours(), d.getMinutes());
|
|
344
|
+
}
|
|
345
|
+
return s.length === TIME_SHORT_LENGTH ? s + ':00' : s;
|
|
346
|
+
}
|
|
347
|
+
function getDefaultStartTime(d) {
|
|
348
|
+
let h = d.getHours();
|
|
349
|
+
let m = d.getMinutes();
|
|
350
|
+
if (m < MINUTES_HALF_HOUR) {
|
|
351
|
+
m = MINUTES_HALF_HOUR;
|
|
352
|
+
}
|
|
353
|
+
else {
|
|
354
|
+
h++;
|
|
355
|
+
m = 0;
|
|
356
|
+
}
|
|
357
|
+
if (h >= HOURS_IN_DAY) {
|
|
358
|
+
h = 0;
|
|
359
|
+
}
|
|
360
|
+
return formatTime(h, m);
|
|
361
|
+
}
|
|
362
|
+
function getDefaultEndTime(startTime) {
|
|
363
|
+
const [hS, mS] = startTime.split(':');
|
|
364
|
+
let h = +hS;
|
|
365
|
+
let m = +mS + MINUTES_HALF_HOUR;
|
|
366
|
+
if (m >= MINUTES_IN_HOUR) {
|
|
367
|
+
h++;
|
|
368
|
+
m -= MINUTES_IN_HOUR;
|
|
369
|
+
}
|
|
370
|
+
if (h >= HOURS_IN_DAY) {
|
|
371
|
+
h = 0;
|
|
372
|
+
}
|
|
373
|
+
return formatTime(h, m);
|
|
374
|
+
}
|
|
375
|
+
function getCurrentWeekDay(d) {
|
|
376
|
+
const days = [
|
|
377
|
+
WeekDay.Sunday, WeekDay.Monday, WeekDay.Tuesday,
|
|
378
|
+
WeekDay.Wednesday, WeekDay.Thursday, WeekDay.Friday,
|
|
379
|
+
WeekDay.Saturday
|
|
380
|
+
];
|
|
381
|
+
return days[d.getDay()];
|
|
382
|
+
}
|
|
383
|
+
function getCurrentMonth(d) {
|
|
384
|
+
const months = [
|
|
385
|
+
Month.January, Month.February, Month.March,
|
|
386
|
+
Month.April, Month.May, Month.June,
|
|
387
|
+
Month.July, Month.August, Month.September,
|
|
388
|
+
Month.October, Month.November, Month.December
|
|
389
|
+
];
|
|
390
|
+
return months[d.getMonth()];
|
|
391
|
+
}
|
|
392
|
+
function getOrdinalForDate(d) {
|
|
393
|
+
const dom = d.getDate();
|
|
394
|
+
const wn = Math.ceil(dom / DAYS_IN_WEEK);
|
|
395
|
+
const ld = new Date(d.getFullYear(), d.getMonth() + 1, 0).getDate();
|
|
396
|
+
if (dom + DAYS_IN_WEEK > ld && wn >= 4) {
|
|
397
|
+
return OrdinalWeekDay.Last;
|
|
398
|
+
}
|
|
399
|
+
switch (wn) {
|
|
400
|
+
case 1: {
|
|
401
|
+
return OrdinalWeekDay.First;
|
|
402
|
+
}
|
|
403
|
+
case 2: {
|
|
404
|
+
return OrdinalWeekDay.Second;
|
|
405
|
+
}
|
|
406
|
+
case ORDINAL_THIRD_WEEK: {
|
|
407
|
+
return OrdinalWeekDay.Third;
|
|
408
|
+
}
|
|
409
|
+
case 4: {
|
|
410
|
+
return OrdinalWeekDay.Fourth;
|
|
411
|
+
}
|
|
412
|
+
default: {
|
|
413
|
+
return OrdinalWeekDay.Last;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
function formatTime(h, m) {
|
|
418
|
+
return `${String(h).padStart(2, '0')}:${String(m).padStart(2, '0')}:00`;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
const ICON_PI_USER = 'pi pi-user';
|
|
422
|
+
const ORIGIN_LABELS = {
|
|
423
|
+
ACCOUNT: 'crmx.components.schedule_participant_account',
|
|
424
|
+
ACCOUNT_CONTACT: 'crmx.components.schedule_participant_account_contact',
|
|
425
|
+
COLLABORATOR: 'crmx.components.schedule_participant_collaborator',
|
|
426
|
+
EXTERNAL_PARTICIPANT: 'crmx.components.schedule_participant_external'
|
|
427
|
+
};
|
|
428
|
+
const ORIGIN_ICONS = {
|
|
429
|
+
ACCOUNT: 'pi pi-building',
|
|
430
|
+
ACCOUNT_CONTACT: 'pi pi-id-card',
|
|
431
|
+
COLLABORATOR: ICON_PI_USER,
|
|
432
|
+
EXTERNAL_PARTICIPANT: 'pi pi-user-plus'
|
|
433
|
+
};
|
|
434
|
+
function getOriginLabel(t, o) {
|
|
435
|
+
return t.translate(ORIGIN_LABELS[o] ?? o);
|
|
436
|
+
}
|
|
437
|
+
function getOriginIcon(o) {
|
|
438
|
+
return ORIGIN_ICONS[o] ?? ICON_PI_USER;
|
|
439
|
+
}
|
|
440
|
+
function getParticipantName(p) {
|
|
441
|
+
const candidates = [
|
|
442
|
+
p.collaborator?.name,
|
|
443
|
+
p.account?.name,
|
|
444
|
+
p.accountContact?.name,
|
|
445
|
+
p.externalParticipant?.name
|
|
446
|
+
];
|
|
447
|
+
return candidates.find(name => name != null) ?? '-';
|
|
448
|
+
}
|
|
449
|
+
function getParticipantType(t, p) {
|
|
450
|
+
if (p.collaborator) {
|
|
451
|
+
return t.translate('crmx.components.schedule_participant_collaborator');
|
|
452
|
+
}
|
|
453
|
+
if (p.account) {
|
|
454
|
+
return t.translate('crmx.components.schedule_participant_account');
|
|
455
|
+
}
|
|
456
|
+
if (p.accountContact) {
|
|
457
|
+
return t.translate('crmx.components.schedule_participant_account_contact');
|
|
458
|
+
}
|
|
459
|
+
if (p.externalParticipant) {
|
|
460
|
+
return t.translate('crmx.components.schedule_participant_external');
|
|
461
|
+
}
|
|
462
|
+
return '-';
|
|
463
|
+
}
|
|
464
|
+
function getParticipantTypeIcon(p) {
|
|
465
|
+
if (p.collaborator) {
|
|
466
|
+
return ICON_PI_USER;
|
|
467
|
+
}
|
|
468
|
+
if (p.account) {
|
|
469
|
+
return 'pi pi-building';
|
|
470
|
+
}
|
|
471
|
+
if (p.accountContact) {
|
|
472
|
+
return 'pi pi-id-card';
|
|
473
|
+
}
|
|
474
|
+
if (p.externalParticipant) {
|
|
475
|
+
return 'pi pi-user-plus';
|
|
476
|
+
}
|
|
477
|
+
return ICON_PI_USER;
|
|
478
|
+
}
|
|
479
|
+
function getPrioritySeverity(p) {
|
|
480
|
+
switch (p) {
|
|
481
|
+
case SchedulePriority.Low: {
|
|
482
|
+
return 'success';
|
|
483
|
+
}
|
|
484
|
+
case SchedulePriority.Medium: {
|
|
485
|
+
return 'info';
|
|
486
|
+
}
|
|
487
|
+
case SchedulePriority.High: {
|
|
488
|
+
return 'warn';
|
|
489
|
+
}
|
|
490
|
+
case SchedulePriority.Critical: {
|
|
491
|
+
return 'danger';
|
|
492
|
+
}
|
|
493
|
+
default: {
|
|
494
|
+
return 'info';
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
function getPriorityLabel(t, p) {
|
|
499
|
+
return t.translate(`crmx.components.schedule_priority_${p.toLowerCase()}`);
|
|
500
|
+
}
|
|
501
|
+
function getConfirmationSeverity(c) {
|
|
502
|
+
switch (c) {
|
|
503
|
+
case 'YES': {
|
|
504
|
+
return 'success';
|
|
505
|
+
}
|
|
506
|
+
case 'NO': {
|
|
507
|
+
return 'danger';
|
|
508
|
+
}
|
|
509
|
+
default: {
|
|
510
|
+
return 'warn';
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
function getConfirmationLabel(t, c) {
|
|
515
|
+
switch (c) {
|
|
516
|
+
case 'YES': {
|
|
517
|
+
return t.translate('crmx.components.schedule_confirmation_yes');
|
|
518
|
+
}
|
|
519
|
+
case 'NO': {
|
|
520
|
+
return t.translate('crmx.components.schedule_confirmation_no');
|
|
521
|
+
}
|
|
522
|
+
default: {
|
|
523
|
+
return t.translate('crmx.components.schedule_confirmation_pending');
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
class ScheduleService {
|
|
529
|
+
http;
|
|
310
530
|
entityUrl = 'crmx/schedule/entities/schedule';
|
|
311
531
|
actionsUrl = 'crmx/schedule/actions';
|
|
312
532
|
queriesUrl = 'crmx/schedule/queries';
|
|
313
|
-
constructor(http
|
|
314
|
-
|
|
315
|
-
|
|
533
|
+
constructor(http) {
|
|
534
|
+
this.http = http;
|
|
535
|
+
}
|
|
536
|
+
get(id) {
|
|
537
|
+
return this.http.get(`/${this.entityUrl}/${id}`);
|
|
538
|
+
}
|
|
539
|
+
insert(entity) {
|
|
540
|
+
return this.http.post(`/${this.entityUrl}`, entity);
|
|
541
|
+
}
|
|
542
|
+
update(id, entity) {
|
|
543
|
+
return this.http.put(`/${this.entityUrl}/${id}`, entity);
|
|
544
|
+
}
|
|
545
|
+
delete(id) {
|
|
546
|
+
return this.http.delete(`/${this.entityUrl}/${id}`);
|
|
316
547
|
}
|
|
317
|
-
/**
|
|
318
|
-
* Busca recorrências de agendas por período
|
|
319
|
-
*/
|
|
320
548
|
getRecurrencesByDate(startDate, endDate) {
|
|
321
549
|
return this.http.post(`/${this.queriesUrl}/getRecurrencesByDate`, { startDate, endDate });
|
|
322
550
|
}
|
|
323
|
-
/**
|
|
324
|
-
* Gera descrição textual da recorrência configurada
|
|
325
|
-
*/
|
|
326
551
|
generateRecurrenceDescription(payload) {
|
|
327
552
|
return this.http.post(`/${this.queriesUrl}/generateRecurrenceDescription`, payload);
|
|
328
553
|
}
|
|
329
|
-
/**
|
|
330
|
-
* Aceita uma agenda (participante)
|
|
331
|
-
*/
|
|
332
554
|
acceptSchedule(scheduleId, participantId, date) {
|
|
333
555
|
return this.http.post(`/${this.actionsUrl}/acceptSchedule`, { scheduleId, participantId, date });
|
|
334
556
|
}
|
|
335
|
-
/**
|
|
336
|
-
* Rejeita uma agenda (participante)
|
|
337
|
-
*/
|
|
338
557
|
rejectSchedule(scheduleId, participantId, date) {
|
|
339
558
|
return this.http.post(`/${this.actionsUrl}/rejectSchedule`, { scheduleId, participantId, date });
|
|
340
559
|
}
|
|
341
|
-
/**
|
|
342
|
-
* Cancela uma agenda ou recorrência específica
|
|
343
|
-
*/
|
|
344
560
|
cancelSchedule(scheduleId, date) {
|
|
345
561
|
return this.http.post(`/${this.actionsUrl}/cancelSchedule`, { scheduleId, date });
|
|
346
562
|
}
|
|
347
|
-
/**
|
|
348
|
-
* Gerencia participantes de uma agenda
|
|
349
|
-
*/
|
|
350
563
|
manageParticipants(scheduleId, participants) {
|
|
351
564
|
return this.http.post(`/crmx/schedule/signals/manageScheduleParticipants`, { scheduleId, ...participants });
|
|
352
565
|
}
|
|
353
|
-
/**
|
|
354
|
-
* Lista participantes de uma agenda
|
|
355
|
-
*/
|
|
356
566
|
listParticipants(scheduleId) {
|
|
357
567
|
return this.http.get(`/${this.entityUrl}/${scheduleId}/participants`);
|
|
358
568
|
}
|
|
359
|
-
/**
|
|
360
|
-
* Busca participantes disponíveis (lookup)
|
|
361
|
-
*/
|
|
362
569
|
searchParticipantLookup(filter, size = 10, offset = 0) {
|
|
363
570
|
return this.http.post(`/${this.queriesUrl}/listParticipants`, { filter, size, offset, orderBy: 'name ASC' });
|
|
364
571
|
}
|
|
365
|
-
|
|
572
|
+
list(params = {}) {
|
|
573
|
+
let httpParams = new HttpParams();
|
|
574
|
+
if (params.size) {
|
|
575
|
+
httpParams = httpParams.set('size', String(params.size));
|
|
576
|
+
}
|
|
577
|
+
if (params.filterQuery) {
|
|
578
|
+
httpParams = httpParams.set('filter', params.filterQuery);
|
|
579
|
+
}
|
|
580
|
+
return this.http.get(`/${this.entityUrl}`, { params: httpParams });
|
|
581
|
+
}
|
|
582
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScheduleService, deps: [{ token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
366
583
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScheduleService, providedIn: 'root' });
|
|
367
584
|
}
|
|
368
585
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScheduleService, decorators: [{
|
|
369
586
|
type: Injectable,
|
|
370
587
|
args: [{ providedIn: 'root' }]
|
|
371
|
-
}], ctorParameters: () => [{ type: i1.HttpClient }
|
|
588
|
+
}], ctorParameters: () => [{ type: i1.HttpClient }] });
|
|
372
589
|
|
|
373
|
-
class ScheduleTypeService
|
|
590
|
+
class ScheduleTypeService {
|
|
591
|
+
http;
|
|
374
592
|
entityUrl = 'crmx/schedule/entities/scheduleType';
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
593
|
+
constructor(http) {
|
|
594
|
+
this.http = http;
|
|
595
|
+
}
|
|
596
|
+
list(params = {}) {
|
|
597
|
+
let httpParams = new HttpParams();
|
|
598
|
+
if (params.size) {
|
|
599
|
+
httpParams = httpParams.set('size', String(params.size));
|
|
600
|
+
}
|
|
601
|
+
const statusFilter = "status != 'DELETED'";
|
|
602
|
+
const filter = params.filterQuery
|
|
603
|
+
? `(${params.filterQuery}) and ${statusFilter}`
|
|
604
|
+
: statusFilter;
|
|
605
|
+
httpParams = httpParams.set('filter', filter);
|
|
606
|
+
return this.http.get(`/${this.entityUrl}`, { params: httpParams });
|
|
607
|
+
}
|
|
608
|
+
get(id) {
|
|
609
|
+
return this.http.get(`/${this.entityUrl}/${id}`);
|
|
379
610
|
}
|
|
380
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScheduleTypeService, deps: [{ token: i1.HttpClient }
|
|
611
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScheduleTypeService, deps: [{ token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
381
612
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScheduleTypeService, providedIn: 'root' });
|
|
382
613
|
}
|
|
383
614
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScheduleTypeService, decorators: [{
|
|
384
615
|
type: Injectable,
|
|
385
616
|
args: [{ providedIn: 'root' }]
|
|
386
|
-
}], ctorParameters: () => [{ type: i1.HttpClient }
|
|
617
|
+
}], ctorParameters: () => [{ type: i1.HttpClient }] });
|
|
387
618
|
|
|
619
|
+
/** S109: Extract magic numbers to named constants */
|
|
620
|
+
const MAX_NAME_LENGTH = 255;
|
|
621
|
+
const DEBOUNCE_MS = 500;
|
|
622
|
+
const PARTICIPANT_SEARCH_LIMIT = 5;
|
|
388
623
|
class ScheduleFormComponent {
|
|
389
624
|
fb;
|
|
390
|
-
t;
|
|
391
625
|
scheduleService;
|
|
392
626
|
scheduleTypeService;
|
|
627
|
+
currentCollaboratorService;
|
|
628
|
+
t;
|
|
393
629
|
visible = false;
|
|
394
|
-
|
|
630
|
+
selectedDate = new Date();
|
|
395
631
|
visibleChange = new EventEmitter();
|
|
396
|
-
|
|
397
|
-
onCancel = new EventEmitter();
|
|
632
|
+
saved = new EventEmitter();
|
|
398
633
|
detailFormComponent;
|
|
399
|
-
MAX_NAME_LENGTH = 255;
|
|
400
|
-
MIN_SEARCH_RESULTS = 5;
|
|
401
|
-
MINUTES_HALF_HOUR = 30;
|
|
402
|
-
MINUTES_IN_HOUR = 60;
|
|
403
|
-
HOURS_IN_DAY = 24;
|
|
404
|
-
DAYS_IN_WEEK = 7;
|
|
405
|
-
DEBOUNCE_TIME_MS = 500;
|
|
406
|
-
ORDINAL_WEEK_THRESHOLD = 4;
|
|
407
|
-
WEEK_DAYS_IN_MONTH = 3;
|
|
408
|
-
TIME_SECONDS_SUFFIX = ':00';
|
|
409
|
-
scheduleForm;
|
|
410
634
|
scheduleDetailFields = [];
|
|
411
635
|
entityDataForForm = null;
|
|
412
|
-
|
|
636
|
+
scheduleForm;
|
|
637
|
+
isEditing = false;
|
|
638
|
+
currentCollaboratorId = null;
|
|
639
|
+
scheduleTypes = [];
|
|
640
|
+
participants = [];
|
|
413
641
|
participantsLoading = false;
|
|
414
|
-
addedParticipants = [];
|
|
415
|
-
participantSuggestions = [];
|
|
416
|
-
selectedParticipantLookup = null;
|
|
417
|
-
// Recurrence
|
|
418
642
|
recurrenceDescription = '';
|
|
643
|
+
/** S2933: Mark as readonly */
|
|
419
644
|
recurrenceChange$ = new Subject();
|
|
420
|
-
|
|
645
|
+
participantSuggestions = [];
|
|
646
|
+
selectedParticipantLookup = null;
|
|
647
|
+
addedParticipants = [];
|
|
421
648
|
priorityOptions = [];
|
|
422
649
|
recurrenceOptions = [];
|
|
423
650
|
weekDayOptions = [];
|
|
424
651
|
repeatWhenOptions = [];
|
|
425
652
|
ordinalOptions = [];
|
|
426
653
|
monthOptions = [];
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
}
|
|
430
|
-
constructor(fb, t, scheduleService, scheduleTypeService) {
|
|
654
|
+
/** S2933: Mark constructor-injected services as readonly */
|
|
655
|
+
constructor(fb, scheduleService, scheduleTypeService, currentCollaboratorService, t) {
|
|
431
656
|
this.fb = fb;
|
|
432
|
-
this.t = t;
|
|
433
657
|
this.scheduleService = scheduleService;
|
|
434
658
|
this.scheduleTypeService = scheduleTypeService;
|
|
659
|
+
this.currentCollaboratorService = currentCollaboratorService;
|
|
660
|
+
this.t = t;
|
|
435
661
|
}
|
|
436
662
|
ngOnInit() {
|
|
437
663
|
this.initOptions();
|
|
438
664
|
this.initDetailFields();
|
|
439
665
|
this.initForm();
|
|
666
|
+
this.loadScheduleTypes();
|
|
667
|
+
this.loadCollaborator();
|
|
440
668
|
this.setupRecurrenceDescriptionWatcher();
|
|
441
669
|
}
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
670
|
+
loadCollaborator() {
|
|
671
|
+
this.currentCollaboratorService.load().subscribe({
|
|
672
|
+
next: (collab) => {
|
|
673
|
+
this.currentCollaboratorId = collab?.id ?? null;
|
|
674
|
+
},
|
|
675
|
+
error: () => {
|
|
676
|
+
this.currentCollaboratorId = null;
|
|
677
|
+
}
|
|
678
|
+
});
|
|
449
679
|
}
|
|
450
680
|
initOptions() {
|
|
451
681
|
this.priorityOptions = [
|
|
452
|
-
{ label: this.t.translate('crmx.
|
|
453
|
-
{ label: this.t.translate('crmx.
|
|
454
|
-
{ label: this.t.translate('crmx.
|
|
455
|
-
{ label: this.t.translate('crmx.
|
|
682
|
+
{ label: this.t.translate('crmx.components.schedule_priority_low'), value: SchedulePriority.Low },
|
|
683
|
+
{ label: this.t.translate('crmx.components.schedule_priority_medium'), value: SchedulePriority.Medium },
|
|
684
|
+
{ label: this.t.translate('crmx.components.schedule_priority_high'), value: SchedulePriority.High },
|
|
685
|
+
{ label: this.t.translate('crmx.components.schedule_priority_critical'), value: SchedulePriority.Critical }
|
|
456
686
|
];
|
|
457
687
|
this.recurrenceOptions = [
|
|
458
|
-
{ label: this.t.translate('crmx.
|
|
459
|
-
{ label: this.t.translate('crmx.
|
|
460
|
-
{ label: this.t.translate('crmx.
|
|
461
|
-
{ label: this.t.translate('crmx.
|
|
688
|
+
{ label: this.t.translate('crmx.components.schedule_recurrence_daily'), value: ScheduleRecurrence.Daily },
|
|
689
|
+
{ label: this.t.translate('crmx.components.schedule_recurrence_weekly'), value: ScheduleRecurrence.Weekly },
|
|
690
|
+
{ label: this.t.translate('crmx.components.schedule_recurrence_monthly'), value: ScheduleRecurrence.Monthly },
|
|
691
|
+
{ label: this.t.translate('crmx.components.schedule_recurrence_yearly'), value: ScheduleRecurrence.Yearly }
|
|
462
692
|
];
|
|
463
693
|
this.weekDayOptions = [
|
|
464
|
-
{ label: this.t.translate('crmx.
|
|
465
|
-
{ label: this.t.translate('crmx.
|
|
466
|
-
{ label: this.t.translate('crmx.
|
|
467
|
-
{ label: this.t.translate('crmx.
|
|
468
|
-
{ label: this.t.translate('crmx.
|
|
469
|
-
{ label: this.t.translate('crmx.
|
|
470
|
-
{ label: this.t.translate('crmx.
|
|
694
|
+
{ label: this.t.translate('crmx.components.schedule_sunday'), value: WeekDay.Sunday },
|
|
695
|
+
{ label: this.t.translate('crmx.components.schedule_monday'), value: WeekDay.Monday },
|
|
696
|
+
{ label: this.t.translate('crmx.components.schedule_tuesday'), value: WeekDay.Tuesday },
|
|
697
|
+
{ label: this.t.translate('crmx.components.schedule_wednesday'), value: WeekDay.Wednesday },
|
|
698
|
+
{ label: this.t.translate('crmx.components.schedule_thursday'), value: WeekDay.Thursday },
|
|
699
|
+
{ label: this.t.translate('crmx.components.schedule_friday'), value: WeekDay.Friday },
|
|
700
|
+
{ label: this.t.translate('crmx.components.schedule_saturday'), value: WeekDay.Saturday }
|
|
471
701
|
];
|
|
472
702
|
this.repeatWhenOptions = [
|
|
473
|
-
{ label: this.t.translate('crmx.
|
|
474
|
-
{ label: this.t.translate('crmx.
|
|
703
|
+
{ label: this.t.translate('crmx.components.schedule_repeat_in_day'), value: RepeatWhen.InDay },
|
|
704
|
+
{ label: this.t.translate('crmx.components.schedule_repeat_in_ordinal_week_day'), value: RepeatWhen.InOrdinalWeekDay }
|
|
475
705
|
];
|
|
476
706
|
this.ordinalOptions = [
|
|
477
|
-
{ label: this.t.translate('crmx.
|
|
478
|
-
{ label: this.t.translate('crmx.
|
|
479
|
-
{ label: this.t.translate('crmx.
|
|
480
|
-
{ label: this.t.translate('crmx.
|
|
481
|
-
{ label: this.t.translate('crmx.
|
|
707
|
+
{ label: this.t.translate('crmx.components.schedule_ordinal_first'), value: OrdinalWeekDay.First },
|
|
708
|
+
{ label: this.t.translate('crmx.components.schedule_ordinal_second'), value: OrdinalWeekDay.Second },
|
|
709
|
+
{ label: this.t.translate('crmx.components.schedule_ordinal_third'), value: OrdinalWeekDay.Third },
|
|
710
|
+
{ label: this.t.translate('crmx.components.schedule_ordinal_fourth'), value: OrdinalWeekDay.Fourth },
|
|
711
|
+
{ label: this.t.translate('crmx.components.schedule_ordinal_last'), value: OrdinalWeekDay.Last }
|
|
482
712
|
];
|
|
483
713
|
this.monthOptions = Object.values(Month).map(m => ({
|
|
484
|
-
label: this.t.translate(`crmx.
|
|
714
|
+
label: this.t.translate(`crmx.components.schedule_${m.toLowerCase()}`), value: m
|
|
485
715
|
}));
|
|
486
716
|
}
|
|
487
717
|
initDetailFields() {
|
|
488
718
|
const now = new Date();
|
|
489
719
|
const defaultStart = this.getDefaultStartTime(now);
|
|
490
720
|
const defaultEnd = this.getDefaultEndTime(defaultStart);
|
|
721
|
+
const fullRow = { xl: 12, lg: 12, md: 12, sm: 12 };
|
|
722
|
+
const halfRow = { xl: 6, lg: 6, md: 6, sm: 12 };
|
|
491
723
|
this.scheduleDetailFields = [
|
|
492
|
-
{
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
},
|
|
498
|
-
{
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
defaultValue: SchedulePriority.Medium, size: { xl: 12, lg: 12, md: 12, sm: 12 }
|
|
503
|
-
},
|
|
504
|
-
{
|
|
505
|
-
field: 'type', label: this.t.translate('crmx.schedule.type'), type: 'lookup',
|
|
506
|
-
lookupService: this.scheduleTypeService, lookupDisplayField: 'name', lookupValueField: 'id',
|
|
507
|
-
lookupSearchFields: ['name'], showClear: true, lookupAutocomplete: true,
|
|
508
|
-
lookupColumns: [{ field: 'name', header: this.t.translate('crmx.schedule.name') }],
|
|
509
|
-
lookupFilters: "status = 'ACTIVE'",
|
|
510
|
-
placeholder: this.t.translate('crmx.schedule.select_type'), size: { xl: 12, lg: 12, md: 12, sm: 12 }
|
|
511
|
-
},
|
|
512
|
-
{
|
|
513
|
-
field: 'startDate', label: this.t.translate('crmx.schedule.start_date'), type: 'date',
|
|
514
|
-
required: true, validators: [Validators.required],
|
|
515
|
-
defaultValue: this.formatDate(now),
|
|
516
|
-
size: (v) => v['withRecurrence'] ? { xl: 6, lg: 6, md: 6, sm: 12 } : { xl: 12, lg: 12, md: 12, sm: 12 }
|
|
517
|
-
},
|
|
518
|
-
{
|
|
519
|
-
field: 'endDate', label: this.t.translate('crmx.schedule.end_date'), type: 'date',
|
|
520
|
-
visibleWhen: (v) => v['withRecurrence'] === true,
|
|
521
|
-
size: { xl: 6, lg: 6, md: 6, sm: 12 }
|
|
522
|
-
},
|
|
523
|
-
{
|
|
524
|
-
field: 'startTime', label: this.t.translate('crmx.schedule.start_time'), type: 'time',
|
|
525
|
-
defaultValue: defaultStart,
|
|
526
|
-
visibleWhen: (v) => v['allDay'] !== true,
|
|
527
|
-
size: { xl: 6, lg: 6, md: 6, sm: 12 }
|
|
528
|
-
},
|
|
529
|
-
{
|
|
530
|
-
field: 'endTime', label: this.t.translate('crmx.schedule.end_time'), type: 'time',
|
|
531
|
-
defaultValue: defaultEnd,
|
|
532
|
-
visibleWhen: (v) => v['allDay'] !== true,
|
|
533
|
-
size: { xl: 6, lg: 6, md: 6, sm: 12 }
|
|
534
|
-
},
|
|
535
|
-
{
|
|
536
|
-
field: 'allDay', label: this.t.translate('crmx.schedule.all_day'), type: 'checkbox',
|
|
537
|
-
defaultValue: false, size: { xl: 6, lg: 6, md: 6, sm: 12 }
|
|
538
|
-
},
|
|
539
|
-
{
|
|
540
|
-
field: 'withRecurrence', label: this.t.translate('crmx.schedule.with_recurrence'), type: 'checkbox',
|
|
541
|
-
defaultValue: false, size: { xl: 6, lg: 6, md: 6, sm: 12 }
|
|
542
|
-
},
|
|
543
|
-
{
|
|
544
|
-
field: 'comments', label: this.t.translate('crmx.schedule.comments'), type: 'textarea',
|
|
545
|
-
placeholder: this.t.translate('crmx.schedule.enter_comments'), rows: 3,
|
|
546
|
-
size: { xl: 12, lg: 12, md: 12, sm: 12 }
|
|
547
|
-
}
|
|
724
|
+
{ field: 'name', label: this.t.translate('crmx.components.schedule_name'), type: 'text', required: true, validators: [Validators.required, Validators.maxLength(MAX_NAME_LENGTH)], placeholder: this.t.translate('crmx.components.schedule_enter_name'), maxLength: MAX_NAME_LENGTH, size: fullRow },
|
|
725
|
+
{ field: 'priority', label: this.t.translate('crmx.components.schedule_priority'), type: 'dropdown', required: true, validators: [Validators.required], options: this.priorityOptions, optionLabel: 'label', optionValue: 'value', defaultValue: SchedulePriority.Medium, size: fullRow },
|
|
726
|
+
{ field: 'type', label: this.t.translate('crmx.components.schedule_type'), type: 'lookup', lookupService: this.scheduleTypeService, lookupDisplayField: 'name', lookupValueField: 'id', lookupSearchFields: ['name'], showClear: true, lookupAutocomplete: true, lookupColumns: [{ field: 'name', header: this.t.translate('crmx.components.schedule_name') }], lookupFilters: "status = 'ACTIVE'", placeholder: this.t.translate('crmx.components.schedule_select_type'), size: fullRow },
|
|
727
|
+
{ field: 'startDate', label: this.t.translate('crmx.components.schedule_start_date'), type: 'date', required: true, validators: [Validators.required], defaultValue: formatDateToString(now), size: (v) => v['withRecurrence'] ? halfRow : fullRow },
|
|
728
|
+
{ field: 'endDate', label: this.t.translate('crmx.components.schedule_end_date'), type: 'date', visibleWhen: (v) => v['withRecurrence'] === true, size: halfRow },
|
|
729
|
+
{ field: 'startTime', label: this.t.translate('crmx.components.schedule_start_time'), type: 'time', defaultValue: defaultStart, visibleWhen: (v) => v['allDay'] !== true, size: halfRow },
|
|
730
|
+
{ field: 'endTime', label: this.t.translate('crmx.components.schedule_end_time'), type: 'time', defaultValue: defaultEnd, visibleWhen: (v) => v['allDay'] !== true, size: halfRow },
|
|
731
|
+
{ field: 'allDay', label: this.t.translate('crmx.components.schedule_all_day'), type: 'checkbox', defaultValue: false, size: halfRow },
|
|
732
|
+
{ field: 'withRecurrence', label: this.t.translate('crmx.components.schedule_with_recurrence'), type: 'checkbox', defaultValue: false, size: halfRow },
|
|
733
|
+
{ field: 'comments', label: this.t.translate('crmx.components.schedule_comments'), type: 'textarea', placeholder: this.t.translate('crmx.components.schedule_enter_comments'), rows: 3, size: fullRow }
|
|
548
734
|
];
|
|
549
735
|
}
|
|
550
|
-
initForm() {
|
|
551
|
-
const now = new Date();
|
|
552
|
-
const currentDayOfWeek = this.getCurrentWeekDay(now);
|
|
553
|
-
const currentMonth = this.getCurrentMonth(now);
|
|
554
|
-
const defaultStart = this.getDefaultStartTime(now);
|
|
555
|
-
const defaultEnd = this.getDefaultEndTime(defaultStart);
|
|
556
|
-
this.scheduleForm = this.fb.group({
|
|
557
|
-
id: [null],
|
|
558
|
-
name: ['', [Validators.required, Validators.maxLength(this.MAX_NAME_LENGTH)]],
|
|
559
|
-
type: [null],
|
|
560
|
-
priority: [SchedulePriority.Medium, Validators.required],
|
|
561
|
-
allDay: [false],
|
|
562
|
-
withRecurrence: [false],
|
|
563
|
-
startDate: [this.formatDate(now), Validators.required],
|
|
564
|
-
endDate: [null],
|
|
565
|
-
startTime: [defaultStart],
|
|
566
|
-
endTime: [defaultEnd],
|
|
567
|
-
recurrence: [ScheduleRecurrence.Daily],
|
|
568
|
-
recurrenceInterval: [1],
|
|
569
|
-
weekDays: [[currentDayOfWeek]],
|
|
570
|
-
repeatWhen: [RepeatWhen.InDay],
|
|
571
|
-
repeatWhenDay: [now.getDate()],
|
|
572
|
-
repeatWhenOrdinalWeekDay: [this.getOrdinalForDate(now)],
|
|
573
|
-
repeatWhenWeekMonth: [currentDayOfWeek],
|
|
574
|
-
repeatWhenMonth: [currentMonth],
|
|
575
|
-
comments: ['']
|
|
576
|
-
});
|
|
577
|
-
}
|
|
578
736
|
onDetailFormReady(form) {
|
|
579
737
|
this.scheduleForm = form;
|
|
580
|
-
|
|
738
|
+
this.addRecurrenceControls();
|
|
739
|
+
this.scheduleForm.valueChanges.subscribe(() => this.recurrenceChange$.next());
|
|
740
|
+
this.setupRecurrenceFormWatchers();
|
|
741
|
+
}
|
|
742
|
+
/** S121: Add braces to all if statements */
|
|
743
|
+
addRecurrenceControls() {
|
|
744
|
+
const now = new Date();
|
|
581
745
|
if (!this.scheduleForm.contains('id')) {
|
|
582
746
|
this.scheduleForm.addControl('id', this.fb.control(null));
|
|
583
747
|
}
|
|
@@ -588,179 +752,218 @@ class ScheduleFormComponent {
|
|
|
588
752
|
this.scheduleForm.addControl('recurrenceInterval', this.fb.control(1));
|
|
589
753
|
}
|
|
590
754
|
if (!this.scheduleForm.contains('weekDays')) {
|
|
591
|
-
this.scheduleForm.addControl('weekDays', this.fb.control([
|
|
755
|
+
this.scheduleForm.addControl('weekDays', this.fb.control([getCurrentWeekDay(now)]));
|
|
592
756
|
}
|
|
593
757
|
if (!this.scheduleForm.contains('repeatWhen')) {
|
|
594
758
|
this.scheduleForm.addControl('repeatWhen', this.fb.control(RepeatWhen.InDay));
|
|
595
759
|
}
|
|
596
760
|
if (!this.scheduleForm.contains('repeatWhenDay')) {
|
|
597
|
-
this.scheduleForm.addControl('repeatWhenDay', this.fb.control(
|
|
761
|
+
this.scheduleForm.addControl('repeatWhenDay', this.fb.control(now.getDate()));
|
|
598
762
|
}
|
|
599
763
|
if (!this.scheduleForm.contains('repeatWhenOrdinalWeekDay')) {
|
|
600
|
-
this.scheduleForm.addControl('repeatWhenOrdinalWeekDay', this.fb.control(
|
|
764
|
+
this.scheduleForm.addControl('repeatWhenOrdinalWeekDay', this.fb.control(getOrdinalForDate(now)));
|
|
601
765
|
}
|
|
602
766
|
if (!this.scheduleForm.contains('repeatWhenWeekMonth')) {
|
|
603
|
-
this.scheduleForm.addControl('repeatWhenWeekMonth', this.fb.control(
|
|
767
|
+
this.scheduleForm.addControl('repeatWhenWeekMonth', this.fb.control(getCurrentWeekDay(now)));
|
|
604
768
|
}
|
|
605
769
|
if (!this.scheduleForm.contains('repeatWhenMonth')) {
|
|
606
|
-
this.scheduleForm.addControl('repeatWhenMonth', this.fb.control(
|
|
770
|
+
this.scheduleForm.addControl('repeatWhenMonth', this.fb.control(getCurrentMonth(now)));
|
|
607
771
|
}
|
|
608
|
-
// Watch for changes
|
|
609
|
-
this.scheduleForm.valueChanges.subscribe(() => {
|
|
610
|
-
this.recurrenceChange$.next();
|
|
611
|
-
});
|
|
612
|
-
this.setupRecurrenceFieldsWatchers();
|
|
613
772
|
}
|
|
614
|
-
|
|
615
|
-
|
|
773
|
+
/**
|
|
774
|
+
* S1541: Break setupRecurrenceFormWatchers into smaller helpers
|
|
775
|
+
* to reduce cyclomatic complexity
|
|
776
|
+
*/
|
|
777
|
+
setupRecurrenceFormWatchers() {
|
|
778
|
+
const d = this.selectedDate || new Date();
|
|
779
|
+
this.watchRecurrenceChanges(d);
|
|
780
|
+
this.watchRepeatWhenChanges(d);
|
|
781
|
+
this.watchWithRecurrenceChanges(d);
|
|
782
|
+
}
|
|
783
|
+
watchRecurrenceChanges(d) {
|
|
616
784
|
this.scheduleForm.get('recurrence')?.valueChanges.subscribe((rec) => {
|
|
617
|
-
this.
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
this.
|
|
621
|
-
});
|
|
622
|
-
this.scheduleForm.get('withRecurrence')?.valueChanges.subscribe((wr) => {
|
|
623
|
-
this.handleWithRecurrenceChange(wr, d);
|
|
785
|
+
this.handleRecurrenceWeekDays(rec, d);
|
|
786
|
+
this.handleRecurrenceMonthlyYearly(rec, d);
|
|
787
|
+
this.handleRecurrenceYearlyMonth(rec, d);
|
|
788
|
+
this.recurrenceChange$.next();
|
|
624
789
|
});
|
|
625
790
|
}
|
|
626
|
-
|
|
627
|
-
this.updateWeekDaysForRecurrence(rec, d);
|
|
628
|
-
this.updateRepeatFieldsForRecurrence(rec, d);
|
|
629
|
-
this.updateMonthFieldForRecurrence(rec, d);
|
|
630
|
-
this.recurrenceChange$.next();
|
|
631
|
-
}
|
|
632
|
-
updateWeekDaysForRecurrence(rec, d) {
|
|
791
|
+
handleRecurrenceWeekDays(rec, d) {
|
|
633
792
|
if (rec === ScheduleRecurrence.Weekly) {
|
|
634
793
|
const current = this.scheduleForm.get('weekDays')?.value;
|
|
635
794
|
if (!current || current.length === 0) {
|
|
636
|
-
this.scheduleForm.patchValue({ weekDays: [
|
|
795
|
+
this.scheduleForm.patchValue({ weekDays: [getCurrentWeekDay(d)] }, { emitEvent: false });
|
|
637
796
|
}
|
|
638
797
|
}
|
|
639
798
|
else {
|
|
640
799
|
this.scheduleForm.patchValue({ weekDays: [] }, { emitEvent: false });
|
|
641
800
|
}
|
|
642
801
|
}
|
|
643
|
-
|
|
644
|
-
if (rec === ScheduleRecurrence.Monthly ||
|
|
802
|
+
handleRecurrenceMonthlyYearly(rec, d) {
|
|
803
|
+
if (rec === ScheduleRecurrence.Monthly ||
|
|
804
|
+
rec === ScheduleRecurrence.Yearly) {
|
|
645
805
|
this.scheduleForm.patchValue({
|
|
646
|
-
repeatWhen: this.scheduleForm.get('repeatWhen')?.value
|
|
647
|
-
repeatWhenDay: this.scheduleForm.get('repeatWhenDay')?.value
|
|
648
|
-
repeatWhenOrdinalWeekDay: this.scheduleForm.get('repeatWhenOrdinalWeekDay')?.value
|
|
649
|
-
|
|
806
|
+
repeatWhen: this.scheduleForm.get('repeatWhen')?.value ?? RepeatWhen.InDay,
|
|
807
|
+
repeatWhenDay: this.scheduleForm.get('repeatWhenDay')?.value ?? d.getDate(),
|
|
808
|
+
repeatWhenOrdinalWeekDay: this.scheduleForm.get('repeatWhenOrdinalWeekDay')?.value
|
|
809
|
+
?? getOrdinalForDate(d),
|
|
810
|
+
repeatWhenWeekMonth: this.scheduleForm.get('repeatWhenWeekMonth')?.value
|
|
811
|
+
?? getCurrentWeekDay(d)
|
|
650
812
|
}, { emitEvent: false });
|
|
651
813
|
}
|
|
652
814
|
else {
|
|
653
815
|
this.scheduleForm.patchValue({
|
|
654
|
-
repeatWhen: null,
|
|
655
|
-
|
|
816
|
+
repeatWhen: null,
|
|
817
|
+
repeatWhenDay: null,
|
|
818
|
+
repeatWhenOrdinalWeekDay: null,
|
|
819
|
+
repeatWhenWeekMonth: null,
|
|
820
|
+
repeatWhenMonth: null
|
|
656
821
|
}, { emitEvent: false });
|
|
657
822
|
}
|
|
658
823
|
}
|
|
659
|
-
|
|
824
|
+
handleRecurrenceYearlyMonth(rec, d) {
|
|
660
825
|
if (rec === ScheduleRecurrence.Yearly) {
|
|
661
826
|
this.scheduleForm.patchValue({
|
|
662
|
-
repeatWhenMonth: this.scheduleForm.get('repeatWhenMonth')?.value
|
|
827
|
+
repeatWhenMonth: this.scheduleForm.get('repeatWhenMonth')?.value
|
|
828
|
+
?? getCurrentMonth(d)
|
|
663
829
|
}, { emitEvent: false });
|
|
664
830
|
}
|
|
665
831
|
else {
|
|
666
832
|
this.scheduleForm.patchValue({ repeatWhenMonth: null }, { emitEvent: false });
|
|
667
833
|
}
|
|
668
834
|
}
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
835
|
+
watchRepeatWhenChanges(d) {
|
|
836
|
+
this.scheduleForm.get('repeatWhen')?.valueChanges.subscribe((rw) => {
|
|
837
|
+
if (rw === RepeatWhen.InDay) {
|
|
838
|
+
this.scheduleForm.patchValue({
|
|
839
|
+
repeatWhenDay: this.scheduleForm.get('repeatWhenDay')?.value ?? d.getDate(),
|
|
840
|
+
repeatWhenOrdinalWeekDay: null,
|
|
841
|
+
repeatWhenWeekMonth: null
|
|
842
|
+
}, { emitEvent: false });
|
|
843
|
+
}
|
|
844
|
+
else if (rw === RepeatWhen.InOrdinalWeekDay) {
|
|
845
|
+
this.scheduleForm.patchValue({
|
|
846
|
+
repeatWhenDay: null,
|
|
847
|
+
repeatWhenOrdinalWeekDay: this.scheduleForm.get('repeatWhenOrdinalWeekDay')?.value
|
|
848
|
+
?? getOrdinalForDate(d),
|
|
849
|
+
repeatWhenWeekMonth: this.scheduleForm.get('repeatWhenWeekMonth')?.value
|
|
850
|
+
?? getCurrentWeekDay(d)
|
|
851
|
+
}, { emitEvent: false });
|
|
852
|
+
}
|
|
853
|
+
else {
|
|
854
|
+
// No action needed for other repeatWhen values
|
|
855
|
+
}
|
|
856
|
+
this.recurrenceChange$.next();
|
|
857
|
+
});
|
|
858
|
+
}
|
|
859
|
+
watchWithRecurrenceChanges(d) {
|
|
860
|
+
this.scheduleForm.get('withRecurrence')?.valueChanges.subscribe(() => {
|
|
861
|
+
const enabled = this.scheduleForm.get('withRecurrence')?.value === true;
|
|
862
|
+
if (enabled) {
|
|
863
|
+
this.onRecurrenceEnabled(d);
|
|
864
|
+
}
|
|
865
|
+
else {
|
|
866
|
+
this.onRecurrenceDisabled();
|
|
867
|
+
}
|
|
868
|
+
});
|
|
869
|
+
}
|
|
870
|
+
onRecurrenceEnabled(d) {
|
|
871
|
+
this.resetRecurrenceDefaults(d);
|
|
683
872
|
this.recurrenceChange$.next();
|
|
684
873
|
}
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
this.recurrenceDescription = '';
|
|
688
|
-
}
|
|
689
|
-
else {
|
|
690
|
-
this.resetRecurrenceDefaults(d);
|
|
691
|
-
this.recurrenceChange$.next();
|
|
692
|
-
}
|
|
874
|
+
onRecurrenceDisabled() {
|
|
875
|
+
this.recurrenceDescription = '';
|
|
693
876
|
}
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
877
|
+
initForm() {
|
|
878
|
+
const now = new Date();
|
|
879
|
+
const defaultStart = this.getDefaultStartTime(now);
|
|
880
|
+
const defaultEnd = this.getDefaultEndTime(defaultStart);
|
|
881
|
+
this.scheduleForm = this.fb.group({
|
|
882
|
+
id: [null],
|
|
883
|
+
name: ['', [Validators.required, Validators.maxLength(MAX_NAME_LENGTH)]],
|
|
884
|
+
type: [null],
|
|
885
|
+
priority: [SchedulePriority.Medium, Validators.required],
|
|
886
|
+
allDay: [false],
|
|
887
|
+
withRecurrence: [false],
|
|
888
|
+
startDate: [
|
|
889
|
+
formatDateToString(this.selectedDate || now),
|
|
890
|
+
Validators.required
|
|
891
|
+
],
|
|
892
|
+
endDate: [null],
|
|
893
|
+
startTime: [defaultStart],
|
|
894
|
+
endTime: [defaultEnd],
|
|
895
|
+
recurrence: [ScheduleRecurrence.Daily],
|
|
896
|
+
recurrenceInterval: [1],
|
|
897
|
+
weekDays: [[getCurrentWeekDay(now)]],
|
|
898
|
+
repeatWhen: [RepeatWhen.InDay],
|
|
899
|
+
repeatWhenDay: [now.getDate()],
|
|
900
|
+
repeatWhenOrdinalWeekDay: [getOrdinalForDate(now)],
|
|
901
|
+
repeatWhenWeekMonth: [getCurrentWeekDay(now)],
|
|
902
|
+
repeatWhenMonth: [getCurrentMonth(now)],
|
|
903
|
+
comments: ['']
|
|
697
904
|
});
|
|
698
905
|
}
|
|
906
|
+
setupRecurrenceDescriptionWatcher() {
|
|
907
|
+
this.recurrenceChange$.pipe(debounceTime(DEBOUNCE_MS)).subscribe(() => this.fetchRecurrenceDescription());
|
|
908
|
+
}
|
|
699
909
|
fetchRecurrenceDescription() {
|
|
700
|
-
if (!this.
|
|
910
|
+
if (!this.scheduleForm) {
|
|
701
911
|
return;
|
|
702
912
|
}
|
|
703
|
-
const payload = this.buildRecurrencePayload();
|
|
704
|
-
this.scheduleService.generateRecurrenceDescription(payload).subscribe({
|
|
705
|
-
next: (r) => { this.recurrenceDescription = r.description || ''; },
|
|
706
|
-
error: () => { this.recurrenceDescription = ''; }
|
|
707
|
-
});
|
|
708
|
-
}
|
|
709
|
-
canFetchRecurrenceDescription() {
|
|
710
|
-
if (!this.scheduleForm || !this.scheduleService) {
|
|
711
|
-
return false;
|
|
712
|
-
}
|
|
713
913
|
const v = this.scheduleForm.value;
|
|
714
914
|
if (!v.withRecurrence || !v.startDate) {
|
|
715
915
|
this.recurrenceDescription = '';
|
|
716
|
-
return
|
|
916
|
+
return;
|
|
717
917
|
}
|
|
718
|
-
|
|
918
|
+
this.scheduleService.generateRecurrenceDescription(this.buildRecurrencePayload(v)).subscribe({
|
|
919
|
+
next: (r) => {
|
|
920
|
+
this.recurrenceDescription = r.description ?? '';
|
|
921
|
+
},
|
|
922
|
+
error: () => {
|
|
923
|
+
this.recurrenceDescription = '';
|
|
924
|
+
}
|
|
925
|
+
});
|
|
719
926
|
}
|
|
720
|
-
buildRecurrencePayload() {
|
|
721
|
-
const v = this.scheduleForm.value;
|
|
927
|
+
buildRecurrencePayload(v) {
|
|
722
928
|
return {
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
recurrenceInterval: v.recurrenceInterval || 1,
|
|
730
|
-
recurrence: v.recurrence,
|
|
731
|
-
weekDays: v.weekDays || null,
|
|
732
|
-
repeatWhen: v.repeatWhen || null,
|
|
733
|
-
repeatWhenDay: v.repeatWhenDay || null,
|
|
734
|
-
repeatWhenOrdinalWeekDay: v.repeatWhenOrdinalWeekDay || null,
|
|
735
|
-
repeatWhenWeekMonth: v.repeatWhenWeekMonth || null,
|
|
736
|
-
repeatWhenMonth: v.repeatWhenMonth || null
|
|
929
|
+
...this.buildDateTimePayload(v),
|
|
930
|
+
allDay: v['allDay'] || false,
|
|
931
|
+
withRecurrence: true,
|
|
932
|
+
recurrenceInterval: v['recurrenceInterval'] || 1,
|
|
933
|
+
recurrence: v['recurrence'],
|
|
934
|
+
...this.buildNullableRecurrenceFields(v)
|
|
737
935
|
};
|
|
738
936
|
}
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
937
|
+
buildDateTimePayload(v) {
|
|
938
|
+
return {
|
|
939
|
+
startDate: toDateString(v['startDate']),
|
|
940
|
+
endDate: v['endDate'] ? toDateString(v['endDate']) : null,
|
|
941
|
+
startTime: v['startTime'] ? toTimeString(v['startTime']) : null,
|
|
942
|
+
endTime: v['endTime'] ? toTimeString(v['endTime']) : null
|
|
943
|
+
};
|
|
944
|
+
}
|
|
945
|
+
buildNullableRecurrenceFields(v) {
|
|
946
|
+
return {
|
|
947
|
+
weekDays: v['weekDays'] ?? null,
|
|
948
|
+
repeatWhen: v['repeatWhen'] ?? null,
|
|
949
|
+
repeatWhenDay: v['repeatWhenDay'] ?? null,
|
|
950
|
+
repeatWhenOrdinalWeekDay: v['repeatWhenOrdinalWeekDay'] ?? null,
|
|
951
|
+
repeatWhenWeekMonth: v['repeatWhenWeekMonth'] ?? null,
|
|
952
|
+
repeatWhenMonth: v['repeatWhenMonth'] ?? null
|
|
953
|
+
};
|
|
954
|
+
}
|
|
955
|
+
loadScheduleTypes() {
|
|
956
|
+
this.scheduleTypeService.list({
|
|
957
|
+
size: 100,
|
|
958
|
+
filterQuery: "status = 'ACTIVE'"
|
|
959
|
+
}).subscribe({
|
|
960
|
+
next: (r) => {
|
|
961
|
+
this.scheduleTypes = r.contents;
|
|
760
962
|
}
|
|
761
963
|
});
|
|
762
964
|
}
|
|
763
|
-
|
|
965
|
+
openNew() {
|
|
966
|
+
this.isEditing = false;
|
|
764
967
|
const now = new Date();
|
|
765
968
|
const defaultStart = this.getDefaultStartTime(now);
|
|
766
969
|
const defaultEnd = this.getDefaultEndTime(defaultStart);
|
|
@@ -769,220 +972,279 @@ class ScheduleFormComponent {
|
|
|
769
972
|
this.detailFormComponent.resetForm();
|
|
770
973
|
}
|
|
771
974
|
this.entityDataForForm = {
|
|
772
|
-
startDate: this.
|
|
975
|
+
startDate: formatDateToString(this.selectedDate || now),
|
|
773
976
|
priority: SchedulePriority.Medium,
|
|
774
977
|
allDay: false,
|
|
775
978
|
withRecurrence: false,
|
|
776
979
|
startTime: defaultStart,
|
|
777
980
|
endTime: defaultEnd
|
|
778
981
|
};
|
|
779
|
-
this.resetRecurrenceDefaults(now);
|
|
982
|
+
this.resetRecurrenceDefaults(this.selectedDate || now);
|
|
780
983
|
this.recurrenceDescription = '';
|
|
984
|
+
this.participants = [];
|
|
781
985
|
this.addedParticipants = [];
|
|
782
986
|
this.selectedParticipantLookup = null;
|
|
987
|
+
this.visible = true;
|
|
988
|
+
this.visibleChange.emit(true);
|
|
783
989
|
}
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
990
|
+
openEdit(scheduleId) {
|
|
991
|
+
this.isEditing = true;
|
|
992
|
+
this.participants = [];
|
|
993
|
+
this.addedParticipants = [];
|
|
994
|
+
this.selectedParticipantLookup = null;
|
|
995
|
+
this.scheduleService.get(scheduleId).subscribe({
|
|
996
|
+
next: (data) => {
|
|
997
|
+
this.entityDataForForm = { ...data, type: data.type ?? null };
|
|
998
|
+
this.loadParticipants(scheduleId);
|
|
999
|
+
this.visible = true;
|
|
1000
|
+
this.visibleChange.emit(true);
|
|
1001
|
+
setTimeout(() => {
|
|
1002
|
+
if (this.scheduleForm) {
|
|
1003
|
+
this.scheduleForm.patchValue({
|
|
1004
|
+
id: data.id,
|
|
1005
|
+
recurrence: data.recurrence,
|
|
1006
|
+
recurrenceInterval: data.recurrenceInterval,
|
|
1007
|
+
weekDays: data.weekDays,
|
|
1008
|
+
repeatWhen: data.repeatWhen,
|
|
1009
|
+
repeatWhenDay: data.repeatWhenDay,
|
|
1010
|
+
repeatWhenOrdinalWeekDay: data.repeatWhenOrdinalWeekDay,
|
|
1011
|
+
repeatWhenWeekMonth: data.repeatWhenWeekMonth,
|
|
1012
|
+
repeatWhenMonth: data.repeatWhenMonth
|
|
1013
|
+
});
|
|
1014
|
+
}
|
|
1015
|
+
});
|
|
1016
|
+
}
|
|
1017
|
+
});
|
|
801
1018
|
}
|
|
802
|
-
// Participants
|
|
803
1019
|
loadParticipants(scheduleId) {
|
|
804
|
-
if (!this.scheduleService) {
|
|
805
|
-
return;
|
|
806
|
-
}
|
|
807
1020
|
this.participantsLoading = true;
|
|
808
1021
|
this.scheduleService.listParticipants(scheduleId).subscribe({
|
|
809
1022
|
next: (r) => {
|
|
810
|
-
|
|
811
|
-
this.addedParticipants = participants
|
|
812
|
-
.filter(
|
|
813
|
-
.map(
|
|
1023
|
+
this.participants = r.contents ?? [];
|
|
1024
|
+
this.addedParticipants = this.participants
|
|
1025
|
+
.filter(p => !p.organizer)
|
|
1026
|
+
.map(p => this.participantToLookup(p))
|
|
814
1027
|
.filter((p) => p !== null);
|
|
815
1028
|
this.participantsLoading = false;
|
|
816
1029
|
},
|
|
817
|
-
error: () => {
|
|
1030
|
+
error: () => {
|
|
1031
|
+
this.participantsLoading = false;
|
|
1032
|
+
}
|
|
818
1033
|
});
|
|
819
1034
|
}
|
|
820
1035
|
participantToLookup(p) {
|
|
821
1036
|
if (p.collaborator) {
|
|
822
|
-
return {
|
|
1037
|
+
return {
|
|
1038
|
+
id: p.collaborator.id,
|
|
1039
|
+
name: p.collaborator.name,
|
|
1040
|
+
origin: 'COLLABORATOR'
|
|
1041
|
+
};
|
|
823
1042
|
}
|
|
824
1043
|
if (p.account) {
|
|
825
|
-
return {
|
|
1044
|
+
return {
|
|
1045
|
+
id: p.account.id,
|
|
1046
|
+
name: p.account.name,
|
|
1047
|
+
origin: 'ACCOUNT'
|
|
1048
|
+
};
|
|
826
1049
|
}
|
|
827
1050
|
if (p.accountContact) {
|
|
828
1051
|
return {
|
|
829
|
-
id: p.accountContact.id,
|
|
830
|
-
|
|
1052
|
+
id: p.accountContact.id,
|
|
1053
|
+
name: p.accountContact.name,
|
|
1054
|
+
referenceName: p.accountContact.account?.name,
|
|
1055
|
+
referenceId: p.accountContact.account?.id,
|
|
831
1056
|
origin: 'ACCOUNT_CONTACT'
|
|
832
1057
|
};
|
|
833
1058
|
}
|
|
834
1059
|
if (p.externalParticipant) {
|
|
835
1060
|
return {
|
|
836
|
-
id: p.externalParticipant.id,
|
|
1061
|
+
id: p.externalParticipant.id,
|
|
1062
|
+
name: p.externalParticipant.name,
|
|
1063
|
+
origin: 'EXTERNAL_PARTICIPANT'
|
|
837
1064
|
};
|
|
838
1065
|
}
|
|
839
1066
|
return null;
|
|
840
1067
|
}
|
|
841
1068
|
onSearchParticipants(event) {
|
|
842
|
-
|
|
843
|
-
return;
|
|
844
|
-
}
|
|
845
|
-
const query = event.query || '';
|
|
846
|
-
this.scheduleService.searchParticipantLookup(query, this.MIN_SEARCH_RESULTS).subscribe({
|
|
1069
|
+
this.scheduleService.searchParticipantLookup(event.query ?? '', PARTICIPANT_SEARCH_LIMIT).subscribe({
|
|
847
1070
|
next: (r) => {
|
|
848
1071
|
const addedIds = new Set(this.addedParticipants.map(p => p.id + p.origin));
|
|
849
|
-
this.participantSuggestions = (r.contents
|
|
1072
|
+
this.participantSuggestions = (r.contents ?? [])
|
|
1073
|
+
.filter(p => !addedIds.has(p.id + p.origin));
|
|
850
1074
|
},
|
|
851
|
-
error: () => {
|
|
1075
|
+
error: () => {
|
|
1076
|
+
this.participantSuggestions = [];
|
|
1077
|
+
}
|
|
852
1078
|
});
|
|
853
1079
|
}
|
|
854
1080
|
onSelectParticipant(participant) {
|
|
855
|
-
|
|
856
|
-
if (!alreadyAdded) {
|
|
1081
|
+
if (!this.addedParticipants.some(p => p.id === participant.id && p.origin === participant.origin)) {
|
|
857
1082
|
this.addedParticipants = [...this.addedParticipants, participant];
|
|
858
1083
|
}
|
|
859
|
-
setTimeout(() => {
|
|
1084
|
+
setTimeout(() => {
|
|
1085
|
+
this.selectedParticipantLookup = null;
|
|
1086
|
+
});
|
|
860
1087
|
}
|
|
861
1088
|
onRemoveParticipant(participant) {
|
|
862
1089
|
this.addedParticipants = this.addedParticipants.filter(p => !(p.id === participant.id && p.origin === participant.origin));
|
|
863
1090
|
}
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
case 'EXTERNAL_PARTICIPANT': return this.t.translate('crmx.schedule.participant_external');
|
|
870
|
-
default: return origin;
|
|
871
|
-
}
|
|
872
|
-
}
|
|
873
|
-
getOriginIcon(origin) {
|
|
874
|
-
switch (origin) {
|
|
875
|
-
case 'ACCOUNT': return 'pi pi-building';
|
|
876
|
-
case 'ACCOUNT_CONTACT': return 'pi pi-id-card';
|
|
877
|
-
case 'COLLABORATOR': return 'pi pi-user';
|
|
878
|
-
case 'EXTERNAL_PARTICIPANT': return 'pi pi-user-plus';
|
|
879
|
-
default: return 'pi pi-user';
|
|
880
|
-
}
|
|
881
|
-
}
|
|
882
|
-
// Save
|
|
883
|
-
handleSave() {
|
|
1091
|
+
/**
|
|
1092
|
+
* S1541: Break onSave into smaller helpers to reduce complexity
|
|
1093
|
+
* S121/S2681: Add braces to all if statements
|
|
1094
|
+
*/
|
|
1095
|
+
onSave() {
|
|
884
1096
|
if (this.scheduleForm.invalid) {
|
|
885
1097
|
this.scheduleForm.markAllAsTouched();
|
|
886
1098
|
return;
|
|
887
1099
|
}
|
|
888
|
-
const
|
|
1100
|
+
const payload = this.buildSavePayload();
|
|
1101
|
+
const op = this.isEditing
|
|
1102
|
+
? this.scheduleService.update(payload['id'], payload)
|
|
1103
|
+
: this.scheduleService.insert(payload);
|
|
1104
|
+
op.pipe(switchMap((result) => this.scheduleService.manageParticipants(this.isEditing ? payload['id'] : result?.['id'], this.buildManageParticipantsPayload()))).subscribe({
|
|
1105
|
+
next: () => {
|
|
1106
|
+
this.visible = false;
|
|
1107
|
+
this.visibleChange.emit(false);
|
|
1108
|
+
this.saved.emit();
|
|
1109
|
+
}
|
|
1110
|
+
});
|
|
1111
|
+
}
|
|
1112
|
+
buildSavePayload() {
|
|
889
1113
|
const payload = {
|
|
890
|
-
...
|
|
891
|
-
type:
|
|
892
|
-
whenOccurs: this.recurrenceDescription
|
|
1114
|
+
...this.scheduleForm.value,
|
|
1115
|
+
type: this.scheduleForm.value.type ?? null,
|
|
1116
|
+
whenOccurs: this.recurrenceDescription ?? null
|
|
893
1117
|
};
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
if (!payload.withRecurrence) {
|
|
909
|
-
payload.endDate = null;
|
|
910
|
-
payload.recurrenceInterval = null;
|
|
911
|
-
payload.weekDays = null;
|
|
912
|
-
payload.repeatWhen = null;
|
|
913
|
-
payload.repeatWhenDay = null;
|
|
914
|
-
payload.repeatWhenOrdinalWeekDay = null;
|
|
915
|
-
payload.repeatWhenWeekMonth = null;
|
|
916
|
-
payload.repeatWhenMonth = null;
|
|
1118
|
+
if (payload['startDate']) {
|
|
1119
|
+
payload['startDate'] = toDateString(payload['startDate']);
|
|
1120
|
+
}
|
|
1121
|
+
if (payload['endDate']) {
|
|
1122
|
+
payload['endDate'] = toDateString(payload['endDate']);
|
|
1123
|
+
}
|
|
1124
|
+
if (payload['startTime']) {
|
|
1125
|
+
payload['startTime'] = toTimeString(payload['startTime']);
|
|
1126
|
+
}
|
|
1127
|
+
if (payload['endTime']) {
|
|
1128
|
+
payload['endTime'] = toTimeString(payload['endTime']);
|
|
1129
|
+
}
|
|
1130
|
+
if (!payload['withRecurrence']) {
|
|
1131
|
+
this.clearRecurrencePayload(payload);
|
|
917
1132
|
}
|
|
918
1133
|
else {
|
|
919
1134
|
this.cleanRecurrenceFields(payload);
|
|
920
1135
|
}
|
|
921
|
-
if (payload
|
|
922
|
-
payload
|
|
923
|
-
payload
|
|
924
|
-
}
|
|
925
|
-
this.onSave.emit({ payload, participants: this.buildManageParticipantsPayload() });
|
|
926
|
-
}
|
|
927
|
-
cleanRecurrenceFields(payload) {
|
|
928
|
-
const rec = payload.recurrence;
|
|
929
|
-
if (rec !== ScheduleRecurrence.Weekly) {
|
|
930
|
-
payload.weekDays = null;
|
|
931
|
-
}
|
|
932
|
-
if (rec === ScheduleRecurrence.Daily || rec === ScheduleRecurrence.Weekly) {
|
|
933
|
-
payload.repeatWhen = null;
|
|
934
|
-
payload.repeatWhenDay = null;
|
|
935
|
-
payload.repeatWhenOrdinalWeekDay = null;
|
|
936
|
-
payload.repeatWhenWeekMonth = null;
|
|
937
|
-
payload.repeatWhenMonth = null;
|
|
938
|
-
}
|
|
939
|
-
if (rec === ScheduleRecurrence.Monthly) {
|
|
940
|
-
payload.repeatWhenMonth = null;
|
|
941
|
-
if (payload.repeatWhen === RepeatWhen.InDay) {
|
|
942
|
-
payload.repeatWhenOrdinalWeekDay = null;
|
|
943
|
-
payload.repeatWhenWeekMonth = null;
|
|
944
|
-
}
|
|
945
|
-
else {
|
|
946
|
-
payload.repeatWhenDay = null;
|
|
947
|
-
}
|
|
948
|
-
}
|
|
949
|
-
if (rec === ScheduleRecurrence.Yearly) {
|
|
950
|
-
if (payload.repeatWhen === RepeatWhen.InDay) {
|
|
951
|
-
payload.repeatWhenOrdinalWeekDay = null;
|
|
952
|
-
payload.repeatWhenWeekMonth = null;
|
|
953
|
-
}
|
|
954
|
-
else {
|
|
955
|
-
payload.repeatWhenDay = null;
|
|
956
|
-
}
|
|
1136
|
+
if (payload['allDay']) {
|
|
1137
|
+
payload['startTime'] = null;
|
|
1138
|
+
payload['endTime'] = null;
|
|
957
1139
|
}
|
|
1140
|
+
return payload;
|
|
1141
|
+
}
|
|
1142
|
+
clearRecurrencePayload(payload) {
|
|
1143
|
+
payload['endDate'] = null;
|
|
1144
|
+
payload['recurrenceInterval'] = null;
|
|
1145
|
+
payload['weekDays'] = null;
|
|
1146
|
+
payload['repeatWhen'] = null;
|
|
1147
|
+
payload['repeatWhenDay'] = null;
|
|
1148
|
+
payload['repeatWhenOrdinalWeekDay'] = null;
|
|
1149
|
+
payload['repeatWhenWeekMonth'] = null;
|
|
1150
|
+
payload['repeatWhenMonth'] = null;
|
|
1151
|
+
}
|
|
1152
|
+
onCancel() {
|
|
1153
|
+
this.visible = false;
|
|
1154
|
+
this.visibleChange.emit(false);
|
|
958
1155
|
}
|
|
959
1156
|
buildManageParticipantsPayload() {
|
|
960
|
-
const
|
|
961
|
-
const
|
|
962
|
-
const
|
|
963
|
-
const
|
|
1157
|
+
const a = [];
|
|
1158
|
+
const ac = [];
|
|
1159
|
+
const c = [];
|
|
1160
|
+
const e = [];
|
|
964
1161
|
for (const p of this.addedParticipants) {
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
1162
|
+
switch (p.origin) {
|
|
1163
|
+
case 'ACCOUNT': {
|
|
1164
|
+
a.push(p.id);
|
|
1165
|
+
break;
|
|
1166
|
+
}
|
|
1167
|
+
case 'ACCOUNT_CONTACT': {
|
|
1168
|
+
ac.push(p.id);
|
|
1169
|
+
break;
|
|
1170
|
+
}
|
|
1171
|
+
case 'COLLABORATOR': {
|
|
1172
|
+
c.push(p.id);
|
|
1173
|
+
break;
|
|
1174
|
+
}
|
|
1175
|
+
case 'EXTERNAL_PARTICIPANT': {
|
|
1176
|
+
e.push(p.id);
|
|
1177
|
+
break;
|
|
1178
|
+
}
|
|
976
1179
|
}
|
|
977
1180
|
}
|
|
978
|
-
return {
|
|
1181
|
+
return {
|
|
1182
|
+
accountsId: a,
|
|
1183
|
+
accountContactsId: ac,
|
|
1184
|
+
collaboratorsId: c,
|
|
1185
|
+
externalParticipantsId: e
|
|
1186
|
+
};
|
|
979
1187
|
}
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
1188
|
+
/**
|
|
1189
|
+
* S1541: Break cleanRecurrenceFields into smaller helpers
|
|
1190
|
+
* S121/S2681: Add braces to all if statements
|
|
1191
|
+
*/
|
|
1192
|
+
cleanRecurrenceFields(p) {
|
|
1193
|
+
const r = p['recurrence'];
|
|
1194
|
+
if (r !== ScheduleRecurrence.Weekly) {
|
|
1195
|
+
p['weekDays'] = null;
|
|
1196
|
+
}
|
|
1197
|
+
this.cleanDailyWeeklyFields(p, r);
|
|
1198
|
+
this.cleanMonthlyFields(p, r);
|
|
1199
|
+
this.cleanYearlyFields(p, r);
|
|
1200
|
+
}
|
|
1201
|
+
cleanDailyWeeklyFields(p, r) {
|
|
1202
|
+
if (r === ScheduleRecurrence.Daily ||
|
|
1203
|
+
r === ScheduleRecurrence.Weekly) {
|
|
1204
|
+
p['repeatWhen'] = null;
|
|
1205
|
+
p['repeatWhenDay'] = null;
|
|
1206
|
+
p['repeatWhenOrdinalWeekDay'] = null;
|
|
1207
|
+
p['repeatWhenWeekMonth'] = null;
|
|
1208
|
+
p['repeatWhenMonth'] = null;
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1211
|
+
cleanMonthlyFields(p, r) {
|
|
1212
|
+
if (r === ScheduleRecurrence.Monthly) {
|
|
1213
|
+
p['repeatWhenMonth'] = null;
|
|
1214
|
+
this.cleanRepeatWhenFields(p);
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
cleanYearlyFields(p, r) {
|
|
1218
|
+
if (r === ScheduleRecurrence.Yearly) {
|
|
1219
|
+
this.cleanRepeatWhenFields(p);
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
cleanRepeatWhenFields(p) {
|
|
1223
|
+
if (p['repeatWhen'] === RepeatWhen.InDay) {
|
|
1224
|
+
p['repeatWhenOrdinalWeekDay'] = null;
|
|
1225
|
+
p['repeatWhenWeekMonth'] = null;
|
|
1226
|
+
}
|
|
1227
|
+
else {
|
|
1228
|
+
p['repeatWhenDay'] = null;
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1231
|
+
resetRecurrenceDefaults(date) {
|
|
1232
|
+
if (!this.scheduleForm) {
|
|
1233
|
+
return;
|
|
1234
|
+
}
|
|
1235
|
+
const d = date || new Date();
|
|
1236
|
+
this.scheduleForm.patchValue({
|
|
1237
|
+
id: null,
|
|
1238
|
+
recurrence: ScheduleRecurrence.Daily,
|
|
1239
|
+
recurrenceInterval: 1,
|
|
1240
|
+
weekDays: [getCurrentWeekDay(d)],
|
|
1241
|
+
repeatWhen: RepeatWhen.InDay,
|
|
1242
|
+
repeatWhenDay: d.getDate(),
|
|
1243
|
+
repeatWhenOrdinalWeekDay: getOrdinalForDate(d),
|
|
1244
|
+
repeatWhenWeekMonth: getCurrentWeekDay(d),
|
|
1245
|
+
repeatWhenMonth: getCurrentMonth(d)
|
|
1246
|
+
});
|
|
984
1247
|
}
|
|
985
|
-
// Getters for template
|
|
986
1248
|
get showRecurrenceFields() {
|
|
987
1249
|
return this.scheduleForm?.get('withRecurrence')?.value === true;
|
|
988
1250
|
}
|
|
@@ -996,135 +1258,53 @@ class ScheduleFormComponent {
|
|
|
996
1258
|
return this.currentRecurrence === ScheduleRecurrence.Weekly;
|
|
997
1259
|
}
|
|
998
1260
|
get showRepeatWhen() {
|
|
999
|
-
return this.currentRecurrence === ScheduleRecurrence.Monthly ||
|
|
1000
|
-
this.currentRecurrence === ScheduleRecurrence.Yearly;
|
|
1261
|
+
return (this.currentRecurrence === ScheduleRecurrence.Monthly ||
|
|
1262
|
+
this.currentRecurrence === ScheduleRecurrence.Yearly);
|
|
1001
1263
|
}
|
|
1002
1264
|
get showRepeatWhenDay() {
|
|
1003
1265
|
return this.showRepeatWhen && this.currentRepeatWhen === RepeatWhen.InDay;
|
|
1004
1266
|
}
|
|
1005
1267
|
get showOrdinalFields() {
|
|
1006
|
-
return this.showRepeatWhen &&
|
|
1268
|
+
return (this.showRepeatWhen &&
|
|
1269
|
+
this.currentRepeatWhen === RepeatWhen.InOrdinalWeekDay);
|
|
1007
1270
|
}
|
|
1008
1271
|
get showMonthField() {
|
|
1009
1272
|
return this.currentRecurrence === ScheduleRecurrence.Yearly;
|
|
1010
1273
|
}
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
}
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
return this.formatDate(value);
|
|
1021
|
-
}
|
|
1022
|
-
const str = String(value);
|
|
1023
|
-
return str.length > 10 ? str.substring(0, 10) : str;
|
|
1024
|
-
}
|
|
1025
|
-
toTimeString(value) {
|
|
1026
|
-
if (!value) {
|
|
1027
|
-
return value;
|
|
1028
|
-
}
|
|
1029
|
-
if (value instanceof Date) {
|
|
1030
|
-
return `${String(value.getHours()).padStart(2, '0')}:${String(value.getMinutes()).padStart(2, '0')}:00`;
|
|
1031
|
-
}
|
|
1032
|
-
const str = String(value);
|
|
1033
|
-
if (str.includes('T')) {
|
|
1034
|
-
const d = new Date(str);
|
|
1035
|
-
return `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}:00`;
|
|
1036
|
-
}
|
|
1037
|
-
if (str.length === 5) {
|
|
1038
|
-
return str + this.TIME_SECONDS_SUFFIX;
|
|
1039
|
-
}
|
|
1040
|
-
else {
|
|
1041
|
-
return str;
|
|
1042
|
-
}
|
|
1043
|
-
}
|
|
1274
|
+
getOriginLabel(o) { return getOriginLabel(this.t, o); }
|
|
1275
|
+
getOriginIcon(o) { return getOriginIcon(o); }
|
|
1276
|
+
getParticipantName(p) { return getParticipantName(p); }
|
|
1277
|
+
getParticipantType(p) { return getParticipantType(this.t, p); }
|
|
1278
|
+
getParticipantTypeIcon(p) { return getParticipantTypeIcon(p); }
|
|
1279
|
+
getPrioritySeverity(p) { return getPrioritySeverity(p); }
|
|
1280
|
+
getPriorityLabel(p) { return getPriorityLabel(this.t, p); }
|
|
1281
|
+
getConfirmationSeverity(c) { return getConfirmationSeverity(c); }
|
|
1282
|
+
getConfirmationLabel(c) { return getConfirmationLabel(this.t, c); }
|
|
1044
1283
|
getDefaultStartTime(d) {
|
|
1045
|
-
|
|
1046
|
-
let m = d.getMinutes();
|
|
1047
|
-
if (m < this.MINUTES_HALF_HOUR) {
|
|
1048
|
-
m = this.MINUTES_HALF_HOUR;
|
|
1049
|
-
}
|
|
1050
|
-
else {
|
|
1051
|
-
h += 1;
|
|
1052
|
-
m = 0;
|
|
1053
|
-
}
|
|
1054
|
-
if (h >= this.HOURS_IN_DAY) {
|
|
1055
|
-
h = 0;
|
|
1056
|
-
}
|
|
1057
|
-
return `${String(h).padStart(2, '0')}:${String(m).padStart(2, '0')}:00`;
|
|
1058
|
-
}
|
|
1059
|
-
getDefaultEndTime(startTime) {
|
|
1060
|
-
const [hStr, mStr] = startTime.split(':');
|
|
1061
|
-
let h = parseInt(hStr, 10);
|
|
1062
|
-
let m = parseInt(mStr, 10) + this.MINUTES_HALF_HOUR;
|
|
1063
|
-
if (m >= this.MINUTES_IN_HOUR) {
|
|
1064
|
-
h += 1;
|
|
1065
|
-
m -= this.MINUTES_IN_HOUR;
|
|
1066
|
-
}
|
|
1067
|
-
if (h >= this.HOURS_IN_DAY) {
|
|
1068
|
-
h = 0;
|
|
1069
|
-
}
|
|
1070
|
-
return `${String(h).padStart(2, '0')}:${String(m).padStart(2, '0')}:00`;
|
|
1071
|
-
}
|
|
1072
|
-
getCurrentWeekDay(d) {
|
|
1073
|
-
return [
|
|
1074
|
-
WeekDay.Sunday, WeekDay.Monday, WeekDay.Tuesday, WeekDay.Wednesday,
|
|
1075
|
-
WeekDay.Thursday, WeekDay.Friday, WeekDay.Saturday
|
|
1076
|
-
][d.getDay()];
|
|
1077
|
-
}
|
|
1078
|
-
getCurrentMonth(d) {
|
|
1079
|
-
return [
|
|
1080
|
-
Month.January, Month.February, Month.March, Month.April, Month.May, Month.June,
|
|
1081
|
-
Month.July, Month.August, Month.September, Month.October, Month.November, Month.December
|
|
1082
|
-
][d.getMonth()];
|
|
1083
|
-
}
|
|
1084
|
-
getOrdinalForDate(d) {
|
|
1085
|
-
const dayOfMonth = d.getDate();
|
|
1086
|
-
const weekNum = Math.ceil(dayOfMonth / this.DAYS_IN_WEEK);
|
|
1087
|
-
const lastDay = new Date(d.getFullYear(), d.getMonth() + 1, 0).getDate();
|
|
1088
|
-
const isLast = dayOfMonth + this.DAYS_IN_WEEK > lastDay;
|
|
1089
|
-
if (isLast && weekNum >= this.ORDINAL_WEEK_THRESHOLD) {
|
|
1090
|
-
return OrdinalWeekDay.Last;
|
|
1091
|
-
}
|
|
1092
|
-
if (weekNum === 1) {
|
|
1093
|
-
return OrdinalWeekDay.First;
|
|
1094
|
-
}
|
|
1095
|
-
else if (weekNum === 2) {
|
|
1096
|
-
return OrdinalWeekDay.Second;
|
|
1097
|
-
}
|
|
1098
|
-
else if (weekNum === this.WEEK_DAYS_IN_MONTH) {
|
|
1099
|
-
return OrdinalWeekDay.Third;
|
|
1100
|
-
}
|
|
1101
|
-
else if (weekNum === this.ORDINAL_WEEK_THRESHOLD) {
|
|
1102
|
-
return OrdinalWeekDay.Fourth;
|
|
1103
|
-
}
|
|
1104
|
-
else {
|
|
1105
|
-
return OrdinalWeekDay.Last;
|
|
1106
|
-
}
|
|
1284
|
+
return getDefaultStartTime(d);
|
|
1107
1285
|
}
|
|
1108
|
-
|
|
1109
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: ScheduleFormComponent, isStandalone: true, selector: "s-schedule-form", inputs: { visible: "visible", scheduleData: "scheduleData" }, outputs: { visibleChange: "visibleChange", onSave: "onSave", onCancel: "onCancel" }, viewQueries: [{ propertyName: "detailFormComponent", first: true, predicate: ["detailForm"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<p-drawer [(visible)]=\"visible\" position=\"right\" [styleClass]=\"'drawer-style'\" [modal]=\"true\">\n <ng-template pTemplate=\"header\">\n <span class=\"drawer-title\">\n <i class=\"pi pi-calendar\"></i>\n {{ isEditing ? ('crmx.schedule.schedule_edit' | translate) : ('crmx.schedule.schedule_new' | translate) }}\n </span>\n </ng-template>\n\n <div class=\"drawer-layout\">\n <!-- Left: Form -->\n <div class=\"drawer-left\">\n <div class=\"drawer-section-header\">\n <i class=\"pi pi-info-circle\"></i>\n <span>{{ 'crmx.schedule.schedule_details' | translate }}</span>\n </div>\n <sia-dynamic-form\n #detailForm\n [sections]=\"[{ fields: scheduleDetailFields }]\"\n [entityData]=\"entityDataForForm\"\n [mode]=\"'form'\"\n [showSubmitButton]=\"false\"\n [showCancelButton]=\"false\"\n (formReady)=\"onDetailFormReady($event)\"\n ></sia-dynamic-form>\n </div>\n\n <!-- Right: Recurrence + Participants -->\n <div class=\"drawer-right\">\n <!-- Recurrence Config -->\n <div class=\"drawer-section\" *ngIf=\"showRecurrenceFields\">\n <div class=\"drawer-section-header\">\n <i class=\"pi pi-replay\"></i>\n <span>{{ 'crmx.schedule.recurrence_config' | translate }}</span>\n </div>\n <form [formGroup]=\"scheduleForm\" class=\"drawer-form\">\n <div class=\"form-row\">\n <div class=\"form-field flex-1\">\n <label for=\"recurrence-select\">\n {{ 'crmx.schedule.recurrence' | translate }}\n </label>\n <p-dropdown \n inputId=\"recurrence-select\"\n formControlName=\"recurrence\" \n [options]=\"recurrenceOptions\" \n optionLabel=\"label\" \n optionValue=\"value\" \n class=\"w-full\">\n </p-dropdown>\n </div>\n <div class=\"form-field flex-1\">\n <label for=\"recurrence-interval-input\">\n {{ 'crmx.schedule.recurrence_interval' | translate }}\n </label>\n <p-inputNumber \n inputId=\"recurrence-interval-input\"\n formControlName=\"recurrenceInterval\" \n [min]=\"1\" \n [max]=\"99\" \n class=\"w-full\">\n </p-inputNumber>\n </div>\n </div>\n <div class=\"form-row\" *ngIf=\"showWeekDays\">\n <div class=\"form-field flex-1\">\n <label for=\"week-days-select\">\n {{ 'crmx.schedule.week_days' | translate }}\n </label>\n <p-multiSelect \n inputId=\"week-days-select\"\n formControlName=\"weekDays\" \n [options]=\"weekDayOptions\" \n optionLabel=\"label\" \n optionValue=\"value\" \n [placeholder]=\"'crmx.schedule.select_week_day' | translate\" \n class=\"w-full\">\n </p-multiSelect>\n </div>\n </div>\n <div class=\"form-row\" *ngIf=\"showRepeatWhen\">\n <div class=\"form-field flex-1\">\n <label for=\"repeat-when-select\">\n {{ 'crmx.schedule.repeat_when' | translate }}\n </label>\n <p-dropdown \n inputId=\"repeat-when-select\"\n formControlName=\"repeatWhen\" \n [options]=\"repeatWhenOptions\" \n optionLabel=\"label\" \n optionValue=\"value\" \n class=\"w-full\">\n </p-dropdown>\n </div>\n <div class=\"form-field flex-1\" *ngIf=\"showRepeatWhenDay\">\n <label for=\"repeat-when-day-input\">\n {{ 'crmx.schedule.repeat_when_day' | translate }}\n </label>\n <p-inputNumber \n inputId=\"repeat-when-day-input\"\n formControlName=\"repeatWhenDay\" \n [min]=\"1\" \n [max]=\"31\" \n class=\"w-full\">\n </p-inputNumber>\n </div>\n <div class=\"form-field flex-1\" *ngIf=\"showOrdinalFields\">\n <label for=\"ordinal-week-day-select\">\n {{ 'crmx.schedule.ordinal_week_day' | translate }}\n </label>\n <p-dropdown \n inputId=\"ordinal-week-day-select\"\n formControlName=\"repeatWhenOrdinalWeekDay\" \n [options]=\"ordinalOptions\" \n optionLabel=\"label\" \n optionValue=\"value\" \n class=\"w-full\">\n </p-dropdown>\n </div>\n <div class=\"form-field flex-1\" *ngIf=\"showOrdinalFields\">\n <label for=\"week-month-select\">\n {{ 'crmx.schedule.week_month' | translate }}\n </label>\n <p-dropdown \n inputId=\"week-month-select\"\n formControlName=\"repeatWhenWeekMonth\" \n [options]=\"weekDayOptions\" \n optionLabel=\"label\" \n optionValue=\"value\" \n class=\"w-full\">\n </p-dropdown>\n </div>\n </div>\n <div class=\"form-row\" *ngIf=\"showMonthField\">\n <div class=\"form-field flex-1\">\n <label for=\"repeat-month-select\">\n {{ 'crmx.schedule.repeat_month' | translate }}\n </label>\n <p-dropdown \n inputId=\"repeat-month-select\"\n formControlName=\"repeatWhenMonth\" \n [options]=\"monthOptions\" \n optionLabel=\"label\" \n optionValue=\"value\" \n class=\"w-full\">\n </p-dropdown>\n </div>\n </div>\n </form>\n <div class=\"recurrence-description\" *ngIf=\"recurrenceDescription\">\n <i class=\"pi pi-info-circle\"></i>\n <span>{{ recurrenceDescription }}</span>\n </div>\n </div>\n\n <p-divider></p-divider>\n\n <!-- Participants -->\n <div class=\"drawer-section\">\n <div class=\"drawer-section-header\">\n <i class=\"pi pi-users\"></i>\n <span>{{ 'crmx.schedule.participants' | translate }}</span>\n </div>\n\n <!-- Autocomplete search -->\n <div class=\"participant-search\">\n <p-autoComplete\n [(ngModel)]=\"selectedParticipantLookup\"\n [suggestions]=\"participantSuggestions\"\n (completeMethod)=\"onSearchParticipants($event)\"\n (onSelect)=\"onSelectParticipant($event.value)\"\n (onFocus)=\"onSearchParticipants({ query: '' })\"\n optionLabel=\"name\"\n [placeholder]=\"'crmx.schedule.search_participant' | translate\"\n [minLength]=\"0\"\n [forceSelection]=\"true\"\n [showClear]=\"true\"\n [fluid]=\"true\"\n >\n <ng-template let-item pTemplate=\"item\">\n <div class=\"participant-suggestion\">\n <i [class]=\"getOriginIcon(item.origin)\"></i>\n <div class=\"participant-suggestion-info\">\n <span class=\"participant-suggestion-name\">{{ item.name }}</span>\n <span class=\"participant-suggestion-detail\" *ngIf=\"item.referenceName\">{{ item.referenceName }}</span>\n </div>\n <span class=\"participant-suggestion-origin\">{{ getOriginLabel(item.origin) }}</span>\n </div>\n </ng-template>\n </p-autoComplete>\n </div>\n\n <sia-loading \n *ngIf=\"participantsLoading\" \n variant=\"dots\" \n color=\"primary\" \n [size]=\"32\" \n padding=\"1.5rem 0\">\n </sia-loading>\n <div *ngIf=\"!participantsLoading && addedParticipants.length === 0\" class=\"participants-empty\">\n <i class=\"pi pi-users\"></i>\n <p>{{ 'crmx.schedule.no_participants' | translate }}</p>\n </div>\n <p-table *ngIf=\"!participantsLoading && addedParticipants.length > 0\" \n [value]=\"addedParticipants\" styleClass=\"p-datatable-sm p-datatable-striped\">\n <ng-template pTemplate=\"header\">\n <tr>\n <th scope=\"col\">{{ 'crmx.schedule.name' | translate }}</th>\n <th scope=\"col\" class=\"table-header-col\">\n {{ 'crmx.schedule.participant_type' | translate }}\n </th>\n <th scope=\"col\" class=\"table-action-col\"></th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\" let-p>\n <tr>\n <td>\n <div class=\"participant-name-cell\">\n <span>{{ p.name }}</span>\n <span *ngIf=\"p.referenceName\" class=\"participant-reference\">{{ p.referenceName }}</span>\n </div>\n </td>\n <td>\n <div class=\"participant-type-cell\">\n <i [class]=\"getOriginIcon(p.origin)\"></i>\n <span>{{ getOriginLabel(p.origin) }}</span>\n </div>\n </td>\n <td>\n <p-button icon=\"pi pi-trash\" [rounded]=\"true\" [text]=\"true\" severity=\"danger\" \n (onClick)=\"onRemoveParticipant(p)\" \n [pTooltip]=\"'crmx.schedule.remove' | translate\" tooltipPosition=\"top\"></p-button>\n </td>\n </tr>\n </ng-template>\n </p-table>\n </div>\n </div>\n </div>\n\n <ng-template pTemplate=\"footer\">\n <div class=\"drawer-footer\">\n <p-button [label]=\"'crmx.schedule.cancel' | translate\" icon=\"pi pi-times\" \n severity=\"secondary\" [outlined]=\"true\" (onClick)=\"handleCancel()\"></p-button>\n <p-button [label]=\"'crmx.schedule.save' | translate\" icon=\"pi pi-check\" \n (onClick)=\"handleSave()\"></p-button>\n </div>\n </ng-template>\n</p-drawer>\n", styles: [".drawer-title{display:flex;align-items:center;gap:.75rem;font-size:1.15rem;font-weight:600;color:var(--p-text-color)}.drawer-title i{color:var(--p-primary-color)}.drawer-layout{display:flex;gap:0;height:100%}.drawer-left{width:380px;min-width:380px;border-right:1px solid var(--p-surface-200);padding:0 1.5rem 1.5rem 0;overflow-y:auto}.drawer-right{flex:1;padding:0 0 0 1.5rem;overflow-y:auto}.drawer-section-header{display:flex;align-items:center;gap:.5rem;padding-bottom:1rem;margin-bottom:1rem;border-bottom:1px solid var(--p-surface-200);font-weight:600;font-size:.95rem;color:var(--p-text-color)}.drawer-section-header i{color:var(--p-primary-color);font-size:1rem}.drawer-form{display:flex;flex-direction:column;gap:1rem}.drawer-form .form-field{display:flex;flex-direction:column;gap:.375rem}.drawer-form .form-field label{font-weight:500;font-size:.8rem;color:var(--p-text-secondary-color);text-transform:uppercase;letter-spacing:.3px}.drawer-form .form-row{display:flex;gap:1rem}.drawer-form .form-row.checkboxes{gap:2rem;padding:.5rem 0}.drawer-form .form-check{display:flex;align-items:center;gap:.5rem}.drawer-form .form-check label{font-size:.875rem;font-weight:500;margin:0;text-transform:none;letter-spacing:0}.drawer-section{margin-bottom:1.5rem}.recurrence-description{display:flex;align-items:flex-start;gap:.5rem;margin-top:1rem;padding:.75rem 1rem;background:var(--p-primary-50);border-left:3px solid var(--p-primary-color);border-radius:4px;font-size:.85rem;color:var(--p-text-color);line-height:1.4}.recurrence-description i{color:var(--p-primary-color);margin-top:.1rem;flex-shrink:0}.participants-empty{display:flex;flex-direction:column;align-items:center;padding:2rem;text-align:center;color:var(--p-text-secondary-color);border:1px dashed var(--p-surface-300);border-radius:8px}.participants-empty i{font-size:2rem;margin-bottom:.5rem;opacity:.4}.participants-empty p{margin:0}.participant-name-cell{display:flex;align-items:center;gap:.5rem}.participant-name-cell .organizer-tag{font-size:.7rem}.participant-type-cell{display:flex;align-items:center;gap:.5rem;font-size:.85rem;color:var(--p-text-secondary-color)}.participant-type-cell i{font-size:.9rem}.drawer-footer{display:flex;gap:.75rem;justify-content:flex-end}.table-header-col{width:10rem}.table-action-col{width:4rem}@media (max-width: 768px){.drawer-layout{flex-direction:column}.drawer-left{width:100%;min-width:100%;border-right:none;border-bottom:1px solid var(--p-surface-200);padding:0 0 1.5rem}.drawer-right{padding:1.5rem 0 0}}.participant-search{margin-bottom:1rem}.participant-search :host ::ng-deep .p-autocomplete{width:100%;display:flex}.participant-search :host ::ng-deep .p-autocomplete-input{width:100%}.participant-suggestion{display:flex;align-items:center;gap:.75rem;padding:.25rem 0}.participant-suggestion i{font-size:1.1rem;color:var(--p-text-secondary-color)}.participant-suggestion-info{display:flex;flex-direction:column;flex:1;min-width:0}.participant-suggestion-name{font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.participant-suggestion-detail{font-size:.8rem;color:var(--p-text-secondary-color)}.participant-suggestion-origin{font-size:.75rem;color:var(--p-text-secondary-color);white-space:nowrap}.participant-reference{font-size:.8rem;color:var(--p-text-secondary-color);margin-left:.25rem}.drawer-style{width:85vw;max-width:1200px}:host-context(.p-dark) .drawer-left{border-color:var(--p-surface-300)}:host-context(.p-dark) .drawer-section-header{border-color:var(--p-surface-300)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: DrawerModule }, { kind: "component", type: i6.Drawer, selector: "p-drawer", inputs: ["appendTo", "blockScroll", "style", "styleClass", "ariaCloseLabel", "autoZIndex", "baseZIndex", "modal", "closeButtonProps", "dismissible", "showCloseIcon", "closeOnEscape", "transitionOptions", "visible", "position", "fullScreen", "header", "maskStyle", "closable"], outputs: ["onShow", "onHide", "visibleChange"] }, { kind: "directive", type: i2$1.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i8.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "fluid", "buttonProps"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: DropdownModule }, { kind: "component", type: i9.Dropdown, selector: "p-dropdown", inputs: ["id", "scrollHeight", "filter", "name", "style", "panelStyle", "styleClass", "panelStyleClass", "readonly", "required", "editable", "appendTo", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "variant", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "autoDisplayFirst", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "maxlength", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "fluid", "disabled", "itemSize", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "filterValue", "options"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: InputNumberModule }, { kind: "component", type: i10.InputNumber, selector: "p-inputNumber, p-inputnumber, p-input-number", inputs: ["showButtons", "format", "buttonLayout", "inputId", "styleClass", "style", "placeholder", "size", "maxlength", "tabindex", "title", "ariaLabelledBy", "ariaLabel", "ariaRequired", "name", "required", "autocomplete", "min", "max", "incrementButtonClass", "decrementButtonClass", "incrementButtonIcon", "decrementButtonIcon", "readonly", "step", "allowEmpty", "locale", "localeMatcher", "mode", "currency", "currencyDisplay", "useGrouping", "variant", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "inputStyle", "inputStyleClass", "showClear", "autofocus", "disabled", "fluid"], outputs: ["onInput", "onFocus", "onBlur", "onKeyDown", "onClear"] }, { kind: "ngmodule", type: MultiSelectModule }, { kind: "component", type: i11.MultiSelect, selector: "p-multiSelect, p-multiselect, p-multi-select", inputs: ["id", "ariaLabel", "style", "styleClass", "panelStyle", "panelStyleClass", "inputId", "disabled", "fluid", "readonly", "group", "filter", "filterPlaceHolder", "filterLocale", "overlayVisible", "tabindex", "variant", "appendTo", "dataKey", "name", "ariaLabelledBy", "displaySelectedLabel", "maxSelectedLabels", "selectionLimit", "selectedItemsLabel", "showToggleAll", "emptyFilterMessage", "emptyMessage", "resetFilterOnHide", "dropdownIcon", "chipIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "showHeader", "filterBy", "scrollHeight", "lazy", "virtualScroll", "loading", "virtualScrollItemSize", "loadingIcon", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "autofocusFilter", "display", "autocomplete", "size", "showClear", "autofocus", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "defaultLabel", "placeholder", "options", "filterValue", "itemSize", "selectAll", "focusOnHover", "filterFields", "selectOnFocus", "autoOptionFocus"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onClear", "onPanelShow", "onPanelHide", "onLazyLoad", "onRemove", "onSelectAllChange"] }, { kind: "ngmodule", type: DividerModule }, { kind: "component", type: i12.Divider, selector: "p-divider", inputs: ["style", "styleClass", "layout", "type", "align"] }, { kind: "ngmodule", type: TableModule }, { kind: "component", type: i13.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "style", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "scrollDirection", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "responsive", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "autoLayout", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "virtualRowHeight", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "ngmodule", type: AutoCompleteModule }, { kind: "component", type: i14.AutoComplete, selector: "p-autoComplete, p-autocomplete, p-auto-complete", inputs: ["minLength", "delay", "style", "panelStyle", "styleClass", "panelStyleClass", "inputStyle", "inputId", "inputStyleClass", "placeholder", "readonly", "disabled", "scrollHeight", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "maxlength", "name", "required", "size", "appendTo", "autoHighlight", "forceSelection", "type", "autoZIndex", "baseZIndex", "ariaLabel", "dropdownAriaLabel", "ariaLabelledBy", "dropdownIcon", "unique", "group", "completeOnFocus", "showClear", "field", "dropdown", "showEmptyMessage", "dropdownMode", "multiple", "tabindex", "dataKey", "emptyMessage", "showTransitionOptions", "hideTransitionOptions", "autofocus", "autocomplete", "optionGroupChildren", "optionGroupLabel", "overlayOptions", "suggestions", "itemSize", "optionLabel", "optionValue", "id", "searchMessage", "emptySelectionMessage", "selectionMessage", "autoOptionFocus", "selectOnFocus", "searchLocale", "optionDisabled", "focusOnHover", "typeahead", "variant", "fluid"], outputs: ["completeMethod", "onSelect", "onUnselect", "onFocus", "onBlur", "onDropdownClick", "onClear", "onKeyUp", "onShow", "onHide", "onLazyLoad"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i15.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }, { kind: "component", type: LoadingComponent, selector: "sia-loading", inputs: ["variant", "color", "size", "text", "padding"] }, { kind: "component", type: DynamicFormComponent, selector: "sia-dynamic-form", inputs: ["sections", "entityData", "mode", "displayMode", "visible", "dialogConfig", "drawerConfig", "showSubmitButton", "showCancelButton", "submitButtonLabel", "cancelButtonLabel", "submitButtonIcon", "cancelButtonIcon"], outputs: ["formReady", "formSubmit", "visibleChange", "onCancel", "fieldSave"] }] });
|
|
1286
|
+
getDefaultEndTime(st) {
|
|
1287
|
+
return getDefaultEndTime(st);
|
|
1288
|
+
}
|
|
1289
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScheduleFormComponent, deps: [{ token: i1$1.FormBuilder }, { token: ScheduleService }, { token: ScheduleTypeService }, { token: CurrentCollaboratorService }, { token: i5.TranslationService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1290
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: ScheduleFormComponent, isStandalone: true, selector: "s-schedule-form", inputs: { visible: "visible", selectedDate: "selectedDate" }, outputs: { visibleChange: "visibleChange", saved: "saved" }, viewQueries: [{ propertyName: "detailFormComponent", first: true, predicate: ["detailForm"], descendants: true }], ngImport: i0, template: "<!-- Schedule Drawer -->\n<p-drawer\n [(visible)]=\"visible\"\n position=\"right\"\n styleClass=\"schedule-drawer\"\n [modal]=\"true\"\n (onHide)=\"onCancel()\"\n>\n <ng-template pTemplate=\"header\">\n <span class=\"drawer-title\">\n <i class=\"pi pi-calendar\"></i>\n {{\n isEditing\n ? ('crmx.components.schedule_schedule_edit' | translate)\n : ('crmx.components.schedule_schedule_new' | translate)\n }}\n </span>\n </ng-template>\n\n <div class=\"drawer-layout\" *ngIf=\"scheduleForm\">\n <!-- Left: Form -->\n <div class=\"drawer-left\">\n <div class=\"drawer-section-header\">\n <i class=\"pi pi-info-circle\"></i>\n <span>\n {{ 'crmx.components.schedule_schedule_details' | translate }}\n </span>\n </div>\n <sia-dynamic-form\n #detailForm\n [sections]=\"[{ fields: scheduleDetailFields }]\"\n [entityData]=\"entityDataForForm\"\n [mode]=\"'form'\"\n [showSubmitButton]=\"false\"\n [showCancelButton]=\"false\"\n (formReady)=\"onDetailFormReady($event)\"\n ></sia-dynamic-form>\n </div>\n\n <!-- Right: Recurrence + Participants -->\n <div class=\"drawer-right\">\n <div\n class=\"drawer-section\"\n *ngIf=\"showRecurrenceFields\"\n >\n <div class=\"drawer-section-header\">\n <i class=\"pi pi-replay\"></i>\n <span>\n {{\n 'crmx.components.schedule_recurrence_config'\n | translate\n }}\n </span>\n </div>\n <form\n [formGroup]=\"scheduleForm\"\n class=\"drawer-form\"\n >\n <div class=\"form-row\">\n <div class=\"form-field flex-1\">\n <label for=\"recurrence\">\n {{ 'crmx.components.schedule_recurrence' | translate }}\n </label>\n <p-dropdown\n id=\"recurrence\"\n formControlName=\"recurrence\"\n [options]=\"recurrenceOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n class=\"w-full\"\n ></p-dropdown>\n </div>\n <div class=\"form-field flex-1\">\n <label for=\"recurrenceInterval\">\n {{\n 'crmx.components.schedule_recurrence_interval'\n | translate\n }}\n </label>\n <p-inputNumber\n id=\"recurrenceInterval\"\n formControlName=\"recurrenceInterval\"\n [min]=\"1\"\n [max]=\"99\"\n class=\"w-full\"\n ></p-inputNumber>\n </div>\n </div>\n <div\n class=\"form-row\"\n *ngIf=\"showWeekDays\"\n >\n <div class=\"form-field flex-1\">\n <label for=\"weekDays\">\n {{ 'crmx.components.schedule_week_days' | translate }}\n </label>\n <p-multiSelect\n id=\"weekDays\"\n formControlName=\"weekDays\"\n [options]=\"weekDayOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"\n 'crmx.components.schedule_select_week_day'\n | translate\n \"\n class=\"w-full\"\n ></p-multiSelect>\n </div>\n </div>\n <div\n class=\"form-row\"\n *ngIf=\"showRepeatWhen\"\n >\n <div class=\"form-field flex-1\">\n <label for=\"repeatWhen\">\n {{\n 'crmx.components.schedule_repeat_when' | translate\n }}\n </label>\n <p-dropdown\n id=\"repeatWhen\"\n formControlName=\"repeatWhen\"\n [options]=\"repeatWhenOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n class=\"w-full\"\n ></p-dropdown>\n </div>\n <div\n class=\"form-field flex-1\"\n *ngIf=\"showRepeatWhenDay\"\n >\n <label for=\"repeatWhenDay\">\n {{\n 'crmx.components.schedule_repeat_when_day'\n | translate\n }}\n </label>\n <p-inputNumber\n id=\"repeatWhenDay\"\n formControlName=\"repeatWhenDay\"\n [min]=\"1\"\n [max]=\"31\"\n class=\"w-full\"\n ></p-inputNumber>\n </div>\n <div\n class=\"form-field flex-1\"\n *ngIf=\"showOrdinalFields\"\n >\n <label for=\"repeatWhenOrdinalWeekDay\">\n {{\n 'crmx.components.schedule_ordinal_week_day'\n | translate\n }}\n </label>\n <p-dropdown\n id=\"repeatWhenOrdinalWeekDay\"\n formControlName=\"repeatWhenOrdinalWeekDay\"\n [options]=\"ordinalOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n class=\"w-full\"\n ></p-dropdown>\n </div>\n <div\n class=\"form-field flex-1\"\n *ngIf=\"showOrdinalFields\"\n >\n <label for=\"repeatWhenWeekMonth\">\n {{\n 'crmx.components.schedule_week_month' | translate\n }}\n </label>\n <p-dropdown\n id=\"repeatWhenWeekMonth\"\n formControlName=\"repeatWhenWeekMonth\"\n [options]=\"weekDayOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n class=\"w-full\"\n ></p-dropdown>\n </div>\n </div>\n <div\n class=\"form-row\"\n *ngIf=\"showMonthField\"\n >\n <div class=\"form-field flex-1\">\n <label for=\"repeatWhenMonth\">\n {{\n 'crmx.components.schedule_repeat_month' | translate\n }}\n </label>\n <p-dropdown\n id=\"repeatWhenMonth\"\n formControlName=\"repeatWhenMonth\"\n [options]=\"monthOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n class=\"w-full\"\n ></p-dropdown>\n </div>\n </div>\n </form>\n <div\n class=\"recurrence-description\"\n *ngIf=\"recurrenceDescription\"\n >\n <i class=\"pi pi-info-circle\"></i>\n <span>{{ recurrenceDescription }}</span>\n </div>\n </div>\n\n <p-divider></p-divider>\n\n <!-- Participants -->\n <div class=\"drawer-section\">\n <div class=\"drawer-section-header\">\n <i class=\"pi pi-users\"></i>\n <span>\n {{ 'crmx.components.schedule_participants' | translate }}\n </span>\n </div>\n <div class=\"participant-search\">\n <p-autoComplete\n [(ngModel)]=\"selectedParticipantLookup\"\n [ngModelOptions]=\"{standalone: true}\"\n [suggestions]=\"participantSuggestions\"\n (completeMethod)=\"\n onSearchParticipants($event)\n \"\n (onSelect)=\"\n onSelectParticipant($event.value)\n \"\n (onFocus)=\"\n onSearchParticipants({ query: '' })\n \"\n optionLabel=\"name\"\n [placeholder]=\"\n 'crmx.components.schedule_search_participant'\n | translate\n \"\n [minLength]=\"0\"\n [forceSelection]=\"true\"\n [showClear]=\"true\"\n [fluid]=\"true\"\n >\n <ng-template\n let-item\n pTemplate=\"item\"\n >\n <div class=\"participant-suggestion\">\n <i\n [class]=\"getOriginIcon(item.origin)\"\n ></i>\n <div\n class=\"participant-suggestion-info\"\n >\n <span\n class=\"participant-suggestion-name\"\n >\n {{ item.name }}\n </span>\n <span\n class=\"participant-suggestion-detail\"\n *ngIf=\"item.referenceName\"\n >\n {{ item.referenceName }}\n </span>\n </div>\n <span\n class=\"participant-suggestion-origin\"\n >\n {{ getOriginLabel(item.origin) }}\n </span>\n </div>\n </ng-template>\n </p-autoComplete>\n </div>\n <div\n *ngIf=\"\n !participantsLoading &&\n addedParticipants.length === 0\n \"\n class=\"participants-empty\"\n >\n <i class=\"pi pi-users\"></i>\n <p>\n {{\n 'crmx.components.schedule_no_participants'\n | translate\n }}\n </p>\n </div>\n <p-table\n *ngIf=\"\n !participantsLoading &&\n addedParticipants.length > 0\n \"\n [value]=\"addedParticipants\"\n styleClass=\"p-datatable-sm p-datatable-striped\"\n >\n <ng-template pTemplate=\"header\">\n <tr>\n <th scope=\"col\">\n {{ 'crmx.components.schedule_name' | translate }}\n </th>\n <th\n scope=\"col\"\n class=\"col-participant-type\"\n >\n {{\n 'crmx.components.schedule_participant_type'\n | translate\n }}\n </th>\n <th\n scope=\"col\"\n class=\"col-actions\"\n ></th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\" let-p>\n <tr>\n <td>\n <div class=\"participant-name-cell\">\n <span>{{ p.name }}</span>\n <span\n *ngIf=\"p.referenceName\"\n class=\"participant-reference\"\n >\n {{ p.referenceName }}\n </span>\n </div>\n </td>\n <td>\n <div class=\"participant-type-cell\">\n <i\n [class]=\"getOriginIcon(p.origin)\"\n ></i>\n <span>\n {{ getOriginLabel(p.origin) }}\n </span>\n </div>\n </td>\n <td>\n <p-button\n icon=\"pi pi-trash\"\n [rounded]=\"true\"\n [text]=\"true\"\n severity=\"danger\"\n (onClick)=\"onRemoveParticipant(p)\"\n [pTooltip]=\"\n 'crmx.components.schedule_remove' | translate\n \"\n tooltipPosition=\"top\"\n ></p-button>\n </td>\n </tr>\n </ng-template>\n </p-table>\n </div>\n </div>\n </div>\n\n <ng-template pTemplate=\"footer\">\n <div class=\"drawer-footer\">\n <p-button\n [label]=\"'crmx.components.schedule_cancel' | translate\"\n icon=\"pi pi-times\"\n severity=\"secondary\"\n [outlined]=\"true\"\n (onClick)=\"onCancel()\"\n ></p-button>\n <p-button\n [label]=\"'crmx.components.schedule_save' | translate\"\n icon=\"pi pi-check\"\n (onClick)=\"onSave()\"\n ></p-button>\n </div>\n </ng-template>\n</p-drawer>\n", styles: [":host ::ng-deep .schedule-drawer{width:85vw;max-width:1200px}.col-participant-type{width:10rem}.col-actions{width:4rem}.drawer-title{display:flex;align-items:center;gap:.75rem;font-size:1.15rem;font-weight:600;color:var(--p-text-color)}.drawer-title i{color:var(--p-primary-color)}.drawer-layout{display:flex;gap:0;height:100%}.drawer-left{width:380px;min-width:380px;border-right:1px solid var(--p-surface-200);padding:0 1.5rem 1.5rem 0;overflow-y:auto}.drawer-right{flex:1;padding:0 0 0 1.5rem;overflow-y:auto}.drawer-section-header{display:flex;align-items:center;gap:.5rem;padding-bottom:1rem;margin-bottom:1rem;border-bottom:1px solid var(--p-surface-200);font-weight:600;font-size:.95rem;color:var(--p-text-color)}.drawer-section-header i{color:var(--p-primary-color);font-size:1rem}.drawer-form{display:flex;flex-direction:column;gap:1rem}.drawer-form .form-field{display:flex;flex-direction:column;gap:.375rem}.drawer-form .form-field label{font-weight:500;font-size:.8rem;color:var(--p-text-secondary-color);text-transform:uppercase;letter-spacing:.3px}.drawer-form .form-row{display:flex;gap:1rem}.drawer-form .form-row.checkboxes{gap:2rem;padding:.5rem 0}.drawer-form .form-check{display:flex;align-items:center;gap:.5rem}.drawer-form .form-check label{font-size:.875rem;font-weight:500;margin:0;text-transform:none;letter-spacing:0}.drawer-section{margin-bottom:1.5rem}.recurrence-description{display:flex;align-items:flex-start;gap:.5rem;margin-top:1rem;padding:.75rem 1rem;background:var(--p-primary-50);border-left:3px solid var(--p-primary-color);border-radius:4px;font-size:.85rem;color:var(--p-text-color);line-height:1.4}.recurrence-description i{color:var(--p-primary-color);margin-top:.1rem;flex-shrink:0}.participants-empty{display:flex;flex-direction:column;align-items:center;padding:2rem;text-align:center;color:var(--p-text-secondary-color);border:1px dashed var(--p-surface-300);border-radius:8px}.participants-empty i{font-size:2rem;margin-bottom:.5rem;opacity:.4}.participants-empty p{margin:0}.participant-name-cell{display:flex;align-items:center;gap:.5rem}.participant-type-cell{display:flex;align-items:center;gap:.5rem;font-size:.85rem;color:var(--p-text-secondary-color)}.participant-type-cell i{font-size:.9rem}.drawer-footer{display:flex;gap:.75rem;justify-content:flex-end}.participant-search{margin-bottom:1rem}.participant-search :host ::ng-deep .p-autocomplete{width:100%;display:flex}.participant-search :host ::ng-deep .p-autocomplete-input{width:100%}.participant-suggestion{display:flex;align-items:center;gap:.75rem;padding:.25rem 0}.participant-suggestion i{font-size:1.1rem;color:var(--p-text-secondary-color)}.participant-suggestion-info{display:flex;flex-direction:column;flex:1;min-width:0}.participant-suggestion-name{font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.participant-suggestion-detail{font-size:.8rem;color:var(--p-text-secondary-color)}.participant-suggestion-origin{font-size:.75rem;color:var(--p-text-secondary-color);white-space:nowrap}.participant-reference{font-size:.8rem;color:var(--p-text-secondary-color);margin-left:.25rem}.detail-dialog-body{display:flex;flex-direction:column;gap:.5rem}.detail-dialog-row{display:flex;align-items:center;gap:.75rem;padding:.4rem 0}.detail-label{font-weight:500;color:var(--p-text-secondary-color);min-width:8rem}@media (max-width: 768px){.drawer-layout{flex-direction:column}.drawer-left{width:100%;min-width:100%;border-right:none;border-bottom:1px solid var(--p-surface-200);padding:0 0 1.5rem}.drawer-right{padding:1.5rem 0 0}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i7.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "fluid", "buttonProps"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "directive", type: i8.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: DialogModule }, { kind: "ngmodule", type: DrawerModule }, { kind: "component", type: i9.Drawer, selector: "p-drawer", inputs: ["appendTo", "blockScroll", "style", "styleClass", "ariaCloseLabel", "autoZIndex", "baseZIndex", "modal", "closeButtonProps", "dismissible", "showCloseIcon", "closeOnEscape", "transitionOptions", "visible", "position", "fullScreen", "header", "maskStyle", "closable"], outputs: ["onShow", "onHide", "visibleChange"] }, { kind: "ngmodule", type: DropdownModule }, { kind: "component", type: i10.Dropdown, selector: "p-dropdown", inputs: ["id", "scrollHeight", "filter", "name", "style", "panelStyle", "styleClass", "panelStyleClass", "readonly", "required", "editable", "appendTo", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "variant", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "autoDisplayFirst", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "maxlength", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "fluid", "disabled", "itemSize", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "filterValue", "options"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: InputNumberModule }, { kind: "component", type: i11.InputNumber, selector: "p-inputNumber, p-inputnumber, p-input-number", inputs: ["showButtons", "format", "buttonLayout", "inputId", "styleClass", "style", "placeholder", "size", "maxlength", "tabindex", "title", "ariaLabelledBy", "ariaLabel", "ariaRequired", "name", "required", "autocomplete", "min", "max", "incrementButtonClass", "decrementButtonClass", "incrementButtonIcon", "decrementButtonIcon", "readonly", "step", "allowEmpty", "locale", "localeMatcher", "mode", "currency", "currencyDisplay", "useGrouping", "variant", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "inputStyle", "inputStyleClass", "showClear", "autofocus", "disabled", "fluid"], outputs: ["onInput", "onFocus", "onBlur", "onKeyDown", "onClear"] }, { kind: "ngmodule", type: MultiSelectModule }, { kind: "component", type: i12.MultiSelect, selector: "p-multiSelect, p-multiselect, p-multi-select", inputs: ["id", "ariaLabel", "style", "styleClass", "panelStyle", "panelStyleClass", "inputId", "disabled", "fluid", "readonly", "group", "filter", "filterPlaceHolder", "filterLocale", "overlayVisible", "tabindex", "variant", "appendTo", "dataKey", "name", "ariaLabelledBy", "displaySelectedLabel", "maxSelectedLabels", "selectionLimit", "selectedItemsLabel", "showToggleAll", "emptyFilterMessage", "emptyMessage", "resetFilterOnHide", "dropdownIcon", "chipIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "showHeader", "filterBy", "scrollHeight", "lazy", "virtualScroll", "loading", "virtualScrollItemSize", "loadingIcon", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "autofocusFilter", "display", "autocomplete", "size", "showClear", "autofocus", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "defaultLabel", "placeholder", "options", "filterValue", "itemSize", "selectAll", "focusOnHover", "filterFields", "selectOnFocus", "autoOptionFocus"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onClear", "onPanelShow", "onPanelHide", "onLazyLoad", "onRemove", "onSelectAllChange"] }, { kind: "ngmodule", type: TagModule }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i13.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { kind: "ngmodule", type: DividerModule }, { kind: "component", type: i14.Divider, selector: "p-divider", inputs: ["style", "styleClass", "layout", "type", "align"] }, { kind: "ngmodule", type: TableModule }, { kind: "component", type: i15.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "style", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "scrollDirection", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "responsive", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "autoLayout", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "virtualRowHeight", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "ngmodule", type: AutoCompleteModule }, { kind: "component", type: i16.AutoComplete, selector: "p-autoComplete, p-autocomplete, p-auto-complete", inputs: ["minLength", "delay", "style", "panelStyle", "styleClass", "panelStyleClass", "inputStyle", "inputId", "inputStyleClass", "placeholder", "readonly", "disabled", "scrollHeight", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "maxlength", "name", "required", "size", "appendTo", "autoHighlight", "forceSelection", "type", "autoZIndex", "baseZIndex", "ariaLabel", "dropdownAriaLabel", "ariaLabelledBy", "dropdownIcon", "unique", "group", "completeOnFocus", "showClear", "field", "dropdown", "showEmptyMessage", "dropdownMode", "multiple", "tabindex", "dataKey", "emptyMessage", "showTransitionOptions", "hideTransitionOptions", "autofocus", "autocomplete", "optionGroupChildren", "optionGroupLabel", "overlayOptions", "suggestions", "itemSize", "optionLabel", "optionValue", "id", "searchMessage", "emptySelectionMessage", "selectionMessage", "autoOptionFocus", "selectOnFocus", "searchLocale", "optionDisabled", "focusOnHover", "typeahead", "variant", "fluid"], outputs: ["completeMethod", "onSelect", "onUnselect", "onFocus", "onBlur", "onDropdownClick", "onClear", "onKeyUp", "onShow", "onHide", "onLazyLoad"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }, { kind: "component", type: DynamicFormComponent, selector: "sia-dynamic-form", inputs: ["sections", "entityData", "mode", "displayMode", "visible", "dialogConfig", "drawerConfig", "showSubmitButton", "showCancelButton", "submitButtonLabel", "cancelButtonLabel", "submitButtonIcon", "cancelButtonIcon"], outputs: ["formReady", "formSubmit", "visibleChange", "onCancel", "fieldSave"] }] });
|
|
1110
1291
|
}
|
|
1111
1292
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScheduleFormComponent, decorators: [{
|
|
1112
1293
|
type: Component,
|
|
1113
1294
|
args: [{ selector: 's-schedule-form', standalone: true, imports: [
|
|
1114
1295
|
CommonModule, FormsModule, ReactiveFormsModule,
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
], template: "<p-drawer [(visible)]=\"visible\" position=\"right\" [styleClass]=\"'drawer-style'\" [modal]=\"true\">\n <ng-template pTemplate=\"header\">\n <span class=\"drawer-title\">\n <i class=\"pi pi-calendar\"></i>\n {{ isEditing ? ('crmx.schedule.schedule_edit' | translate) : ('crmx.schedule.schedule_new' | translate) }}\n </span>\n </ng-template>\n\n <div class=\"drawer-layout\">\n <!-- Left: Form -->\n <div class=\"drawer-left\">\n <div class=\"drawer-section-header\">\n <i class=\"pi pi-info-circle\"></i>\n <span>{{ 'crmx.schedule.schedule_details' | translate }}</span>\n </div>\n <sia-dynamic-form\n #detailForm\n [sections]=\"[{ fields: scheduleDetailFields }]\"\n [entityData]=\"entityDataForForm\"\n [mode]=\"'form'\"\n [showSubmitButton]=\"false\"\n [showCancelButton]=\"false\"\n (formReady)=\"onDetailFormReady($event)\"\n ></sia-dynamic-form>\n </div>\n\n <!-- Right: Recurrence + Participants -->\n <div class=\"drawer-right\">\n <!-- Recurrence Config -->\n <div class=\"drawer-section\" *ngIf=\"showRecurrenceFields\">\n <div class=\"drawer-section-header\">\n <i class=\"pi pi-replay\"></i>\n <span>{{ 'crmx.schedule.recurrence_config' | translate }}</span>\n </div>\n <form [formGroup]=\"scheduleForm\" class=\"drawer-form\">\n <div class=\"form-row\">\n <div class=\"form-field flex-1\">\n <label for=\"recurrence-select\">\n {{ 'crmx.schedule.recurrence' | translate }}\n </label>\n <p-dropdown \n inputId=\"recurrence-select\"\n formControlName=\"recurrence\" \n [options]=\"recurrenceOptions\" \n optionLabel=\"label\" \n optionValue=\"value\" \n class=\"w-full\">\n </p-dropdown>\n </div>\n <div class=\"form-field flex-1\">\n <label for=\"recurrence-interval-input\">\n {{ 'crmx.schedule.recurrence_interval' | translate }}\n </label>\n <p-inputNumber \n inputId=\"recurrence-interval-input\"\n formControlName=\"recurrenceInterval\" \n [min]=\"1\" \n [max]=\"99\" \n class=\"w-full\">\n </p-inputNumber>\n </div>\n </div>\n <div class=\"form-row\" *ngIf=\"showWeekDays\">\n <div class=\"form-field flex-1\">\n <label for=\"week-days-select\">\n {{ 'crmx.schedule.week_days' | translate }}\n </label>\n <p-multiSelect \n inputId=\"week-days-select\"\n formControlName=\"weekDays\" \n [options]=\"weekDayOptions\" \n optionLabel=\"label\" \n optionValue=\"value\" \n [placeholder]=\"'crmx.schedule.select_week_day' | translate\" \n class=\"w-full\">\n </p-multiSelect>\n </div>\n </div>\n <div class=\"form-row\" *ngIf=\"showRepeatWhen\">\n <div class=\"form-field flex-1\">\n <label for=\"repeat-when-select\">\n {{ 'crmx.schedule.repeat_when' | translate }}\n </label>\n <p-dropdown \n inputId=\"repeat-when-select\"\n formControlName=\"repeatWhen\" \n [options]=\"repeatWhenOptions\" \n optionLabel=\"label\" \n optionValue=\"value\" \n class=\"w-full\">\n </p-dropdown>\n </div>\n <div class=\"form-field flex-1\" *ngIf=\"showRepeatWhenDay\">\n <label for=\"repeat-when-day-input\">\n {{ 'crmx.schedule.repeat_when_day' | translate }}\n </label>\n <p-inputNumber \n inputId=\"repeat-when-day-input\"\n formControlName=\"repeatWhenDay\" \n [min]=\"1\" \n [max]=\"31\" \n class=\"w-full\">\n </p-inputNumber>\n </div>\n <div class=\"form-field flex-1\" *ngIf=\"showOrdinalFields\">\n <label for=\"ordinal-week-day-select\">\n {{ 'crmx.schedule.ordinal_week_day' | translate }}\n </label>\n <p-dropdown \n inputId=\"ordinal-week-day-select\"\n formControlName=\"repeatWhenOrdinalWeekDay\" \n [options]=\"ordinalOptions\" \n optionLabel=\"label\" \n optionValue=\"value\" \n class=\"w-full\">\n </p-dropdown>\n </div>\n <div class=\"form-field flex-1\" *ngIf=\"showOrdinalFields\">\n <label for=\"week-month-select\">\n {{ 'crmx.schedule.week_month' | translate }}\n </label>\n <p-dropdown \n inputId=\"week-month-select\"\n formControlName=\"repeatWhenWeekMonth\" \n [options]=\"weekDayOptions\" \n optionLabel=\"label\" \n optionValue=\"value\" \n class=\"w-full\">\n </p-dropdown>\n </div>\n </div>\n <div class=\"form-row\" *ngIf=\"showMonthField\">\n <div class=\"form-field flex-1\">\n <label for=\"repeat-month-select\">\n {{ 'crmx.schedule.repeat_month' | translate }}\n </label>\n <p-dropdown \n inputId=\"repeat-month-select\"\n formControlName=\"repeatWhenMonth\" \n [options]=\"monthOptions\" \n optionLabel=\"label\" \n optionValue=\"value\" \n class=\"w-full\">\n </p-dropdown>\n </div>\n </div>\n </form>\n <div class=\"recurrence-description\" *ngIf=\"recurrenceDescription\">\n <i class=\"pi pi-info-circle\"></i>\n <span>{{ recurrenceDescription }}</span>\n </div>\n </div>\n\n <p-divider></p-divider>\n\n <!-- Participants -->\n <div class=\"drawer-section\">\n <div class=\"drawer-section-header\">\n <i class=\"pi pi-users\"></i>\n <span>{{ 'crmx.schedule.participants' | translate }}</span>\n </div>\n\n <!-- Autocomplete search -->\n <div class=\"participant-search\">\n <p-autoComplete\n [(ngModel)]=\"selectedParticipantLookup\"\n [suggestions]=\"participantSuggestions\"\n (completeMethod)=\"onSearchParticipants($event)\"\n (onSelect)=\"onSelectParticipant($event.value)\"\n (onFocus)=\"onSearchParticipants({ query: '' })\"\n optionLabel=\"name\"\n [placeholder]=\"'crmx.schedule.search_participant' | translate\"\n [minLength]=\"0\"\n [forceSelection]=\"true\"\n [showClear]=\"true\"\n [fluid]=\"true\"\n >\n <ng-template let-item pTemplate=\"item\">\n <div class=\"participant-suggestion\">\n <i [class]=\"getOriginIcon(item.origin)\"></i>\n <div class=\"participant-suggestion-info\">\n <span class=\"participant-suggestion-name\">{{ item.name }}</span>\n <span class=\"participant-suggestion-detail\" *ngIf=\"item.referenceName\">{{ item.referenceName }}</span>\n </div>\n <span class=\"participant-suggestion-origin\">{{ getOriginLabel(item.origin) }}</span>\n </div>\n </ng-template>\n </p-autoComplete>\n </div>\n\n <sia-loading \n *ngIf=\"participantsLoading\" \n variant=\"dots\" \n color=\"primary\" \n [size]=\"32\" \n padding=\"1.5rem 0\">\n </sia-loading>\n <div *ngIf=\"!participantsLoading && addedParticipants.length === 0\" class=\"participants-empty\">\n <i class=\"pi pi-users\"></i>\n <p>{{ 'crmx.schedule.no_participants' | translate }}</p>\n </div>\n <p-table *ngIf=\"!participantsLoading && addedParticipants.length > 0\" \n [value]=\"addedParticipants\" styleClass=\"p-datatable-sm p-datatable-striped\">\n <ng-template pTemplate=\"header\">\n <tr>\n <th scope=\"col\">{{ 'crmx.schedule.name' | translate }}</th>\n <th scope=\"col\" class=\"table-header-col\">\n {{ 'crmx.schedule.participant_type' | translate }}\n </th>\n <th scope=\"col\" class=\"table-action-col\"></th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\" let-p>\n <tr>\n <td>\n <div class=\"participant-name-cell\">\n <span>{{ p.name }}</span>\n <span *ngIf=\"p.referenceName\" class=\"participant-reference\">{{ p.referenceName }}</span>\n </div>\n </td>\n <td>\n <div class=\"participant-type-cell\">\n <i [class]=\"getOriginIcon(p.origin)\"></i>\n <span>{{ getOriginLabel(p.origin) }}</span>\n </div>\n </td>\n <td>\n <p-button icon=\"pi pi-trash\" [rounded]=\"true\" [text]=\"true\" severity=\"danger\" \n (onClick)=\"onRemoveParticipant(p)\" \n [pTooltip]=\"'crmx.schedule.remove' | translate\" tooltipPosition=\"top\"></p-button>\n </td>\n </tr>\n </ng-template>\n </p-table>\n </div>\n </div>\n </div>\n\n <ng-template pTemplate=\"footer\">\n <div class=\"drawer-footer\">\n <p-button [label]=\"'crmx.schedule.cancel' | translate\" icon=\"pi pi-times\" \n severity=\"secondary\" [outlined]=\"true\" (onClick)=\"handleCancel()\"></p-button>\n <p-button [label]=\"'crmx.schedule.save' | translate\" icon=\"pi pi-check\" \n (onClick)=\"handleSave()\"></p-button>\n </div>\n </ng-template>\n</p-drawer>\n", styles: [".drawer-title{display:flex;align-items:center;gap:.75rem;font-size:1.15rem;font-weight:600;color:var(--p-text-color)}.drawer-title i{color:var(--p-primary-color)}.drawer-layout{display:flex;gap:0;height:100%}.drawer-left{width:380px;min-width:380px;border-right:1px solid var(--p-surface-200);padding:0 1.5rem 1.5rem 0;overflow-y:auto}.drawer-right{flex:1;padding:0 0 0 1.5rem;overflow-y:auto}.drawer-section-header{display:flex;align-items:center;gap:.5rem;padding-bottom:1rem;margin-bottom:1rem;border-bottom:1px solid var(--p-surface-200);font-weight:600;font-size:.95rem;color:var(--p-text-color)}.drawer-section-header i{color:var(--p-primary-color);font-size:1rem}.drawer-form{display:flex;flex-direction:column;gap:1rem}.drawer-form .form-field{display:flex;flex-direction:column;gap:.375rem}.drawer-form .form-field label{font-weight:500;font-size:.8rem;color:var(--p-text-secondary-color);text-transform:uppercase;letter-spacing:.3px}.drawer-form .form-row{display:flex;gap:1rem}.drawer-form .form-row.checkboxes{gap:2rem;padding:.5rem 0}.drawer-form .form-check{display:flex;align-items:center;gap:.5rem}.drawer-form .form-check label{font-size:.875rem;font-weight:500;margin:0;text-transform:none;letter-spacing:0}.drawer-section{margin-bottom:1.5rem}.recurrence-description{display:flex;align-items:flex-start;gap:.5rem;margin-top:1rem;padding:.75rem 1rem;background:var(--p-primary-50);border-left:3px solid var(--p-primary-color);border-radius:4px;font-size:.85rem;color:var(--p-text-color);line-height:1.4}.recurrence-description i{color:var(--p-primary-color);margin-top:.1rem;flex-shrink:0}.participants-empty{display:flex;flex-direction:column;align-items:center;padding:2rem;text-align:center;color:var(--p-text-secondary-color);border:1px dashed var(--p-surface-300);border-radius:8px}.participants-empty i{font-size:2rem;margin-bottom:.5rem;opacity:.4}.participants-empty p{margin:0}.participant-name-cell{display:flex;align-items:center;gap:.5rem}.participant-name-cell .organizer-tag{font-size:.7rem}.participant-type-cell{display:flex;align-items:center;gap:.5rem;font-size:.85rem;color:var(--p-text-secondary-color)}.participant-type-cell i{font-size:.9rem}.drawer-footer{display:flex;gap:.75rem;justify-content:flex-end}.table-header-col{width:10rem}.table-action-col{width:4rem}@media (max-width: 768px){.drawer-layout{flex-direction:column}.drawer-left{width:100%;min-width:100%;border-right:none;border-bottom:1px solid var(--p-surface-200);padding:0 0 1.5rem}.drawer-right{padding:1.5rem 0 0}}.participant-search{margin-bottom:1rem}.participant-search :host ::ng-deep .p-autocomplete{width:100%;display:flex}.participant-search :host ::ng-deep .p-autocomplete-input{width:100%}.participant-suggestion{display:flex;align-items:center;gap:.75rem;padding:.25rem 0}.participant-suggestion i{font-size:1.1rem;color:var(--p-text-secondary-color)}.participant-suggestion-info{display:flex;flex-direction:column;flex:1;min-width:0}.participant-suggestion-name{font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.participant-suggestion-detail{font-size:.8rem;color:var(--p-text-secondary-color)}.participant-suggestion-origin{font-size:.75rem;color:var(--p-text-secondary-color);white-space:nowrap}.participant-reference{font-size:.8rem;color:var(--p-text-secondary-color);margin-left:.25rem}.drawer-style{width:85vw;max-width:1200px}:host-context(.p-dark) .drawer-left{border-color:var(--p-surface-300)}:host-context(.p-dark) .drawer-section-header{border-color:var(--p-surface-300)}\n"] }]
|
|
1119
|
-
}], ctorParameters: () => [{ type: i1$1.FormBuilder }, { type: i2.TranslationService }, { type: ScheduleService }, { type: ScheduleTypeService }], propDecorators: { visible: [{
|
|
1296
|
+
ButtonModule, DialogModule, DrawerModule, DropdownModule,
|
|
1297
|
+
InputNumberModule, MultiSelectModule, TagModule, TooltipModule,
|
|
1298
|
+
DividerModule, TableModule, AutoCompleteModule,
|
|
1299
|
+
TranslatePipe, DynamicFormComponent
|
|
1300
|
+
], template: "<!-- Schedule Drawer -->\n<p-drawer\n [(visible)]=\"visible\"\n position=\"right\"\n styleClass=\"schedule-drawer\"\n [modal]=\"true\"\n (onHide)=\"onCancel()\"\n>\n <ng-template pTemplate=\"header\">\n <span class=\"drawer-title\">\n <i class=\"pi pi-calendar\"></i>\n {{\n isEditing\n ? ('crmx.components.schedule_schedule_edit' | translate)\n : ('crmx.components.schedule_schedule_new' | translate)\n }}\n </span>\n </ng-template>\n\n <div class=\"drawer-layout\" *ngIf=\"scheduleForm\">\n <!-- Left: Form -->\n <div class=\"drawer-left\">\n <div class=\"drawer-section-header\">\n <i class=\"pi pi-info-circle\"></i>\n <span>\n {{ 'crmx.components.schedule_schedule_details' | translate }}\n </span>\n </div>\n <sia-dynamic-form\n #detailForm\n [sections]=\"[{ fields: scheduleDetailFields }]\"\n [entityData]=\"entityDataForForm\"\n [mode]=\"'form'\"\n [showSubmitButton]=\"false\"\n [showCancelButton]=\"false\"\n (formReady)=\"onDetailFormReady($event)\"\n ></sia-dynamic-form>\n </div>\n\n <!-- Right: Recurrence + Participants -->\n <div class=\"drawer-right\">\n <div\n class=\"drawer-section\"\n *ngIf=\"showRecurrenceFields\"\n >\n <div class=\"drawer-section-header\">\n <i class=\"pi pi-replay\"></i>\n <span>\n {{\n 'crmx.components.schedule_recurrence_config'\n | translate\n }}\n </span>\n </div>\n <form\n [formGroup]=\"scheduleForm\"\n class=\"drawer-form\"\n >\n <div class=\"form-row\">\n <div class=\"form-field flex-1\">\n <label for=\"recurrence\">\n {{ 'crmx.components.schedule_recurrence' | translate }}\n </label>\n <p-dropdown\n id=\"recurrence\"\n formControlName=\"recurrence\"\n [options]=\"recurrenceOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n class=\"w-full\"\n ></p-dropdown>\n </div>\n <div class=\"form-field flex-1\">\n <label for=\"recurrenceInterval\">\n {{\n 'crmx.components.schedule_recurrence_interval'\n | translate\n }}\n </label>\n <p-inputNumber\n id=\"recurrenceInterval\"\n formControlName=\"recurrenceInterval\"\n [min]=\"1\"\n [max]=\"99\"\n class=\"w-full\"\n ></p-inputNumber>\n </div>\n </div>\n <div\n class=\"form-row\"\n *ngIf=\"showWeekDays\"\n >\n <div class=\"form-field flex-1\">\n <label for=\"weekDays\">\n {{ 'crmx.components.schedule_week_days' | translate }}\n </label>\n <p-multiSelect\n id=\"weekDays\"\n formControlName=\"weekDays\"\n [options]=\"weekDayOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"\n 'crmx.components.schedule_select_week_day'\n | translate\n \"\n class=\"w-full\"\n ></p-multiSelect>\n </div>\n </div>\n <div\n class=\"form-row\"\n *ngIf=\"showRepeatWhen\"\n >\n <div class=\"form-field flex-1\">\n <label for=\"repeatWhen\">\n {{\n 'crmx.components.schedule_repeat_when' | translate\n }}\n </label>\n <p-dropdown\n id=\"repeatWhen\"\n formControlName=\"repeatWhen\"\n [options]=\"repeatWhenOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n class=\"w-full\"\n ></p-dropdown>\n </div>\n <div\n class=\"form-field flex-1\"\n *ngIf=\"showRepeatWhenDay\"\n >\n <label for=\"repeatWhenDay\">\n {{\n 'crmx.components.schedule_repeat_when_day'\n | translate\n }}\n </label>\n <p-inputNumber\n id=\"repeatWhenDay\"\n formControlName=\"repeatWhenDay\"\n [min]=\"1\"\n [max]=\"31\"\n class=\"w-full\"\n ></p-inputNumber>\n </div>\n <div\n class=\"form-field flex-1\"\n *ngIf=\"showOrdinalFields\"\n >\n <label for=\"repeatWhenOrdinalWeekDay\">\n {{\n 'crmx.components.schedule_ordinal_week_day'\n | translate\n }}\n </label>\n <p-dropdown\n id=\"repeatWhenOrdinalWeekDay\"\n formControlName=\"repeatWhenOrdinalWeekDay\"\n [options]=\"ordinalOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n class=\"w-full\"\n ></p-dropdown>\n </div>\n <div\n class=\"form-field flex-1\"\n *ngIf=\"showOrdinalFields\"\n >\n <label for=\"repeatWhenWeekMonth\">\n {{\n 'crmx.components.schedule_week_month' | translate\n }}\n </label>\n <p-dropdown\n id=\"repeatWhenWeekMonth\"\n formControlName=\"repeatWhenWeekMonth\"\n [options]=\"weekDayOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n class=\"w-full\"\n ></p-dropdown>\n </div>\n </div>\n <div\n class=\"form-row\"\n *ngIf=\"showMonthField\"\n >\n <div class=\"form-field flex-1\">\n <label for=\"repeatWhenMonth\">\n {{\n 'crmx.components.schedule_repeat_month' | translate\n }}\n </label>\n <p-dropdown\n id=\"repeatWhenMonth\"\n formControlName=\"repeatWhenMonth\"\n [options]=\"monthOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n class=\"w-full\"\n ></p-dropdown>\n </div>\n </div>\n </form>\n <div\n class=\"recurrence-description\"\n *ngIf=\"recurrenceDescription\"\n >\n <i class=\"pi pi-info-circle\"></i>\n <span>{{ recurrenceDescription }}</span>\n </div>\n </div>\n\n <p-divider></p-divider>\n\n <!-- Participants -->\n <div class=\"drawer-section\">\n <div class=\"drawer-section-header\">\n <i class=\"pi pi-users\"></i>\n <span>\n {{ 'crmx.components.schedule_participants' | translate }}\n </span>\n </div>\n <div class=\"participant-search\">\n <p-autoComplete\n [(ngModel)]=\"selectedParticipantLookup\"\n [ngModelOptions]=\"{standalone: true}\"\n [suggestions]=\"participantSuggestions\"\n (completeMethod)=\"\n onSearchParticipants($event)\n \"\n (onSelect)=\"\n onSelectParticipant($event.value)\n \"\n (onFocus)=\"\n onSearchParticipants({ query: '' })\n \"\n optionLabel=\"name\"\n [placeholder]=\"\n 'crmx.components.schedule_search_participant'\n | translate\n \"\n [minLength]=\"0\"\n [forceSelection]=\"true\"\n [showClear]=\"true\"\n [fluid]=\"true\"\n >\n <ng-template\n let-item\n pTemplate=\"item\"\n >\n <div class=\"participant-suggestion\">\n <i\n [class]=\"getOriginIcon(item.origin)\"\n ></i>\n <div\n class=\"participant-suggestion-info\"\n >\n <span\n class=\"participant-suggestion-name\"\n >\n {{ item.name }}\n </span>\n <span\n class=\"participant-suggestion-detail\"\n *ngIf=\"item.referenceName\"\n >\n {{ item.referenceName }}\n </span>\n </div>\n <span\n class=\"participant-suggestion-origin\"\n >\n {{ getOriginLabel(item.origin) }}\n </span>\n </div>\n </ng-template>\n </p-autoComplete>\n </div>\n <div\n *ngIf=\"\n !participantsLoading &&\n addedParticipants.length === 0\n \"\n class=\"participants-empty\"\n >\n <i class=\"pi pi-users\"></i>\n <p>\n {{\n 'crmx.components.schedule_no_participants'\n | translate\n }}\n </p>\n </div>\n <p-table\n *ngIf=\"\n !participantsLoading &&\n addedParticipants.length > 0\n \"\n [value]=\"addedParticipants\"\n styleClass=\"p-datatable-sm p-datatable-striped\"\n >\n <ng-template pTemplate=\"header\">\n <tr>\n <th scope=\"col\">\n {{ 'crmx.components.schedule_name' | translate }}\n </th>\n <th\n scope=\"col\"\n class=\"col-participant-type\"\n >\n {{\n 'crmx.components.schedule_participant_type'\n | translate\n }}\n </th>\n <th\n scope=\"col\"\n class=\"col-actions\"\n ></th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\" let-p>\n <tr>\n <td>\n <div class=\"participant-name-cell\">\n <span>{{ p.name }}</span>\n <span\n *ngIf=\"p.referenceName\"\n class=\"participant-reference\"\n >\n {{ p.referenceName }}\n </span>\n </div>\n </td>\n <td>\n <div class=\"participant-type-cell\">\n <i\n [class]=\"getOriginIcon(p.origin)\"\n ></i>\n <span>\n {{ getOriginLabel(p.origin) }}\n </span>\n </div>\n </td>\n <td>\n <p-button\n icon=\"pi pi-trash\"\n [rounded]=\"true\"\n [text]=\"true\"\n severity=\"danger\"\n (onClick)=\"onRemoveParticipant(p)\"\n [pTooltip]=\"\n 'crmx.components.schedule_remove' | translate\n \"\n tooltipPosition=\"top\"\n ></p-button>\n </td>\n </tr>\n </ng-template>\n </p-table>\n </div>\n </div>\n </div>\n\n <ng-template pTemplate=\"footer\">\n <div class=\"drawer-footer\">\n <p-button\n [label]=\"'crmx.components.schedule_cancel' | translate\"\n icon=\"pi pi-times\"\n severity=\"secondary\"\n [outlined]=\"true\"\n (onClick)=\"onCancel()\"\n ></p-button>\n <p-button\n [label]=\"'crmx.components.schedule_save' | translate\"\n icon=\"pi pi-check\"\n (onClick)=\"onSave()\"\n ></p-button>\n </div>\n </ng-template>\n</p-drawer>\n", styles: [":host ::ng-deep .schedule-drawer{width:85vw;max-width:1200px}.col-participant-type{width:10rem}.col-actions{width:4rem}.drawer-title{display:flex;align-items:center;gap:.75rem;font-size:1.15rem;font-weight:600;color:var(--p-text-color)}.drawer-title i{color:var(--p-primary-color)}.drawer-layout{display:flex;gap:0;height:100%}.drawer-left{width:380px;min-width:380px;border-right:1px solid var(--p-surface-200);padding:0 1.5rem 1.5rem 0;overflow-y:auto}.drawer-right{flex:1;padding:0 0 0 1.5rem;overflow-y:auto}.drawer-section-header{display:flex;align-items:center;gap:.5rem;padding-bottom:1rem;margin-bottom:1rem;border-bottom:1px solid var(--p-surface-200);font-weight:600;font-size:.95rem;color:var(--p-text-color)}.drawer-section-header i{color:var(--p-primary-color);font-size:1rem}.drawer-form{display:flex;flex-direction:column;gap:1rem}.drawer-form .form-field{display:flex;flex-direction:column;gap:.375rem}.drawer-form .form-field label{font-weight:500;font-size:.8rem;color:var(--p-text-secondary-color);text-transform:uppercase;letter-spacing:.3px}.drawer-form .form-row{display:flex;gap:1rem}.drawer-form .form-row.checkboxes{gap:2rem;padding:.5rem 0}.drawer-form .form-check{display:flex;align-items:center;gap:.5rem}.drawer-form .form-check label{font-size:.875rem;font-weight:500;margin:0;text-transform:none;letter-spacing:0}.drawer-section{margin-bottom:1.5rem}.recurrence-description{display:flex;align-items:flex-start;gap:.5rem;margin-top:1rem;padding:.75rem 1rem;background:var(--p-primary-50);border-left:3px solid var(--p-primary-color);border-radius:4px;font-size:.85rem;color:var(--p-text-color);line-height:1.4}.recurrence-description i{color:var(--p-primary-color);margin-top:.1rem;flex-shrink:0}.participants-empty{display:flex;flex-direction:column;align-items:center;padding:2rem;text-align:center;color:var(--p-text-secondary-color);border:1px dashed var(--p-surface-300);border-radius:8px}.participants-empty i{font-size:2rem;margin-bottom:.5rem;opacity:.4}.participants-empty p{margin:0}.participant-name-cell{display:flex;align-items:center;gap:.5rem}.participant-type-cell{display:flex;align-items:center;gap:.5rem;font-size:.85rem;color:var(--p-text-secondary-color)}.participant-type-cell i{font-size:.9rem}.drawer-footer{display:flex;gap:.75rem;justify-content:flex-end}.participant-search{margin-bottom:1rem}.participant-search :host ::ng-deep .p-autocomplete{width:100%;display:flex}.participant-search :host ::ng-deep .p-autocomplete-input{width:100%}.participant-suggestion{display:flex;align-items:center;gap:.75rem;padding:.25rem 0}.participant-suggestion i{font-size:1.1rem;color:var(--p-text-secondary-color)}.participant-suggestion-info{display:flex;flex-direction:column;flex:1;min-width:0}.participant-suggestion-name{font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.participant-suggestion-detail{font-size:.8rem;color:var(--p-text-secondary-color)}.participant-suggestion-origin{font-size:.75rem;color:var(--p-text-secondary-color);white-space:nowrap}.participant-reference{font-size:.8rem;color:var(--p-text-secondary-color);margin-left:.25rem}.detail-dialog-body{display:flex;flex-direction:column;gap:.5rem}.detail-dialog-row{display:flex;align-items:center;gap:.75rem;padding:.4rem 0}.detail-label{font-weight:500;color:var(--p-text-secondary-color);min-width:8rem}@media (max-width: 768px){.drawer-layout{flex-direction:column}.drawer-left{width:100%;min-width:100%;border-right:none;border-bottom:1px solid var(--p-surface-200);padding:0 0 1.5rem}.drawer-right{padding:1.5rem 0 0}}\n"] }]
|
|
1301
|
+
}], ctorParameters: () => [{ type: i1$1.FormBuilder }, { type: ScheduleService }, { type: ScheduleTypeService }, { type: CurrentCollaboratorService }, { type: i5.TranslationService }], propDecorators: { visible: [{
|
|
1120
1302
|
type: Input
|
|
1121
|
-
}],
|
|
1303
|
+
}], selectedDate: [{
|
|
1122
1304
|
type: Input
|
|
1123
1305
|
}], visibleChange: [{
|
|
1124
1306
|
type: Output
|
|
1125
|
-
}],
|
|
1126
|
-
type: Output
|
|
1127
|
-
}], onCancel: [{
|
|
1307
|
+
}], saved: [{
|
|
1128
1308
|
type: Output
|
|
1129
1309
|
}], detailFormComponent: [{
|
|
1130
1310
|
type: ViewChild,
|
|
@@ -1132,189 +1312,67 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
1132
1312
|
}] } });
|
|
1133
1313
|
|
|
1134
1314
|
class ScheduleDetailComponent {
|
|
1315
|
+
scheduleService;
|
|
1135
1316
|
t;
|
|
1136
|
-
confirmationService;
|
|
1137
1317
|
visible = false;
|
|
1138
|
-
schedule = null;
|
|
1139
|
-
showAcceptButton = false;
|
|
1140
|
-
showRejectButton = false;
|
|
1141
|
-
showCancelButton = false;
|
|
1142
|
-
showEditButton = true;
|
|
1143
|
-
showDeleteButton = false;
|
|
1144
1318
|
visibleChange = new EventEmitter();
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1319
|
+
schedule = null;
|
|
1320
|
+
scheduleData = null;
|
|
1321
|
+
participants = [];
|
|
1322
|
+
participantsLoading = false;
|
|
1323
|
+
loading = false;
|
|
1324
|
+
constructor(scheduleService, t) {
|
|
1325
|
+
this.scheduleService = scheduleService;
|
|
1148
1326
|
this.t = t;
|
|
1149
|
-
this.confirmationService = confirmationService;
|
|
1150
|
-
}
|
|
1151
|
-
get dialogHeader() {
|
|
1152
|
-
return this.schedule?.name ?? this.t.translate('sr.schedule.schedule_details');
|
|
1153
1327
|
}
|
|
1154
|
-
|
|
1155
|
-
this.
|
|
1156
|
-
this.
|
|
1157
|
-
this.
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
this.
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
if (!this.schedule)
|
|
1181
|
-
return;
|
|
1182
|
-
this.confirmAction('sr.schedule.confirm_delete', 'pi pi-exclamation-triangle', 'delete');
|
|
1183
|
-
}
|
|
1184
|
-
confirmAction(messageKey, icon, type) {
|
|
1185
|
-
this.confirmationService.confirm({
|
|
1186
|
-
message: this.t.translate(messageKey),
|
|
1187
|
-
header: this.t.translate('sr.schedule.confirmation'),
|
|
1188
|
-
icon,
|
|
1189
|
-
acceptLabel: this.t.translate('sr.schedule.yes'),
|
|
1190
|
-
rejectLabel: this.t.translate('sr.schedule.no'),
|
|
1191
|
-
accept: () => {
|
|
1192
|
-
if (this.schedule) {
|
|
1193
|
-
this.onAction.emit({ type, schedule: this.schedule });
|
|
1194
|
-
}
|
|
1195
|
-
}
|
|
1328
|
+
open(scheduleId) {
|
|
1329
|
+
this.schedule = null;
|
|
1330
|
+
this.scheduleData = null;
|
|
1331
|
+
this.participants = [];
|
|
1332
|
+
this.loading = true;
|
|
1333
|
+
this.participantsLoading = true;
|
|
1334
|
+
this.visible = true;
|
|
1335
|
+
this.visibleChange.emit(true);
|
|
1336
|
+
this.scheduleService.get(scheduleId).subscribe({
|
|
1337
|
+
next: (data) => {
|
|
1338
|
+
this.scheduleData = data;
|
|
1339
|
+
this.schedule = {
|
|
1340
|
+
id: data.id, name: data.name,
|
|
1341
|
+
scheduleType: data.type ?? null,
|
|
1342
|
+
withRecurrence: data.withRecurrence,
|
|
1343
|
+
whenOccurs: data.whenOccurs ?? '',
|
|
1344
|
+
allDay: data.allDay, startTime: data.startTime,
|
|
1345
|
+
endTime: data.endTime, priority: data.priority
|
|
1346
|
+
};
|
|
1347
|
+
this.loading = false;
|
|
1348
|
+
},
|
|
1349
|
+
error: () => { this.loading = false; }
|
|
1350
|
+
});
|
|
1351
|
+
this.scheduleService.listParticipants(scheduleId).subscribe({
|
|
1352
|
+
next: (r) => { this.participants = r.contents ?? []; this.participantsLoading = false; },
|
|
1353
|
+
error: () => { this.participantsLoading = false; }
|
|
1196
1354
|
});
|
|
1197
1355
|
}
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
return dateObj.toLocaleString('pt-BR', {
|
|
1208
|
-
day: '2-digit', month: '2-digit', year: 'numeric',
|
|
1209
|
-
hour: '2-digit', minute: '2-digit'
|
|
1210
|
-
});
|
|
1211
|
-
}
|
|
1212
|
-
catch {
|
|
1213
|
-
return this.t.translate('sr.schedule.invalid_date');
|
|
1214
|
-
}
|
|
1215
|
-
}
|
|
1216
|
-
getPriorityLabel(priority) {
|
|
1217
|
-
if (!priority) {
|
|
1218
|
-
return this.t.translate('sr.schedule.not_informed');
|
|
1219
|
-
}
|
|
1220
|
-
const labels = {
|
|
1221
|
-
[SchedulePriority.Low]: this.t.translate('sr.schedule.priority_low'),
|
|
1222
|
-
[SchedulePriority.Medium]: this.t.translate('sr.schedule.priority_medium'),
|
|
1223
|
-
[SchedulePriority.High]: this.t.translate('sr.schedule.priority_high'),
|
|
1224
|
-
[SchedulePriority.Critical]: this.t.translate('sr.schedule.priority_critical')
|
|
1225
|
-
};
|
|
1226
|
-
return labels[priority] ?? priority;
|
|
1227
|
-
}
|
|
1228
|
-
getPrioritySeverity(priority) {
|
|
1229
|
-
if (!priority) {
|
|
1230
|
-
return 'info';
|
|
1231
|
-
}
|
|
1232
|
-
const severities = {
|
|
1233
|
-
[SchedulePriority.Low]: 'info',
|
|
1234
|
-
[SchedulePriority.Medium]: 'success',
|
|
1235
|
-
[SchedulePriority.High]: 'warn',
|
|
1236
|
-
[SchedulePriority.Critical]: 'danger'
|
|
1237
|
-
};
|
|
1238
|
-
return severities[priority] ?? 'info';
|
|
1239
|
-
}
|
|
1240
|
-
getRecurrenceLabel(recurrence) {
|
|
1241
|
-
if (!recurrence) {
|
|
1242
|
-
return this.t.translate('sr.schedule.recurrence_none');
|
|
1243
|
-
}
|
|
1244
|
-
const labels = {
|
|
1245
|
-
'NONE': this.t.translate('sr.schedule.recurrence_none'),
|
|
1246
|
-
'DAILY': this.t.translate('sr.schedule.recurrence_daily'),
|
|
1247
|
-
'WEEKLY': this.t.translate('sr.schedule.recurrence_weekly'),
|
|
1248
|
-
'MONTHLY': this.t.translate('sr.schedule.recurrence_monthly'),
|
|
1249
|
-
'YEARLY': this.t.translate('sr.schedule.recurrence_yearly'),
|
|
1250
|
-
'CUSTOM': this.t.translate('sr.schedule.recurrence_custom')
|
|
1251
|
-
};
|
|
1252
|
-
return labels[recurrence] ?? recurrence;
|
|
1253
|
-
}
|
|
1254
|
-
getOrganizerName() {
|
|
1255
|
-
const organizer = this.schedule?.participants?.find((p) => p.organizer);
|
|
1256
|
-
return organizer?.collaborator?.name ?? this.t.translate('sr.schedule.not_informed');
|
|
1257
|
-
}
|
|
1258
|
-
getParticipantsCount() {
|
|
1259
|
-
return this.schedule?.participants?.filter((p) => !p.organizer).length ?? 0;
|
|
1260
|
-
}
|
|
1261
|
-
getParticipantsList() {
|
|
1262
|
-
const participants = this.schedule?.participants?.filter((p) => !p.organizer) ?? [];
|
|
1263
|
-
if (participants.length === 0) {
|
|
1264
|
-
return this.t.translate('sr.schedule.no_participants');
|
|
1265
|
-
}
|
|
1266
|
-
return participants.map((p) => p.collaborator?.name ?? this.t.translate('sr.schedule.no_name')).join(', ');
|
|
1267
|
-
}
|
|
1268
|
-
getConfirmationLabel(confirmation) {
|
|
1269
|
-
if (!confirmation) {
|
|
1270
|
-
return '';
|
|
1271
|
-
}
|
|
1272
|
-
const labels = {
|
|
1273
|
-
'CONFIRMED': this.t.translate('sr.schedule.status_accepted'),
|
|
1274
|
-
'DECLINED': this.t.translate('sr.schedule.status_rejected')
|
|
1275
|
-
};
|
|
1276
|
-
return labels[confirmation] ?? this.t.translate('sr.schedule.status_pending');
|
|
1277
|
-
}
|
|
1278
|
-
getConfirmationSeverity(confirmation) {
|
|
1279
|
-
const severities = {
|
|
1280
|
-
'CONFIRMED': 'success',
|
|
1281
|
-
'DECLINED': 'danger'
|
|
1282
|
-
};
|
|
1283
|
-
return severities[confirmation ?? ''] ?? 'warn';
|
|
1284
|
-
}
|
|
1285
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScheduleDetailComponent, deps: [{ token: i2.TranslationService }, { token: i2$1.ConfirmationService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1286
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: ScheduleDetailComponent, isStandalone: true, selector: "s-schedule-detail", inputs: { visible: "visible", schedule: "schedule", showAcceptButton: "showAcceptButton", showRejectButton: "showRejectButton", showCancelButton: "showCancelButton", showEditButton: "showEditButton", showDeleteButton: "showDeleteButton" }, outputs: { visibleChange: "visibleChange", onAction: "onAction", onClose: "onClose" }, providers: [ConfirmationService], ngImport: i0, template: "<p-dialog\n [(visible)]=\"visible\"\n [modal]=\"true\"\n [draggable]=\"false\"\n [resizable]=\"false\"\n [styleClass]=\"'schedule-detail-dialog'\"\n [header]=\"dialogHeader\"\n (onHide)=\"closeDialog()\">\n \n <ng-template pTemplate=\"header\">\n <div class=\"dialog-header\">\n <h3>{{ dialogHeader }}</h3>\n <p-tag \n *ngIf=\"schedule?.priority\"\n [severity]=\"getPrioritySeverity(schedule?.priority)\"\n [value]=\"getPriorityLabel(schedule?.priority)\">\n </p-tag>\n </div>\n </ng-template>\n\n <div class=\"schedule-detail-content\" *ngIf=\"schedule\">\n \n <!-- Informa\u00E7\u00F5es B\u00E1sicas -->\n <div class=\"detail-section\">\n <h4 class=\"section-title\">{{ 'sr.schedule.basic_info' | translate }}</h4>\n \n <div class=\"detail-row\">\n <span class=\"detail-label\">\n <i class=\"pi pi-calendar\"></i>\n {{ 'sr.schedule.type' | translate }}:\n </span>\n <span class=\"detail-value\">{{ schedule.type?.name ?? ('sr.schedule.not_informed' | translate) }}</span>\n </div>\n\n <div class=\"detail-row\">\n <span class=\"detail-label\">\n <i class=\"pi pi-clock\"></i>\n {{ 'sr.schedule.when_occurs' | translate }}:\n </span>\n <span class=\"detail-value\">{{ schedule.whenOccurs }}</span>\n </div>\n\n <div class=\"detail-row\" *ngIf=\"schedule.duration\">\n <span class=\"detail-label\">\n <i class=\"pi pi-hourglass\"></i>\n {{ 'sr.schedule.duration' | translate }}:\n </span>\n <span class=\"detail-value\">{{ schedule.duration }} {{ 'sr.schedule.minutes' | translate }}</span>\n </div>\n\n <div class=\"detail-row\">\n <span class=\"detail-label\">\n <i class=\"pi pi-refresh\"></i>\n {{ 'sr.schedule.recurrence' | translate }}:\n </span>\n <span class=\"detail-value\">{{ getRecurrenceLabel(schedule.recurrence) }}</span>\n </div>\n </div>\n\n <p-divider></p-divider>\n\n <!-- Descri\u00E7\u00E3o -->\n <div class=\"detail-section\" *ngIf=\"schedule.description\">\n <h4 class=\"section-title\">{{ 'sr.schedule.description' | translate }}</h4>\n <p class=\"description-text\">{{ schedule.description }}</p>\n </div>\n\n <p-divider *ngIf=\"schedule.description\"></p-divider>\n\n <!-- Participantes -->\n <div class=\"detail-section\">\n <h4 class=\"section-title\">{{ 'sr.schedule.participants' | translate }}</h4>\n \n <div class=\"detail-row\">\n <span class=\"detail-label\">\n <i class=\"pi pi-user\"></i>\n {{ 'sr.schedule.organizer' | translate }}:\n </span>\n <span class=\"detail-value\">{{ getOrganizerName() }}</span>\n </div>\n\n <div class=\"detail-row\">\n <span class=\"detail-label\">\n <i class=\"pi pi-users\"></i>\n {{ 'sr.schedule.participants' | translate }} ({{ getParticipantsCount() }}):\n </span>\n </div>\n \n <div class=\"participants-list\" *ngIf=\"getParticipantsCount() > 0\">\n <div class=\"participant-item\" *ngFor=\"let participant of schedule.participants\">\n <ng-container *ngIf=\"!participant.organizer\">\n <i class=\"pi pi-user\"></i>\n <span>{{ participant.collaborator?.name ?? ('sr.schedule.no_name' | translate) }}</span>\n <p-tag \n *ngIf=\"participant.confirmation\"\n [severity]=\"getConfirmationSeverity(participant.confirmation)\"\n [value]=\"getConfirmationLabel(participant.confirmation)\"\n styleClass=\"participant-status\">\n </p-tag>\n </ng-container>\n </div>\n </div>\n <p class=\"no-participants\" *ngIf=\"getParticipantsCount() === 0\">\n {{ 'sr.schedule.no_participants_besides_organizer' | translate }}\n </p>\n </div>\n\n <p-divider></p-divider>\n\n <!-- Local -->\n <div class=\"detail-section\" *ngIf=\"schedule.location\">\n <h4 class=\"section-title\">{{ 'sr.schedule.location' | translate }}</h4>\n <div class=\"detail-row\">\n <span class=\"detail-label\">\n <i class=\"pi pi-map-marker\"></i>\n {{ 'sr.schedule.address' | translate }}:\n </span>\n <span class=\"detail-value\">{{ schedule.location }}</span>\n </div>\n </div>\n\n <!-- Observa\u00E7\u00F5es -->\n <div class=\"detail-section\" *ngIf=\"schedule.observations\">\n <h4 class=\"section-title\">{{ 'sr.schedule.notes' | translate }}</h4>\n <p class=\"observations-text\">{{ schedule.observations }}</p>\n </div>\n\n </div>\n\n <ng-template pTemplate=\"footer\">\n <div class=\"dialog-footer\">\n <div class=\"footer-left\">\n <button \n *ngIf=\"showDeleteButton\"\n pButton type=\"button\" \n [label]=\"'sr.schedule.delete' | translate\" \n icon=\"pi pi-trash\"\n class=\"p-button-danger p-button-text\"\n (click)=\"deleteSchedule()\">\n </button>\n </div>\n <div class=\"footer-right\">\n <button \n *ngIf=\"showRejectButton\"\n pButton type=\"button\" \n [label]=\"'sr.schedule.reject' | translate\" \n icon=\"pi pi-times\"\n class=\"p-button-warning\"\n (click)=\"rejectSchedule()\">\n </button>\n <button \n *ngIf=\"showCancelButton\"\n pButton type=\"button\" \n [label]=\"'sr.schedule.cancel' | translate\" \n icon=\"pi pi-ban\"\n class=\"p-button-secondary\"\n (click)=\"cancelSchedule()\">\n </button>\n <button \n *ngIf=\"showAcceptButton\"\n pButton type=\"button\" \n [label]=\"'sr.schedule.accept' | translate\" \n icon=\"pi pi-check\"\n class=\"p-button-success\"\n (click)=\"acceptSchedule()\">\n </button>\n <button \n *ngIf=\"showEditButton\"\n pButton type=\"button\" \n [label]=\"'sr.schedule.edit_schedule' | translate\" \n icon=\"pi pi-pencil\"\n (click)=\"editSchedule()\">\n </button>\n <button \n pButton type=\"button\" \n [label]=\"'sr.schedule.close' | translate\" \n icon=\"pi pi-times\"\n class=\"p-button-text\"\n (click)=\"closeDialog()\">\n </button>\n </div>\n </div>\n </ng-template>\n\n</p-dialog>\n\n<p-confirmDialog></p-confirmDialog>\n", styles: [".dialog-header{display:flex;align-items:center;justify-content:space-between;width:100%;gap:1rem}.dialog-header h3{margin:0;font-size:1.25rem;font-weight:600;flex:1}.schedule-detail-content{padding:.5rem 0}.detail-section{margin-bottom:1rem}.detail-section .section-title{font-size:1rem;font-weight:600;margin:0 0 1rem;color:var(--text-color)}.detail-section .detail-row{display:flex;align-items:flex-start;margin-bottom:.75rem;gap:.5rem}.detail-section .detail-row .detail-label{display:flex;align-items:center;gap:.5rem;font-weight:500;color:var(--text-color-secondary);min-width:140px;flex-shrink:0}.detail-section .detail-row .detail-label i{font-size:.875rem}.detail-section .detail-row .detail-value{color:var(--text-color);flex:1}.detail-section .description-text,.detail-section .observations-text{color:var(--text-color);line-height:1.6;margin:0;white-space:pre-wrap}.detail-section .participants-list{margin-top:.5rem;display:flex;flex-direction:column;gap:.5rem}.detail-section .participants-list .participant-item{display:flex;align-items:center;gap:.5rem;padding:.5rem;background:var(--surface-50);border-radius:4px}.detail-section .participants-list .participant-item i{color:var(--text-color-secondary);font-size:.875rem}.detail-section .participants-list .participant-item span{flex:1;color:var(--text-color)}.detail-section .participants-list .participant-item .participant-status{font-size:.75rem}.detail-section .no-participants{color:var(--text-color-secondary);font-style:italic;margin:.5rem 0 0}.dialog-footer{display:flex;justify-content:space-between;align-items:center;width:100%;gap:.5rem}.dialog-footer .footer-left{display:flex;gap:.5rem}.dialog-footer .footer-right{display:flex;gap:.5rem;margin-left:auto}:host ::ng-deep .schedule-detail-dialog{width:600px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: DialogModule }, { kind: "component", type: i4.Dialog, selector: "p-dialog", inputs: ["header", "draggable", "resizable", "positionLeft", "positionTop", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "responsive", "appendTo", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "breakpoint", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "closeButtonProps", "maximizeButtonProps", "visible", "style", "position", "role", "content", "contentTemplate", "footerTemplate", "closeIconTemplate", "maximizeIconTemplate", "minimizeIconTemplate", "headlessTemplate"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }, { kind: "directive", type: i2$1.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i8.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "loading", "severity", "raised", "rounded", "text", "outlined", "size", "plain", "fluid", "label", "icon", "buttonProps"] }, { kind: "ngmodule", type: TagModule }, { kind: "component", type: i6$1.Tag, selector: "p-tag", inputs: ["style", "styleClass", "severity", "value", "icon", "rounded"] }, { kind: "ngmodule", type: DividerModule }, { kind: "component", type: i12.Divider, selector: "p-divider", inputs: ["style", "styleClass", "layout", "type", "align"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "ngmodule", type: ConfirmDialogModule }, { kind: "component", type: i8$1.ConfirmDialog, selector: "p-confirmDialog, p-confirmdialog, p-confirm-dialog", inputs: ["header", "icon", "message", "style", "styleClass", "maskStyleClass", "acceptIcon", "acceptLabel", "closeAriaLabel", "acceptAriaLabel", "acceptVisible", "rejectIcon", "rejectLabel", "rejectAriaLabel", "rejectVisible", "acceptButtonStyleClass", "rejectButtonStyleClass", "closeOnEscape", "dismissableMask", "blockScroll", "rtl", "closable", "appendTo", "key", "autoZIndex", "baseZIndex", "transitionOptions", "focusTrap", "defaultFocus", "breakpoints", "visible", "position"], outputs: ["onHide"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
|
|
1356
|
+
onClose() { this.visible = false; this.visibleChange.emit(false); }
|
|
1357
|
+
getParticipantName(p) { return getParticipantName(p); }
|
|
1358
|
+
getParticipantType(p) { return getParticipantType(this.t, p); }
|
|
1359
|
+
getParticipantTypeIcon(p) { return getParticipantTypeIcon(p); }
|
|
1360
|
+
getPrioritySeverity(p) { return getPrioritySeverity(p); }
|
|
1361
|
+
getPriorityLabel(p) { return getPriorityLabel(this.t, p); }
|
|
1362
|
+
getConfirmationSeverity(c) { return getConfirmationSeverity(c); }
|
|
1363
|
+
getConfirmationLabel(c) { return getConfirmationLabel(this.t, c); }
|
|
1364
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScheduleDetailComponent, deps: [{ token: ScheduleService }, { token: i5.TranslationService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1365
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: ScheduleDetailComponent, isStandalone: true, selector: "s-schedule-detail", inputs: { visible: "visible" }, outputs: { visibleChange: "visibleChange" }, ngImport: i0, template: "<p-dialog\n [(visible)]=\"visible\"\n [header]=\"schedule?.name || ''\"\n [modal]=\"true\"\n styleClass=\"detail-dialog\"\n [draggable]=\"false\"\n [resizable]=\"false\"\n (onHide)=\"onClose()\"\n>\n <div class=\"detail-dialog-body\" *ngIf=\"schedule\">\n <div\n class=\"detail-dialog-section\"\n *ngIf=\"scheduleData\"\n >\n <div class=\"detail-dialog-row\">\n <span class=\"detail-label\">\n {{ 'crmx.components.schedule_priority' | translate }}\n </span>\n <p-tag\n [value]=\"getPriorityLabel(schedule.priority)\"\n [severity]=\"getPrioritySeverity(schedule.priority)\"\n ></p-tag>\n </div>\n <div\n class=\"detail-dialog-row\"\n *ngIf=\"schedule.scheduleType\"\n >\n <span class=\"detail-label\">\n {{ 'crmx.components.schedule_type' | translate }}\n </span>\n <span>{{ schedule.scheduleType.name }}</span>\n </div>\n <div class=\"detail-dialog-row\">\n <span class=\"detail-label\">\n {{ 'crmx.components.schedule_start_date' | translate }}\n </span>\n <span>{{ scheduleData.startDate }}</span>\n </div>\n <div\n class=\"detail-dialog-row\"\n *ngIf=\"scheduleData.endDate\"\n >\n <span class=\"detail-label\">\n {{ 'crmx.components.schedule_end_date' | translate }}\n </span>\n <span>{{ scheduleData.endDate }}</span>\n </div>\n <div\n class=\"detail-dialog-row\"\n *ngIf=\"!schedule.allDay && schedule.startTime\"\n >\n <span class=\"detail-label\">\n {{ 'crmx.components.schedule_start_time' | translate }}\n </span>\n <span>\n {{ schedule.startTime }} - {{ schedule.endTime }}\n </span>\n </div>\n <div\n class=\"detail-dialog-row\"\n *ngIf=\"schedule.allDay\"\n >\n <span class=\"detail-label\">\n {{ 'crmx.components.schedule_start_time' | translate }}\n </span>\n <span>\n {{ 'crmx.components.schedule_all_day' | translate }}\n </span>\n </div>\n <div\n class=\"detail-dialog-row\"\n *ngIf=\"schedule.whenOccurs\"\n >\n <span class=\"detail-label\">\n {{ 'crmx.components.schedule_recurrence' | translate }}\n </span>\n <span>{{ schedule.whenOccurs }}</span>\n </div>\n <div\n class=\"detail-dialog-row\"\n *ngIf=\"scheduleData.comments\"\n >\n <span class=\"detail-label\">\n {{ 'crmx.components.schedule_comments' | translate }}\n </span>\n <span>{{ scheduleData.comments }}</span>\n </div>\n </div>\n <p-divider *ngIf=\"scheduleData\"></p-divider>\n <div\n class=\"detail-dialog-section\"\n *ngIf=\"scheduleData\"\n >\n <div class=\"detail-section-header\">\n <i class=\"pi pi-users\"></i>\n <span>\n {{ 'crmx.components.schedule_participants' | translate }}\n </span>\n </div>\n <p-table\n [value]=\"participants\"\n [loading]=\"participantsLoading\"\n styleClass=\"p-datatable-sm p-datatable-striped\"\n >\n <ng-template pTemplate=\"header\">\n <tr>\n <th scope=\"col\">\n {{ 'crmx.components.schedule_name' | translate }}\n </th>\n <th\n scope=\"col\"\n class=\"col-participant-type\"\n >\n {{ 'crmx.components.schedule_participant_type' | translate }}\n </th>\n <th\n scope=\"col\"\n class=\"col-status\"\n >\n {{ 'crmx.components.schedule_status' | translate }}\n </th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\" let-p>\n <tr>\n <td>\n <span>{{ getParticipantName(p) }}</span>\n </td>\n <td>\n <div class=\"participant-type-cell\">\n <i\n [class]=\"getParticipantTypeIcon(p)\"\n ></i>\n <span>\n {{ getParticipantType(p) }}\n </span>\n </div>\n </td>\n <td>\n <p-tag\n *ngIf=\"p.organizer\"\n [value]=\"\n 'crmx.components.schedule_participant_organizer_label'\n | translate\n \"\n severity=\"info\"\n ></p-tag>\n <p-tag\n *ngIf=\"!p.organizer\"\n [value]=\"\n getConfirmationLabel(p.confirmation)\n \"\n [severity]=\"\n getConfirmationSeverity(p.confirmation)\n \"\n ></p-tag>\n </td>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"emptymessage\">\n <tr>\n <td colspan=\"3\">\n <div class=\"participants-empty\">\n <i class=\"pi pi-users\"></i>\n <p>\n {{\n 'crmx.components.schedule_no_participants'\n | translate\n }}\n </p>\n </div>\n </td>\n </tr>\n </ng-template>\n </p-table>\n </div>\n </div>\n</p-dialog>\n", styles: [":host ::ng-deep .detail-dialog{width:600px}.detail-dialog-body{display:flex;flex-direction:column;gap:.5rem}.detail-dialog-row{display:flex;align-items:center;gap:.75rem;padding:.4rem 0}.detail-label{font-weight:500;color:var(--p-text-secondary-color);min-width:8rem}.detail-section-header{display:flex;align-items:center;gap:.5rem;padding-bottom:1rem;margin-bottom:1rem;border-bottom:1px solid var(--p-surface-200);font-weight:600;font-size:.95rem;color:var(--p-text-color)}.detail-section-header i{color:var(--p-primary-color);font-size:1rem}.participant-type-cell{display:flex;align-items:center;gap:.5rem;font-size:.85rem;color:var(--p-text-secondary-color)}.participant-type-cell i{font-size:.9rem}.col-participant-type{width:10rem}.col-status{width:8rem}.participants-empty{display:flex;flex-direction:column;align-items:center;padding:2rem;text-align:center;color:var(--p-text-secondary-color);border:1px dashed var(--p-surface-300);border-radius:8px}.participants-empty i{font-size:2rem;margin-bottom:.5rem;opacity:.4}.participants-empty p{margin:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: DialogModule }, { kind: "component", type: i4.Dialog, selector: "p-dialog", inputs: ["header", "draggable", "resizable", "positionLeft", "positionTop", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "responsive", "appendTo", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "breakpoint", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "closeButtonProps", "maximizeButtonProps", "visible", "style", "position", "role", "content", "contentTemplate", "footerTemplate", "closeIconTemplate", "maximizeIconTemplate", "minimizeIconTemplate", "headlessTemplate"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }, { kind: "directive", type: i8.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: DividerModule }, { kind: "component", type: i14.Divider, selector: "p-divider", inputs: ["style", "styleClass", "layout", "type", "align"] }, { kind: "ngmodule", type: TagModule }, { kind: "component", type: i7$1.Tag, selector: "p-tag", inputs: ["style", "styleClass", "severity", "value", "icon", "rounded"] }, { kind: "ngmodule", type: TableModule }, { kind: "component", type: i15.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "style", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "scrollDirection", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "responsive", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "autoLayout", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "virtualRowHeight", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
|
|
1287
1366
|
}
|
|
1288
1367
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScheduleDetailComponent, decorators: [{
|
|
1289
1368
|
type: Component,
|
|
1290
|
-
args: [{ selector: 's-schedule-detail', standalone: true, imports: [
|
|
1291
|
-
|
|
1292
|
-
DividerModule, TooltipModule, ConfirmDialogModule, TranslatePipe
|
|
1293
|
-
], providers: [ConfirmationService], template: "<p-dialog\n [(visible)]=\"visible\"\n [modal]=\"true\"\n [draggable]=\"false\"\n [resizable]=\"false\"\n [styleClass]=\"'schedule-detail-dialog'\"\n [header]=\"dialogHeader\"\n (onHide)=\"closeDialog()\">\n \n <ng-template pTemplate=\"header\">\n <div class=\"dialog-header\">\n <h3>{{ dialogHeader }}</h3>\n <p-tag \n *ngIf=\"schedule?.priority\"\n [severity]=\"getPrioritySeverity(schedule?.priority)\"\n [value]=\"getPriorityLabel(schedule?.priority)\">\n </p-tag>\n </div>\n </ng-template>\n\n <div class=\"schedule-detail-content\" *ngIf=\"schedule\">\n \n <!-- Informa\u00E7\u00F5es B\u00E1sicas -->\n <div class=\"detail-section\">\n <h4 class=\"section-title\">{{ 'sr.schedule.basic_info' | translate }}</h4>\n \n <div class=\"detail-row\">\n <span class=\"detail-label\">\n <i class=\"pi pi-calendar\"></i>\n {{ 'sr.schedule.type' | translate }}:\n </span>\n <span class=\"detail-value\">{{ schedule.type?.name ?? ('sr.schedule.not_informed' | translate) }}</span>\n </div>\n\n <div class=\"detail-row\">\n <span class=\"detail-label\">\n <i class=\"pi pi-clock\"></i>\n {{ 'sr.schedule.when_occurs' | translate }}:\n </span>\n <span class=\"detail-value\">{{ schedule.whenOccurs }}</span>\n </div>\n\n <div class=\"detail-row\" *ngIf=\"schedule.duration\">\n <span class=\"detail-label\">\n <i class=\"pi pi-hourglass\"></i>\n {{ 'sr.schedule.duration' | translate }}:\n </span>\n <span class=\"detail-value\">{{ schedule.duration }} {{ 'sr.schedule.minutes' | translate }}</span>\n </div>\n\n <div class=\"detail-row\">\n <span class=\"detail-label\">\n <i class=\"pi pi-refresh\"></i>\n {{ 'sr.schedule.recurrence' | translate }}:\n </span>\n <span class=\"detail-value\">{{ getRecurrenceLabel(schedule.recurrence) }}</span>\n </div>\n </div>\n\n <p-divider></p-divider>\n\n <!-- Descri\u00E7\u00E3o -->\n <div class=\"detail-section\" *ngIf=\"schedule.description\">\n <h4 class=\"section-title\">{{ 'sr.schedule.description' | translate }}</h4>\n <p class=\"description-text\">{{ schedule.description }}</p>\n </div>\n\n <p-divider *ngIf=\"schedule.description\"></p-divider>\n\n <!-- Participantes -->\n <div class=\"detail-section\">\n <h4 class=\"section-title\">{{ 'sr.schedule.participants' | translate }}</h4>\n \n <div class=\"detail-row\">\n <span class=\"detail-label\">\n <i class=\"pi pi-user\"></i>\n {{ 'sr.schedule.organizer' | translate }}:\n </span>\n <span class=\"detail-value\">{{ getOrganizerName() }}</span>\n </div>\n\n <div class=\"detail-row\">\n <span class=\"detail-label\">\n <i class=\"pi pi-users\"></i>\n {{ 'sr.schedule.participants' | translate }} ({{ getParticipantsCount() }}):\n </span>\n </div>\n \n <div class=\"participants-list\" *ngIf=\"getParticipantsCount() > 0\">\n <div class=\"participant-item\" *ngFor=\"let participant of schedule.participants\">\n <ng-container *ngIf=\"!participant.organizer\">\n <i class=\"pi pi-user\"></i>\n <span>{{ participant.collaborator?.name ?? ('sr.schedule.no_name' | translate) }}</span>\n <p-tag \n *ngIf=\"participant.confirmation\"\n [severity]=\"getConfirmationSeverity(participant.confirmation)\"\n [value]=\"getConfirmationLabel(participant.confirmation)\"\n styleClass=\"participant-status\">\n </p-tag>\n </ng-container>\n </div>\n </div>\n <p class=\"no-participants\" *ngIf=\"getParticipantsCount() === 0\">\n {{ 'sr.schedule.no_participants_besides_organizer' | translate }}\n </p>\n </div>\n\n <p-divider></p-divider>\n\n <!-- Local -->\n <div class=\"detail-section\" *ngIf=\"schedule.location\">\n <h4 class=\"section-title\">{{ 'sr.schedule.location' | translate }}</h4>\n <div class=\"detail-row\">\n <span class=\"detail-label\">\n <i class=\"pi pi-map-marker\"></i>\n {{ 'sr.schedule.address' | translate }}:\n </span>\n <span class=\"detail-value\">{{ schedule.location }}</span>\n </div>\n </div>\n\n <!-- Observa\u00E7\u00F5es -->\n <div class=\"detail-section\" *ngIf=\"schedule.observations\">\n <h4 class=\"section-title\">{{ 'sr.schedule.notes' | translate }}</h4>\n <p class=\"observations-text\">{{ schedule.observations }}</p>\n </div>\n\n </div>\n\n <ng-template pTemplate=\"footer\">\n <div class=\"dialog-footer\">\n <div class=\"footer-left\">\n <button \n *ngIf=\"showDeleteButton\"\n pButton type=\"button\" \n [label]=\"'sr.schedule.delete' | translate\" \n icon=\"pi pi-trash\"\n class=\"p-button-danger p-button-text\"\n (click)=\"deleteSchedule()\">\n </button>\n </div>\n <div class=\"footer-right\">\n <button \n *ngIf=\"showRejectButton\"\n pButton type=\"button\" \n [label]=\"'sr.schedule.reject' | translate\" \n icon=\"pi pi-times\"\n class=\"p-button-warning\"\n (click)=\"rejectSchedule()\">\n </button>\n <button \n *ngIf=\"showCancelButton\"\n pButton type=\"button\" \n [label]=\"'sr.schedule.cancel' | translate\" \n icon=\"pi pi-ban\"\n class=\"p-button-secondary\"\n (click)=\"cancelSchedule()\">\n </button>\n <button \n *ngIf=\"showAcceptButton\"\n pButton type=\"button\" \n [label]=\"'sr.schedule.accept' | translate\" \n icon=\"pi pi-check\"\n class=\"p-button-success\"\n (click)=\"acceptSchedule()\">\n </button>\n <button \n *ngIf=\"showEditButton\"\n pButton type=\"button\" \n [label]=\"'sr.schedule.edit_schedule' | translate\" \n icon=\"pi pi-pencil\"\n (click)=\"editSchedule()\">\n </button>\n <button \n pButton type=\"button\" \n [label]=\"'sr.schedule.close' | translate\" \n icon=\"pi pi-times\"\n class=\"p-button-text\"\n (click)=\"closeDialog()\">\n </button>\n </div>\n </div>\n </ng-template>\n\n</p-dialog>\n\n<p-confirmDialog></p-confirmDialog>\n", styles: [".dialog-header{display:flex;align-items:center;justify-content:space-between;width:100%;gap:1rem}.dialog-header h3{margin:0;font-size:1.25rem;font-weight:600;flex:1}.schedule-detail-content{padding:.5rem 0}.detail-section{margin-bottom:1rem}.detail-section .section-title{font-size:1rem;font-weight:600;margin:0 0 1rem;color:var(--text-color)}.detail-section .detail-row{display:flex;align-items:flex-start;margin-bottom:.75rem;gap:.5rem}.detail-section .detail-row .detail-label{display:flex;align-items:center;gap:.5rem;font-weight:500;color:var(--text-color-secondary);min-width:140px;flex-shrink:0}.detail-section .detail-row .detail-label i{font-size:.875rem}.detail-section .detail-row .detail-value{color:var(--text-color);flex:1}.detail-section .description-text,.detail-section .observations-text{color:var(--text-color);line-height:1.6;margin:0;white-space:pre-wrap}.detail-section .participants-list{margin-top:.5rem;display:flex;flex-direction:column;gap:.5rem}.detail-section .participants-list .participant-item{display:flex;align-items:center;gap:.5rem;padding:.5rem;background:var(--surface-50);border-radius:4px}.detail-section .participants-list .participant-item i{color:var(--text-color-secondary);font-size:.875rem}.detail-section .participants-list .participant-item span{flex:1;color:var(--text-color)}.detail-section .participants-list .participant-item .participant-status{font-size:.75rem}.detail-section .no-participants{color:var(--text-color-secondary);font-style:italic;margin:.5rem 0 0}.dialog-footer{display:flex;justify-content:space-between;align-items:center;width:100%;gap:.5rem}.dialog-footer .footer-left{display:flex;gap:.5rem}.dialog-footer .footer-right{display:flex;gap:.5rem;margin-left:auto}:host ::ng-deep .schedule-detail-dialog{width:600px}\n"] }]
|
|
1294
|
-
}], ctorParameters: () => [{ type: i2.TranslationService }, { type: i2$1.ConfirmationService }], propDecorators: { visible: [{
|
|
1295
|
-
type: Input
|
|
1296
|
-
}], schedule: [{
|
|
1297
|
-
type: Input
|
|
1298
|
-
}], showAcceptButton: [{
|
|
1299
|
-
type: Input
|
|
1300
|
-
}], showRejectButton: [{
|
|
1301
|
-
type: Input
|
|
1302
|
-
}], showCancelButton: [{
|
|
1303
|
-
type: Input
|
|
1304
|
-
}], showEditButton: [{
|
|
1305
|
-
type: Input
|
|
1306
|
-
}], showDeleteButton: [{
|
|
1369
|
+
args: [{ selector: 's-schedule-detail', standalone: true, imports: [CommonModule, DialogModule, DividerModule, TagModule, TableModule, TranslatePipe], template: "<p-dialog\n [(visible)]=\"visible\"\n [header]=\"schedule?.name || ''\"\n [modal]=\"true\"\n styleClass=\"detail-dialog\"\n [draggable]=\"false\"\n [resizable]=\"false\"\n (onHide)=\"onClose()\"\n>\n <div class=\"detail-dialog-body\" *ngIf=\"schedule\">\n <div\n class=\"detail-dialog-section\"\n *ngIf=\"scheduleData\"\n >\n <div class=\"detail-dialog-row\">\n <span class=\"detail-label\">\n {{ 'crmx.components.schedule_priority' | translate }}\n </span>\n <p-tag\n [value]=\"getPriorityLabel(schedule.priority)\"\n [severity]=\"getPrioritySeverity(schedule.priority)\"\n ></p-tag>\n </div>\n <div\n class=\"detail-dialog-row\"\n *ngIf=\"schedule.scheduleType\"\n >\n <span class=\"detail-label\">\n {{ 'crmx.components.schedule_type' | translate }}\n </span>\n <span>{{ schedule.scheduleType.name }}</span>\n </div>\n <div class=\"detail-dialog-row\">\n <span class=\"detail-label\">\n {{ 'crmx.components.schedule_start_date' | translate }}\n </span>\n <span>{{ scheduleData.startDate }}</span>\n </div>\n <div\n class=\"detail-dialog-row\"\n *ngIf=\"scheduleData.endDate\"\n >\n <span class=\"detail-label\">\n {{ 'crmx.components.schedule_end_date' | translate }}\n </span>\n <span>{{ scheduleData.endDate }}</span>\n </div>\n <div\n class=\"detail-dialog-row\"\n *ngIf=\"!schedule.allDay && schedule.startTime\"\n >\n <span class=\"detail-label\">\n {{ 'crmx.components.schedule_start_time' | translate }}\n </span>\n <span>\n {{ schedule.startTime }} - {{ schedule.endTime }}\n </span>\n </div>\n <div\n class=\"detail-dialog-row\"\n *ngIf=\"schedule.allDay\"\n >\n <span class=\"detail-label\">\n {{ 'crmx.components.schedule_start_time' | translate }}\n </span>\n <span>\n {{ 'crmx.components.schedule_all_day' | translate }}\n </span>\n </div>\n <div\n class=\"detail-dialog-row\"\n *ngIf=\"schedule.whenOccurs\"\n >\n <span class=\"detail-label\">\n {{ 'crmx.components.schedule_recurrence' | translate }}\n </span>\n <span>{{ schedule.whenOccurs }}</span>\n </div>\n <div\n class=\"detail-dialog-row\"\n *ngIf=\"scheduleData.comments\"\n >\n <span class=\"detail-label\">\n {{ 'crmx.components.schedule_comments' | translate }}\n </span>\n <span>{{ scheduleData.comments }}</span>\n </div>\n </div>\n <p-divider *ngIf=\"scheduleData\"></p-divider>\n <div\n class=\"detail-dialog-section\"\n *ngIf=\"scheduleData\"\n >\n <div class=\"detail-section-header\">\n <i class=\"pi pi-users\"></i>\n <span>\n {{ 'crmx.components.schedule_participants' | translate }}\n </span>\n </div>\n <p-table\n [value]=\"participants\"\n [loading]=\"participantsLoading\"\n styleClass=\"p-datatable-sm p-datatable-striped\"\n >\n <ng-template pTemplate=\"header\">\n <tr>\n <th scope=\"col\">\n {{ 'crmx.components.schedule_name' | translate }}\n </th>\n <th\n scope=\"col\"\n class=\"col-participant-type\"\n >\n {{ 'crmx.components.schedule_participant_type' | translate }}\n </th>\n <th\n scope=\"col\"\n class=\"col-status\"\n >\n {{ 'crmx.components.schedule_status' | translate }}\n </th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\" let-p>\n <tr>\n <td>\n <span>{{ getParticipantName(p) }}</span>\n </td>\n <td>\n <div class=\"participant-type-cell\">\n <i\n [class]=\"getParticipantTypeIcon(p)\"\n ></i>\n <span>\n {{ getParticipantType(p) }}\n </span>\n </div>\n </td>\n <td>\n <p-tag\n *ngIf=\"p.organizer\"\n [value]=\"\n 'crmx.components.schedule_participant_organizer_label'\n | translate\n \"\n severity=\"info\"\n ></p-tag>\n <p-tag\n *ngIf=\"!p.organizer\"\n [value]=\"\n getConfirmationLabel(p.confirmation)\n \"\n [severity]=\"\n getConfirmationSeverity(p.confirmation)\n \"\n ></p-tag>\n </td>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"emptymessage\">\n <tr>\n <td colspan=\"3\">\n <div class=\"participants-empty\">\n <i class=\"pi pi-users\"></i>\n <p>\n {{\n 'crmx.components.schedule_no_participants'\n | translate\n }}\n </p>\n </div>\n </td>\n </tr>\n </ng-template>\n </p-table>\n </div>\n </div>\n</p-dialog>\n", styles: [":host ::ng-deep .detail-dialog{width:600px}.detail-dialog-body{display:flex;flex-direction:column;gap:.5rem}.detail-dialog-row{display:flex;align-items:center;gap:.75rem;padding:.4rem 0}.detail-label{font-weight:500;color:var(--p-text-secondary-color);min-width:8rem}.detail-section-header{display:flex;align-items:center;gap:.5rem;padding-bottom:1rem;margin-bottom:1rem;border-bottom:1px solid var(--p-surface-200);font-weight:600;font-size:.95rem;color:var(--p-text-color)}.detail-section-header i{color:var(--p-primary-color);font-size:1rem}.participant-type-cell{display:flex;align-items:center;gap:.5rem;font-size:.85rem;color:var(--p-text-secondary-color)}.participant-type-cell i{font-size:.9rem}.col-participant-type{width:10rem}.col-status{width:8rem}.participants-empty{display:flex;flex-direction:column;align-items:center;padding:2rem;text-align:center;color:var(--p-text-secondary-color);border:1px dashed var(--p-surface-300);border-radius:8px}.participants-empty i{font-size:2rem;margin-bottom:.5rem;opacity:.4}.participants-empty p{margin:0}\n"] }]
|
|
1370
|
+
}], ctorParameters: () => [{ type: ScheduleService }, { type: i5.TranslationService }], propDecorators: { visible: [{
|
|
1307
1371
|
type: Input
|
|
1308
1372
|
}], visibleChange: [{
|
|
1309
1373
|
type: Output
|
|
1310
|
-
}], onAction: [{
|
|
1311
|
-
type: Output
|
|
1312
|
-
}], onClose: [{
|
|
1313
|
-
type: Output
|
|
1314
1374
|
}] } });
|
|
1315
1375
|
|
|
1316
|
-
// Components
|
|
1317
|
-
|
|
1318
1376
|
/*
|
|
1319
1377
|
* Public API Surface of @senior-gestao-relacionamento/angular-components
|
|
1320
1378
|
*/
|
|
@@ -1323,5 +1381,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
1323
1381
|
* Generated bundle index. Do not edit.
|
|
1324
1382
|
*/
|
|
1325
1383
|
|
|
1326
|
-
export { AngularComponentsModule, CurrentCollaboratorService, Month, OrdinalWeekDay, ParticipantConfirmation, RepeatWhen, ScheduleDetailComponent, ScheduleFormComponent, SchedulePriority, ScheduleRecurrence, ScheduleService, ScheduleTypeService, StorageService, WeekDay };
|
|
1384
|
+
export { AngularComponentsModule, CurrentCollaboratorService, Month, OrdinalWeekDay, ParticipantConfirmation, RepeatWhen, ScheduleDetailComponent, ScheduleFormComponent, SchedulePriority, ScheduleRecurrence, ScheduleService, ScheduleTypeService, Status, StorageService, WeekDay };
|
|
1327
1385
|
//# sourceMappingURL=senior-gestao-relacionamento-angular-components.mjs.map
|