@memberjunction/ng-list-management 6.1.4 → 6.2.0-edge.1
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/dist/lib/components/audience-source-picker/audience-source-picker.component.d.ts +74 -14
- package/dist/lib/components/audience-source-picker/audience-source-picker.component.d.ts.map +1 -1
- package/dist/lib/components/audience-source-picker/audience-source-picker.component.js +177 -57
- package/dist/lib/components/audience-source-picker/audience-source-picker.component.js.map +1 -1
- package/dist/lib/components/audience-source-summary/audience-source-summary.component.d.ts +7 -1
- package/dist/lib/components/audience-source-summary/audience-source-summary.component.d.ts.map +1 -1
- package/dist/lib/components/audience-source-summary/audience-source-summary.component.js +17 -5
- package/dist/lib/components/audience-source-summary/audience-source-summary.component.js.map +1 -1
- package/dist/lib/components/list-audit-log/list-audit-log.component.d.ts +30 -4
- package/dist/lib/components/list-audit-log/list-audit-log.component.d.ts.map +1 -1
- package/dist/lib/components/list-audit-log/list-audit-log.component.js +54 -14
- package/dist/lib/components/list-audit-log/list-audit-log.component.js.map +1 -1
- package/dist/lib/components/list-delta-confirm/list-delta-confirm.component.d.ts +17 -1
- package/dist/lib/components/list-delta-confirm/list-delta-confirm.component.d.ts.map +1 -1
- package/dist/lib/components/list-delta-confirm/list-delta-confirm.component.js +45 -13
- package/dist/lib/components/list-delta-confirm/list-delta-confirm.component.js.map +1 -1
- package/dist/lib/components/list-invitations/list-invitations.component.d.ts +48 -8
- package/dist/lib/components/list-invitations/list-invitations.component.d.ts.map +1 -1
- package/dist/lib/components/list-invitations/list-invitations.component.js +108 -28
- package/dist/lib/components/list-invitations/list-invitations.component.js.map +1 -1
- package/dist/lib/components/list-management-dialog/list-management-dialog.component.d.ts +123 -15
- package/dist/lib/components/list-management-dialog/list-management-dialog.component.d.ts.map +1 -1
- package/dist/lib/components/list-management-dialog/list-management-dialog.component.js +312 -100
- package/dist/lib/components/list-management-dialog/list-management-dialog.component.js.map +1 -1
- package/dist/lib/components/list-share-dialog/list-share-dialog.component.d.ts +128 -14
- package/dist/lib/components/list-share-dialog/list-share-dialog.component.d.ts.map +1 -1
- package/dist/lib/components/list-share-dialog/list-share-dialog.component.js +288 -92
- package/dist/lib/components/list-share-dialog/list-share-dialog.component.js.map +1 -1
- package/dist/lib/components/list-stats/list-stats.component.d.ts +32 -6
- package/dist/lib/components/list-stats/list-stats.component.d.ts.map +1 -1
- package/dist/lib/components/list-stats/list-stats.component.js +67 -15
- package/dist/lib/components/list-stats/list-stats.component.js.map +1 -1
- package/dist/lib/components/save-view-as-list-dialog/save-view-as-list-dialog.component.d.ts +44 -8
- package/dist/lib/components/save-view-as-list-dialog/save-view-as-list-dialog.component.d.ts.map +1 -1
- package/dist/lib/components/save-view-as-list-dialog/save-view-as-list-dialog.component.js +100 -28
- package/dist/lib/components/save-view-as-list-dialog/save-view-as-list-dialog.component.js.map +1 -1
- package/dist/lib/components/shared-with-me/shared-with-me.component.d.ts +18 -2
- package/dist/lib/components/shared-with-me/shared-with-me.component.d.ts.map +1 -1
- package/dist/lib/components/shared-with-me/shared-with-me.component.js +41 -9
- package/dist/lib/components/shared-with-me/shared-with-me.component.js.map +1 -1
- package/dist/lib/components/tag-chips/tag-chips.component.d.ts +30 -6
- package/dist/lib/components/tag-chips/tag-chips.component.d.ts.map +1 -1
- package/dist/lib/components/tag-chips/tag-chips.component.js +76 -28
- package/dist/lib/components/tag-chips/tag-chips.component.js.map +1 -1
- package/dist/lib/services/list-management.service.d.ts +25 -1
- package/dist/lib/services/list-management.service.d.ts.map +1 -1
- package/dist/lib/services/list-management.service.js +59 -11
- package/dist/lib/services/list-management.service.js.map +1 -1
- package/dist/lib/services/list-sharing.service.d.ts +42 -1
- package/dist/lib/services/list-sharing.service.d.ts.map +1 -1
- package/dist/lib/services/list-sharing.service.js +85 -17
- package/dist/lib/services/list-sharing.service.js.map +1 -1
- package/package.json +11 -11
|
@@ -424,16 +424,24 @@ export class ListManagementDialogComponent extends BaseAngularComponent {
|
|
|
424
424
|
/**
|
|
425
425
|
* Controls dialog visibility
|
|
426
426
|
*/
|
|
427
|
-
get
|
|
427
|
+
get Visible() {
|
|
428
428
|
return this._visible;
|
|
429
429
|
}
|
|
430
|
-
set
|
|
430
|
+
set Visible(value) {
|
|
431
431
|
if (value && !this._visible) {
|
|
432
432
|
this._pendingInit = true;
|
|
433
433
|
}
|
|
434
434
|
this._visible = value;
|
|
435
435
|
this.tryInitialize();
|
|
436
436
|
}
|
|
437
|
+
/** @deprecated Use {@link Visible}. */
|
|
438
|
+
get visible() {
|
|
439
|
+
return this.Visible;
|
|
440
|
+
}
|
|
441
|
+
/** @deprecated Use {@link Visible}. */
|
|
442
|
+
set visible(value) {
|
|
443
|
+
this.Visible = value;
|
|
444
|
+
}
|
|
437
445
|
_visible = false;
|
|
438
446
|
/** Set on each closed→open transition; cleared once init actually runs (requires config). */
|
|
439
447
|
_pendingInit = false;
|
|
@@ -447,31 +455,151 @@ export class ListManagementDialogComponent extends BaseAngularComponent {
|
|
|
447
455
|
/**
|
|
448
456
|
* Emitted when dialog is closed with results
|
|
449
457
|
*/
|
|
450
|
-
|
|
458
|
+
Complete = new EventEmitter();
|
|
459
|
+
/**
|
|
460
|
+
* @deprecated Use {@link Complete}.
|
|
461
|
+
*
|
|
462
|
+
* The same emitter under the old binding name, so a template still binding
|
|
463
|
+
* (complete) keeps working. Must stay AFTER Complete: class fields
|
|
464
|
+
* initialise in order, and the other way round this captures undefined.
|
|
465
|
+
*/
|
|
466
|
+
complete = this.Complete;
|
|
451
467
|
/**
|
|
452
468
|
* Emitted when dialog is cancelled
|
|
453
469
|
*/
|
|
454
470
|
cancel = new EventEmitter();
|
|
455
471
|
// State
|
|
456
|
-
|
|
472
|
+
Loading = false;
|
|
473
|
+
/** @deprecated Use {@link Loading}. */
|
|
474
|
+
get loading() {
|
|
475
|
+
return this.Loading;
|
|
476
|
+
}
|
|
477
|
+
/** @deprecated Use {@link Loading}. */
|
|
478
|
+
set loading(value) {
|
|
479
|
+
this.Loading = value;
|
|
480
|
+
}
|
|
457
481
|
saving = false;
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
482
|
+
SearchText = '';
|
|
483
|
+
/** @deprecated Use {@link SearchText}. */
|
|
484
|
+
get searchText() {
|
|
485
|
+
return this.SearchText;
|
|
486
|
+
}
|
|
487
|
+
/** @deprecated Use {@link SearchText}. */
|
|
488
|
+
set searchText(value) {
|
|
489
|
+
this.SearchText = value;
|
|
490
|
+
}
|
|
491
|
+
ActiveTab = 'all';
|
|
492
|
+
/** @deprecated Use {@link ActiveTab}. */
|
|
493
|
+
get activeTab() {
|
|
494
|
+
return this.ActiveTab;
|
|
495
|
+
}
|
|
496
|
+
/** @deprecated Use {@link ActiveTab}. */
|
|
497
|
+
set activeTab(value) {
|
|
498
|
+
this.ActiveTab = value;
|
|
499
|
+
}
|
|
500
|
+
SortOption = 'name';
|
|
501
|
+
/** @deprecated Use {@link SortOption}. */
|
|
502
|
+
get sortOption() {
|
|
503
|
+
return this.SortOption;
|
|
504
|
+
}
|
|
505
|
+
/** @deprecated Use {@link SortOption}. */
|
|
506
|
+
set sortOption(value) {
|
|
507
|
+
this.SortOption = value;
|
|
508
|
+
}
|
|
509
|
+
ShowCreateForm = false;
|
|
510
|
+
/** @deprecated Use {@link ShowCreateForm}. */
|
|
511
|
+
get showCreateForm() {
|
|
512
|
+
return this.ShowCreateForm;
|
|
513
|
+
}
|
|
514
|
+
/** @deprecated Use {@link ShowCreateForm}. */
|
|
515
|
+
set showCreateForm(value) {
|
|
516
|
+
this.ShowCreateForm = value;
|
|
517
|
+
}
|
|
462
518
|
// Data
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
519
|
+
AllLists = [];
|
|
520
|
+
/** @deprecated Use {@link AllLists}. */
|
|
521
|
+
get allLists() {
|
|
522
|
+
return this.AllLists;
|
|
523
|
+
}
|
|
524
|
+
/** @deprecated Use {@link AllLists}. */
|
|
525
|
+
set allLists(value) {
|
|
526
|
+
this.AllLists = value;
|
|
527
|
+
}
|
|
528
|
+
FilteredLists = [];
|
|
529
|
+
/** @deprecated Use {@link FilteredLists}. */
|
|
530
|
+
get filteredLists() {
|
|
531
|
+
return this.FilteredLists;
|
|
532
|
+
}
|
|
533
|
+
/** @deprecated Use {@link FilteredLists}. */
|
|
534
|
+
set filteredLists(value) {
|
|
535
|
+
this.FilteredLists = value;
|
|
536
|
+
}
|
|
537
|
+
Categories = [];
|
|
538
|
+
/** @deprecated Use {@link Categories}. */
|
|
539
|
+
get categories() {
|
|
540
|
+
return this.Categories;
|
|
541
|
+
}
|
|
542
|
+
/** @deprecated Use {@link Categories}. */
|
|
543
|
+
set categories(value) {
|
|
544
|
+
this.Categories = value;
|
|
545
|
+
}
|
|
466
546
|
// Create form state
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
547
|
+
NewListName = '';
|
|
548
|
+
/** @deprecated Use {@link NewListName}. */
|
|
549
|
+
get newListName() {
|
|
550
|
+
return this.NewListName;
|
|
551
|
+
}
|
|
552
|
+
/** @deprecated Use {@link NewListName}. */
|
|
553
|
+
set newListName(value) {
|
|
554
|
+
this.NewListName = value;
|
|
555
|
+
}
|
|
556
|
+
NewListDescription = '';
|
|
557
|
+
/** @deprecated Use {@link NewListDescription}. */
|
|
558
|
+
get newListDescription() {
|
|
559
|
+
return this.NewListDescription;
|
|
560
|
+
}
|
|
561
|
+
/** @deprecated Use {@link NewListDescription}. */
|
|
562
|
+
set newListDescription(value) {
|
|
563
|
+
this.NewListDescription = value;
|
|
564
|
+
}
|
|
565
|
+
NewListCategoryId = null;
|
|
566
|
+
/** @deprecated Use {@link NewListCategoryId}. */
|
|
567
|
+
get newListCategoryId() {
|
|
568
|
+
return this.NewListCategoryId;
|
|
569
|
+
}
|
|
570
|
+
/** @deprecated Use {@link NewListCategoryId}. */
|
|
571
|
+
set newListCategoryId(value) {
|
|
572
|
+
this.NewListCategoryId = value;
|
|
573
|
+
}
|
|
470
574
|
// Track changes
|
|
471
575
|
originalMembership = new Map();
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
576
|
+
AddedToLists = new Set();
|
|
577
|
+
/** @deprecated Use {@link AddedToLists}. */
|
|
578
|
+
get addedToLists() {
|
|
579
|
+
return this.AddedToLists;
|
|
580
|
+
}
|
|
581
|
+
/** @deprecated Use {@link AddedToLists}. */
|
|
582
|
+
set addedToLists(value) {
|
|
583
|
+
this.AddedToLists = value;
|
|
584
|
+
}
|
|
585
|
+
RemovedFromLists = new Set();
|
|
586
|
+
/** @deprecated Use {@link RemovedFromLists}. */
|
|
587
|
+
get removedFromLists() {
|
|
588
|
+
return this.RemovedFromLists;
|
|
589
|
+
}
|
|
590
|
+
/** @deprecated Use {@link RemovedFromLists}. */
|
|
591
|
+
set removedFromLists(value) {
|
|
592
|
+
this.RemovedFromLists = value;
|
|
593
|
+
}
|
|
594
|
+
NewlyCreatedLists = [];
|
|
595
|
+
/** @deprecated Use {@link NewlyCreatedLists}. */
|
|
596
|
+
get newlyCreatedLists() {
|
|
597
|
+
return this.NewlyCreatedLists;
|
|
598
|
+
}
|
|
599
|
+
/** @deprecated Use {@link NewlyCreatedLists}. */
|
|
600
|
+
set newlyCreatedLists(value) {
|
|
601
|
+
this.NewlyCreatedLists = value;
|
|
602
|
+
}
|
|
475
603
|
// Cleanup
|
|
476
604
|
destroy$ = new Subject();
|
|
477
605
|
searchSubject = new Subject();
|
|
@@ -490,7 +618,7 @@ export class ListManagementDialogComponent extends BaseAngularComponent {
|
|
|
490
618
|
/**
|
|
491
619
|
* Get dialog title based on config
|
|
492
620
|
*/
|
|
493
|
-
get
|
|
621
|
+
get DialogTitle() {
|
|
494
622
|
if (this.config?.dialogTitle) {
|
|
495
623
|
return this.config.dialogTitle;
|
|
496
624
|
}
|
|
@@ -505,10 +633,14 @@ export class ListManagementDialogComponent extends BaseAngularComponent {
|
|
|
505
633
|
return `Manage List Membership`;
|
|
506
634
|
}
|
|
507
635
|
}
|
|
636
|
+
/** @deprecated Use {@link DialogTitle}. */
|
|
637
|
+
get dialogTitle() {
|
|
638
|
+
return this.DialogTitle;
|
|
639
|
+
}
|
|
508
640
|
/**
|
|
509
641
|
* Get subtitle showing context
|
|
510
642
|
*/
|
|
511
|
-
get
|
|
643
|
+
get DialogSubtitle() {
|
|
512
644
|
const recordCount = this.config?.recordIds?.length || 0;
|
|
513
645
|
const entityName = this.config?.entityName || 'records';
|
|
514
646
|
if (recordCount === 1 && this.config?.recordDisplayNames?.[0]) {
|
|
@@ -516,30 +648,46 @@ export class ListManagementDialogComponent extends BaseAngularComponent {
|
|
|
516
648
|
}
|
|
517
649
|
return `${recordCount} ${entityName} record${recordCount !== 1 ? 's' : ''}`;
|
|
518
650
|
}
|
|
651
|
+
/** @deprecated Use {@link DialogSubtitle}. */
|
|
652
|
+
get dialogSubtitle() {
|
|
653
|
+
return this.DialogSubtitle;
|
|
654
|
+
}
|
|
519
655
|
/**
|
|
520
656
|
* Check if there are pending changes
|
|
521
657
|
*/
|
|
658
|
+
get HasChanges() {
|
|
659
|
+
return this.AddedToLists.size > 0 || this.RemovedFromLists.size > 0;
|
|
660
|
+
}
|
|
661
|
+
/** @deprecated Use {@link HasChanges}. */
|
|
522
662
|
get hasChanges() {
|
|
523
|
-
return this.
|
|
663
|
+
return this.HasChanges;
|
|
524
664
|
}
|
|
525
665
|
/**
|
|
526
666
|
* Get count of lists to add to
|
|
527
667
|
*/
|
|
668
|
+
get AddCount() {
|
|
669
|
+
return this.AddedToLists.size;
|
|
670
|
+
}
|
|
671
|
+
/** @deprecated Use {@link AddCount}. */
|
|
528
672
|
get addCount() {
|
|
529
|
-
return this.
|
|
673
|
+
return this.AddCount;
|
|
530
674
|
}
|
|
531
675
|
/**
|
|
532
676
|
* Get count of lists to remove from
|
|
533
677
|
*/
|
|
678
|
+
get RemoveCount() {
|
|
679
|
+
return this.RemovedFromLists.size;
|
|
680
|
+
}
|
|
681
|
+
/** @deprecated Use {@link RemoveCount}. */
|
|
534
682
|
get removeCount() {
|
|
535
|
-
return this.
|
|
683
|
+
return this.RemoveCount;
|
|
536
684
|
}
|
|
537
685
|
/**
|
|
538
686
|
* Setup search with debounce
|
|
539
687
|
*/
|
|
540
688
|
setupSearchDebounce() {
|
|
541
689
|
this.searchSubject.pipe(debounceTime(300), takeUntil(this.destroy$)).subscribe((searchText) => {
|
|
542
|
-
this.
|
|
690
|
+
this.SearchText = searchText;
|
|
543
691
|
this.applyFilters();
|
|
544
692
|
});
|
|
545
693
|
}
|
|
@@ -558,16 +706,16 @@ export class ListManagementDialogComponent extends BaseAngularComponent {
|
|
|
558
706
|
* Reset all state
|
|
559
707
|
*/
|
|
560
708
|
resetState() {
|
|
561
|
-
this.
|
|
562
|
-
this.
|
|
563
|
-
this.
|
|
564
|
-
this.
|
|
565
|
-
this.
|
|
566
|
-
this.
|
|
567
|
-
this.
|
|
568
|
-
this.
|
|
569
|
-
this.
|
|
570
|
-
this.
|
|
709
|
+
this.SearchText = '';
|
|
710
|
+
this.ActiveTab = 'all';
|
|
711
|
+
this.SortOption = 'name';
|
|
712
|
+
this.ShowCreateForm = false;
|
|
713
|
+
this.NewListName = '';
|
|
714
|
+
this.NewListDescription = '';
|
|
715
|
+
this.NewListCategoryId = null;
|
|
716
|
+
this.AddedToLists.clear();
|
|
717
|
+
this.RemovedFromLists.clear();
|
|
718
|
+
this.NewlyCreatedLists = [];
|
|
571
719
|
this.originalMembership.clear();
|
|
572
720
|
}
|
|
573
721
|
/**
|
|
@@ -576,7 +724,7 @@ export class ListManagementDialogComponent extends BaseAngularComponent {
|
|
|
576
724
|
async loadData() {
|
|
577
725
|
if (!this.config)
|
|
578
726
|
return;
|
|
579
|
-
this.
|
|
727
|
+
this.Loading = true;
|
|
580
728
|
this.cdr.detectChanges();
|
|
581
729
|
try {
|
|
582
730
|
const md = this.ProviderToUse;
|
|
@@ -587,20 +735,20 @@ export class ListManagementDialogComponent extends BaseAngularComponent {
|
|
|
587
735
|
this.listService.getRecordMembership(this.config.entityId, this.config.recordIds),
|
|
588
736
|
this.listService.getListCategories()
|
|
589
737
|
]);
|
|
590
|
-
this.
|
|
738
|
+
this.Categories = categories;
|
|
591
739
|
// Build view models
|
|
592
|
-
this.
|
|
740
|
+
this.AllLists = await this.listService.buildListViewModels(lists, this.config.recordIds, membership);
|
|
593
741
|
// Store original membership state
|
|
594
|
-
for (const vm of this.
|
|
742
|
+
for (const vm of this.AllLists) {
|
|
595
743
|
this.originalMembership.set(vm.list.ID, vm.isFullMember || vm.isPartialMember);
|
|
596
744
|
}
|
|
597
745
|
// Pre-select lists if configured
|
|
598
746
|
if (this.config.preSelectedListIds) {
|
|
599
747
|
for (const listId of this.config.preSelectedListIds) {
|
|
600
|
-
const vm = this.
|
|
748
|
+
const vm = this.AllLists.find(l => UUIDsEqual(l.list.ID, listId));
|
|
601
749
|
if (vm) {
|
|
602
750
|
vm.isSelectedForAdd = true;
|
|
603
|
-
this.
|
|
751
|
+
this.AddedToLists.add(listId);
|
|
604
752
|
}
|
|
605
753
|
}
|
|
606
754
|
}
|
|
@@ -610,51 +758,67 @@ export class ListManagementDialogComponent extends BaseAngularComponent {
|
|
|
610
758
|
console.error('Error loading list data:', error);
|
|
611
759
|
}
|
|
612
760
|
finally {
|
|
613
|
-
this.
|
|
761
|
+
this.Loading = false;
|
|
614
762
|
this.cdr.detectChanges();
|
|
615
763
|
}
|
|
616
764
|
}
|
|
617
765
|
/**
|
|
618
766
|
* Handle search input
|
|
619
767
|
*/
|
|
620
|
-
|
|
768
|
+
OnSearchInput(event) {
|
|
621
769
|
const value = event.target.value;
|
|
622
770
|
this.searchSubject.next(value);
|
|
623
771
|
}
|
|
772
|
+
/** @deprecated Use {@link OnSearchInput}. */
|
|
773
|
+
onSearchInput(event) {
|
|
774
|
+
return this.OnSearchInput(event);
|
|
775
|
+
}
|
|
624
776
|
/**
|
|
625
777
|
* Clear search
|
|
626
778
|
*/
|
|
627
|
-
|
|
628
|
-
this.
|
|
779
|
+
ClearSearch() {
|
|
780
|
+
this.SearchText = '';
|
|
629
781
|
this.searchSubject.next('');
|
|
630
782
|
}
|
|
783
|
+
/** @deprecated Use {@link ClearSearch}. */
|
|
784
|
+
clearSearch() {
|
|
785
|
+
return this.ClearSearch();
|
|
786
|
+
}
|
|
631
787
|
/**
|
|
632
788
|
* Change active tab
|
|
633
789
|
*/
|
|
634
|
-
|
|
635
|
-
this.
|
|
790
|
+
SetActiveTab(tab) {
|
|
791
|
+
this.ActiveTab = tab;
|
|
636
792
|
this.applyFilters();
|
|
637
793
|
}
|
|
794
|
+
/** @deprecated Use {@link SetActiveTab}. */
|
|
795
|
+
setActiveTab(tab) {
|
|
796
|
+
return this.SetActiveTab(tab);
|
|
797
|
+
}
|
|
638
798
|
/**
|
|
639
799
|
* Change sort option
|
|
640
800
|
*/
|
|
641
|
-
|
|
642
|
-
this.
|
|
801
|
+
SetSortOption(option) {
|
|
802
|
+
this.SortOption = option;
|
|
643
803
|
this.applyFilters();
|
|
644
804
|
}
|
|
805
|
+
/** @deprecated Use {@link SetSortOption}. */
|
|
806
|
+
setSortOption(option) {
|
|
807
|
+
return this.SetSortOption(option);
|
|
808
|
+
}
|
|
645
809
|
/**
|
|
646
810
|
* Apply all filters and sorting
|
|
647
811
|
*/
|
|
648
812
|
applyFilters() {
|
|
649
|
-
let result = [...this.
|
|
813
|
+
let result = [...this.AllLists];
|
|
650
814
|
// Apply search filter
|
|
651
|
-
if (this.
|
|
652
|
-
const search = this.
|
|
815
|
+
if (this.SearchText.trim()) {
|
|
816
|
+
const search = this.SearchText.toLowerCase();
|
|
653
817
|
result = result.filter(vm => vm.list.Name.toLowerCase().includes(search) ||
|
|
654
818
|
(vm.list.Description?.toLowerCase().includes(search)));
|
|
655
819
|
}
|
|
656
820
|
// Apply tab filter
|
|
657
|
-
switch (this.
|
|
821
|
+
switch (this.ActiveTab) {
|
|
658
822
|
case 'my-lists':
|
|
659
823
|
// Already filtered by user in loadData
|
|
660
824
|
break;
|
|
@@ -667,7 +831,7 @@ export class ListManagementDialogComponent extends BaseAngularComponent {
|
|
|
667
831
|
// 'all' and 'shared' - no additional filtering for now
|
|
668
832
|
}
|
|
669
833
|
// Apply sorting
|
|
670
|
-
switch (this.
|
|
834
|
+
switch (this.SortOption) {
|
|
671
835
|
case 'name':
|
|
672
836
|
result.sort((a, b) => a.list.Name.localeCompare(b.list.Name));
|
|
673
837
|
break;
|
|
@@ -678,67 +842,79 @@ export class ListManagementDialogComponent extends BaseAngularComponent {
|
|
|
678
842
|
result.sort((a, b) => b.itemCount - a.itemCount);
|
|
679
843
|
break;
|
|
680
844
|
}
|
|
681
|
-
this.
|
|
845
|
+
this.FilteredLists = result;
|
|
682
846
|
this.cdr.detectChanges();
|
|
683
847
|
}
|
|
684
848
|
/**
|
|
685
849
|
* Toggle list selection for adding
|
|
686
850
|
*/
|
|
687
|
-
|
|
851
|
+
ToggleListForAdd(vm) {
|
|
688
852
|
if (this.config?.mode === 'remove')
|
|
689
853
|
return;
|
|
690
854
|
const listId = vm.list.ID;
|
|
691
|
-
if (vm.isSelectedForAdd || this.
|
|
855
|
+
if (vm.isSelectedForAdd || this.AddedToLists.has(listId)) {
|
|
692
856
|
// Deselect
|
|
693
857
|
vm.isSelectedForAdd = false;
|
|
694
|
-
this.
|
|
858
|
+
this.AddedToLists.delete(listId);
|
|
695
859
|
}
|
|
696
860
|
else {
|
|
697
861
|
// Select for add
|
|
698
862
|
vm.isSelectedForAdd = true;
|
|
699
863
|
vm.isSelectedForRemove = false;
|
|
700
|
-
this.
|
|
701
|
-
this.
|
|
864
|
+
this.AddedToLists.add(listId);
|
|
865
|
+
this.RemovedFromLists.delete(listId);
|
|
702
866
|
}
|
|
703
867
|
this.cdr.detectChanges();
|
|
704
868
|
}
|
|
869
|
+
/** @deprecated Use {@link ToggleListForAdd}. */
|
|
870
|
+
toggleListForAdd(vm) {
|
|
871
|
+
return this.ToggleListForAdd(vm);
|
|
872
|
+
}
|
|
705
873
|
/**
|
|
706
874
|
* Toggle list selection for removal
|
|
707
875
|
*/
|
|
708
|
-
|
|
876
|
+
ToggleListForRemove(vm) {
|
|
709
877
|
if (this.config?.mode === 'add')
|
|
710
878
|
return;
|
|
711
879
|
if (!this.config?.allowRemove && this.config?.mode !== 'manage')
|
|
712
880
|
return;
|
|
713
881
|
const listId = vm.list.ID;
|
|
714
|
-
if (vm.isSelectedForRemove || this.
|
|
882
|
+
if (vm.isSelectedForRemove || this.RemovedFromLists.has(listId)) {
|
|
715
883
|
// Deselect
|
|
716
884
|
vm.isSelectedForRemove = false;
|
|
717
|
-
this.
|
|
885
|
+
this.RemovedFromLists.delete(listId);
|
|
718
886
|
}
|
|
719
887
|
else {
|
|
720
888
|
// Select for remove
|
|
721
889
|
vm.isSelectedForRemove = true;
|
|
722
890
|
vm.isSelectedForAdd = false;
|
|
723
|
-
this.
|
|
724
|
-
this.
|
|
891
|
+
this.RemovedFromLists.add(listId);
|
|
892
|
+
this.AddedToLists.delete(listId);
|
|
725
893
|
}
|
|
726
894
|
this.cdr.detectChanges();
|
|
727
895
|
}
|
|
896
|
+
/** @deprecated Use {@link ToggleListForRemove}. */
|
|
897
|
+
toggleListForRemove(vm) {
|
|
898
|
+
return this.ToggleListForRemove(vm);
|
|
899
|
+
}
|
|
728
900
|
/**
|
|
729
901
|
* Get membership indicator class
|
|
730
902
|
*/
|
|
731
|
-
|
|
903
|
+
GetMembershipClass(vm) {
|
|
732
904
|
if (vm.isFullMember)
|
|
733
905
|
return 'full-member';
|
|
734
906
|
if (vm.isPartialMember)
|
|
735
907
|
return 'partial-member';
|
|
736
908
|
return 'not-member';
|
|
737
909
|
}
|
|
910
|
+
/** @deprecated Use {@link GetMembershipClass}. */
|
|
911
|
+
getMembershipClass(vm) {
|
|
912
|
+
return this.GetMembershipClass(vm);
|
|
913
|
+
}
|
|
738
914
|
/**
|
|
739
915
|
* Get membership indicator text
|
|
740
916
|
*/
|
|
741
|
-
|
|
917
|
+
GetMembershipText(vm) {
|
|
742
918
|
if (vm.isFullMember) {
|
|
743
919
|
return `${vm.membershipCount}/${vm.totalSelectedRecords}`;
|
|
744
920
|
}
|
|
@@ -747,51 +923,67 @@ export class ListManagementDialogComponent extends BaseAngularComponent {
|
|
|
747
923
|
}
|
|
748
924
|
return `0/${vm.totalSelectedRecords}`;
|
|
749
925
|
}
|
|
926
|
+
/** @deprecated Use {@link GetMembershipText}. */
|
|
927
|
+
getMembershipText(vm) {
|
|
928
|
+
return this.GetMembershipText(vm);
|
|
929
|
+
}
|
|
750
930
|
/**
|
|
751
931
|
* Get membership icon
|
|
752
932
|
*/
|
|
753
|
-
|
|
933
|
+
GetMembershipIcon(vm) {
|
|
754
934
|
if (vm.isFullMember)
|
|
755
935
|
return 'fa-solid fa-check-circle';
|
|
756
936
|
if (vm.isPartialMember)
|
|
757
937
|
return 'fa-solid fa-circle-half-stroke';
|
|
758
938
|
return 'fa-regular fa-circle';
|
|
759
939
|
}
|
|
940
|
+
/** @deprecated Use {@link GetMembershipIcon}. */
|
|
941
|
+
getMembershipIcon(vm) {
|
|
942
|
+
return this.GetMembershipIcon(vm);
|
|
943
|
+
}
|
|
760
944
|
/**
|
|
761
945
|
* Show create list form
|
|
762
946
|
*/
|
|
947
|
+
ShowCreateListForm() {
|
|
948
|
+
this.ShowCreateForm = true;
|
|
949
|
+
this.NewListName = '';
|
|
950
|
+
this.NewListDescription = '';
|
|
951
|
+
this.NewListCategoryId = null;
|
|
952
|
+
}
|
|
953
|
+
/** @deprecated Use {@link ShowCreateListForm}. */
|
|
763
954
|
showCreateListForm() {
|
|
764
|
-
this.
|
|
765
|
-
this.newListName = '';
|
|
766
|
-
this.newListDescription = '';
|
|
767
|
-
this.newListCategoryId = null;
|
|
955
|
+
return this.ShowCreateListForm();
|
|
768
956
|
}
|
|
769
957
|
/**
|
|
770
958
|
* Cancel create list form
|
|
771
959
|
*/
|
|
960
|
+
CancelCreateList() {
|
|
961
|
+
this.ShowCreateForm = false;
|
|
962
|
+
this.NewListName = '';
|
|
963
|
+
this.NewListDescription = '';
|
|
964
|
+
this.NewListCategoryId = null;
|
|
965
|
+
}
|
|
966
|
+
/** @deprecated Use {@link CancelCreateList}. */
|
|
772
967
|
cancelCreateList() {
|
|
773
|
-
this.
|
|
774
|
-
this.newListName = '';
|
|
775
|
-
this.newListDescription = '';
|
|
776
|
-
this.newListCategoryId = null;
|
|
968
|
+
return this.CancelCreateList();
|
|
777
969
|
}
|
|
778
970
|
/**
|
|
779
971
|
* Create a new list
|
|
780
972
|
*/
|
|
781
|
-
async
|
|
782
|
-
if (!this.
|
|
973
|
+
async CreateList() {
|
|
974
|
+
if (!this.NewListName.trim() || !this.config)
|
|
783
975
|
return;
|
|
784
976
|
this.saving = true;
|
|
785
977
|
try {
|
|
786
978
|
const createConfig = {
|
|
787
|
-
name: this.
|
|
788
|
-
description: this.
|
|
789
|
-
categoryId: this.
|
|
979
|
+
name: this.NewListName.trim(),
|
|
980
|
+
description: this.NewListDescription.trim() || undefined,
|
|
981
|
+
categoryId: this.NewListCategoryId || undefined,
|
|
790
982
|
entityId: this.config.entityId
|
|
791
983
|
};
|
|
792
984
|
const newList = await this.listService.createList(createConfig);
|
|
793
985
|
if (newList) {
|
|
794
|
-
this.
|
|
986
|
+
this.NewlyCreatedLists.push(newList);
|
|
795
987
|
// Add to view models and select for add
|
|
796
988
|
const vm = {
|
|
797
989
|
list: newList,
|
|
@@ -805,12 +997,12 @@ export class ListManagementDialogComponent extends BaseAngularComponent {
|
|
|
805
997
|
isSelectedForAdd: true,
|
|
806
998
|
isSelectedForRemove: false
|
|
807
999
|
};
|
|
808
|
-
this.
|
|
809
|
-
this.
|
|
810
|
-
this.
|
|
811
|
-
this.
|
|
812
|
-
this.
|
|
813
|
-
this.
|
|
1000
|
+
this.AllLists.unshift(vm);
|
|
1001
|
+
this.AddedToLists.add(newList.ID);
|
|
1002
|
+
this.ShowCreateForm = false;
|
|
1003
|
+
this.NewListName = '';
|
|
1004
|
+
this.NewListDescription = '';
|
|
1005
|
+
this.NewListCategoryId = null;
|
|
814
1006
|
this.applyFilters();
|
|
815
1007
|
}
|
|
816
1008
|
}
|
|
@@ -822,10 +1014,14 @@ export class ListManagementDialogComponent extends BaseAngularComponent {
|
|
|
822
1014
|
this.cdr.detectChanges();
|
|
823
1015
|
}
|
|
824
1016
|
}
|
|
1017
|
+
/** @deprecated Use {@link CreateList}. */
|
|
1018
|
+
async createList() {
|
|
1019
|
+
return this.CreateList();
|
|
1020
|
+
}
|
|
825
1021
|
/**
|
|
826
1022
|
* Apply changes and close dialog
|
|
827
1023
|
*/
|
|
828
|
-
async
|
|
1024
|
+
async ApplyChanges() {
|
|
829
1025
|
if (!this.config)
|
|
830
1026
|
return;
|
|
831
1027
|
this.saving = true;
|
|
@@ -833,19 +1029,19 @@ export class ListManagementDialogComponent extends BaseAngularComponent {
|
|
|
833
1029
|
action: 'apply',
|
|
834
1030
|
added: [],
|
|
835
1031
|
removed: [],
|
|
836
|
-
newListsCreated: this.
|
|
1032
|
+
newListsCreated: this.NewlyCreatedLists,
|
|
837
1033
|
summary: { added: 0, removed: 0, skipped: 0, failed: 0 }
|
|
838
1034
|
};
|
|
839
1035
|
try {
|
|
840
1036
|
// Process additions
|
|
841
|
-
if (this.
|
|
842
|
-
const addResult = await this.listService.addRecordsToLists([...this.
|
|
1037
|
+
if (this.AddedToLists.size > 0) {
|
|
1038
|
+
const addResult = await this.listService.addRecordsToLists([...this.AddedToLists], this.config.recordIds, true // Skip duplicates
|
|
843
1039
|
);
|
|
844
1040
|
result.summary.added += addResult.success;
|
|
845
1041
|
result.summary.skipped += addResult.skipped;
|
|
846
1042
|
result.summary.failed += addResult.failed;
|
|
847
|
-
for (const listId of this.
|
|
848
|
-
const vm = this.
|
|
1043
|
+
for (const listId of this.AddedToLists) {
|
|
1044
|
+
const vm = this.AllLists.find(l => UUIDsEqual(l.list.ID, listId));
|
|
849
1045
|
if (vm) {
|
|
850
1046
|
result.added.push({
|
|
851
1047
|
listId,
|
|
@@ -856,12 +1052,12 @@ export class ListManagementDialogComponent extends BaseAngularComponent {
|
|
|
856
1052
|
}
|
|
857
1053
|
}
|
|
858
1054
|
// Process removals
|
|
859
|
-
if (this.
|
|
860
|
-
const removeResult = await this.listService.removeRecordsFromLists([...this.
|
|
1055
|
+
if (this.RemovedFromLists.size > 0) {
|
|
1056
|
+
const removeResult = await this.listService.removeRecordsFromLists([...this.RemovedFromLists], this.config.recordIds);
|
|
861
1057
|
result.summary.removed += removeResult.success;
|
|
862
1058
|
result.summary.failed += removeResult.failed;
|
|
863
|
-
for (const listId of this.
|
|
864
|
-
const vm = this.
|
|
1059
|
+
for (const listId of this.RemovedFromLists) {
|
|
1060
|
+
const vm = this.AllLists.find(l => UUIDsEqual(l.list.ID, listId));
|
|
865
1061
|
if (vm) {
|
|
866
1062
|
result.removed.push({
|
|
867
1063
|
listId,
|
|
@@ -871,7 +1067,7 @@ export class ListManagementDialogComponent extends BaseAngularComponent {
|
|
|
871
1067
|
}
|
|
872
1068
|
}
|
|
873
1069
|
}
|
|
874
|
-
this.
|
|
1070
|
+
this.Complete.emit(result);
|
|
875
1071
|
}
|
|
876
1072
|
catch (error) {
|
|
877
1073
|
console.error('Error applying changes:', error);
|
|
@@ -882,6 +1078,10 @@ export class ListManagementDialogComponent extends BaseAngularComponent {
|
|
|
882
1078
|
this.cdr.detectChanges();
|
|
883
1079
|
}
|
|
884
1080
|
}
|
|
1081
|
+
/** @deprecated Use {@link ApplyChanges}. */
|
|
1082
|
+
async applyChanges() {
|
|
1083
|
+
return this.ApplyChanges();
|
|
1084
|
+
}
|
|
885
1085
|
/**
|
|
886
1086
|
* Cancel and close dialog
|
|
887
1087
|
*/
|
|
@@ -917,23 +1117,31 @@ export class ListManagementDialogComponent extends BaseAngularComponent {
|
|
|
917
1117
|
/**
|
|
918
1118
|
* Check if we should show the add button for a list
|
|
919
1119
|
*/
|
|
920
|
-
|
|
1120
|
+
ShowAddButton(vm) {
|
|
921
1121
|
if (this.config?.mode === 'remove')
|
|
922
1122
|
return false;
|
|
923
1123
|
return !vm.isFullMember || !this.originalMembership.get(vm.list.ID);
|
|
924
1124
|
}
|
|
1125
|
+
/** @deprecated Use {@link ShowAddButton}. */
|
|
1126
|
+
showAddButton(vm) {
|
|
1127
|
+
return this.ShowAddButton(vm);
|
|
1128
|
+
}
|
|
925
1129
|
/**
|
|
926
1130
|
* Check if we should show the remove button for a list
|
|
927
1131
|
*/
|
|
928
|
-
|
|
1132
|
+
ShowRemoveButton(vm) {
|
|
929
1133
|
if (this.config?.mode === 'add')
|
|
930
1134
|
return false;
|
|
931
1135
|
if (!this.config?.allowRemove && this.config?.mode !== 'manage')
|
|
932
1136
|
return false;
|
|
933
1137
|
return vm.isFullMember || vm.isPartialMember || this.originalMembership.get(vm.list.ID) === true;
|
|
934
1138
|
}
|
|
1139
|
+
/** @deprecated Use {@link ShowRemoveButton}. */
|
|
1140
|
+
showRemoveButton(vm) {
|
|
1141
|
+
return this.ShowRemoveButton(vm);
|
|
1142
|
+
}
|
|
935
1143
|
static ɵfac = function ListManagementDialogComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ListManagementDialogComponent)(i0.ɵɵdirectiveInject(i1.ListManagementService), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
|
|
936
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ListManagementDialogComponent, selectors: [["mj-list-management-dialog"]], inputs: { config: "config", visible: "visible" }, outputs: { complete: "complete", cancel: "cancel" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 1, vars: 1, consts: [[1, "dialog-overlay"], [1, "dialog-overlay", 3, "click"], [1, "dialog-container", 3, "click"], [1, "dialog-header"], [1, "header-content"], [1, "header-icon"], [1, "fa-solid", "fa-rectangle-list"], [1, "header-text"], [1, "dialog-title"], [1, "dialog-subtitle"], ["title", "Close", 1, "close-button", 3, "click"], [1, "fa-solid", "fa-times"], [1, "search-section"], [1, "search-bar"], [1, "fa-solid", "fa-search", "search-icon"], ["type", "text", "placeholder", "Search lists...", 1, "search-input", 3, "input", "value"], [1, "clear-search"], [1, "create-button", 3, "disabled"], [1, "filter-tabs"], [1, "tabs-left"], [1, "tab-button", 3, "click"], [1, "tabs-right"], [1, "sort-select", 3, "change", "value"], ["value", "name"], ["value", "recent"], ["value", "item-count"], [1, "create-form"], [1, "list-content"], [1, "loading-state"], [1, "list-items"], [1, "dialog-footer"], [1, "footer-summary"], [1, "summary-empty"], [1, "footer-actions"], [1, "btn", "btn-secondary", 3, "click", "disabled"], [1, "btn", "btn-primary", 3, "click", "disabled"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "clear-search", 3, "click"], [1, "fa-solid", "fa-times-circle"], [1, "create-button", 3, "click", "disabled"], [1, "fa-solid", "fa-plus"], [1, "button-text"], [1, "create-form-header"], [1, "fa-solid", "fa-plus-circle"], [1, "create-form-body"], [1, "form-group"], ["type", "text", "placeholder", "List name *", 1, "form-input", 3, "ngModelChange", "keyup.enter", "ngModel", "disabled"], ["placeholder", "Description (optional)", "rows", "2", 1, "form-input", "form-textarea", 3, "ngModelChange", "ngModel", "disabled"], [1, "create-form-actions"], [1, "form-input", 3, "ngModelChange", "ngModel", "disabled"], [3, "ngValue"], ["text", "Loading lists...", "size", "medium"], ["Variant", "no-results", "Icon", "fa-solid fa-magnifying-glass", "Title", "No lists found", "Message", "Try a different search term"], ["Icon", "fa-solid fa-rectangle-list", "Title", "No lists yet", "Message", "Create your first list to get started", "ActionIcon", "fa-solid fa-plus", 3, "ActionText"], ["Icon", "fa-solid fa-rectangle-list", "Title", "No lists yet", "Message", "Create your first list to get started", "ActionIcon", "fa-solid fa-plus", 3, "Action", "ActionText"], [1, "list-item", 3, "selected-add", "selected-remove", "is-member"], [1, "list-item"], [1, "list-item-select"], [1, "select-btn", "add-btn", 3, "selected", "title"], [1, "select-btn", "remove-btn", 3, "selected", "title"], [1, "list-item-content"], [1, "list-item-header"], [1, "fa-solid", "fa-folder", "list-icon"], [1, "list-name"], [1, "badge", "badge-new"], [1, "list-item-meta"], [1, "list-count"], [1, "meta-separator"], [1, "list-updated"], [1, "membership-indicator", 3, "class"], [1, "select-btn", "add-btn", 3, "click", "title"], [1, "fa-solid", "fa-check"], [1, "select-btn", "remove-btn", 3, "click", "title"], [1, "fa-solid", "fa-undo"], [1, "fa-solid", "fa-minus"], [1, "list-description"], [1, "membership-indicator"], [1, "membership-text"], [1, "summary-item", "add"], [1, "summary-item", "remove"], [1, "fa-solid", "fa-minus-circle"]], template: function ListManagementDialogComponent_Template(rf, ctx) { if (rf & 1) {
|
|
1144
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ListManagementDialogComponent, selectors: [["mj-list-management-dialog"]], inputs: { config: "config", Visible: "Visible", visible: "visible" }, outputs: { Complete: "Complete", complete: "complete", cancel: "cancel" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 1, vars: 1, consts: [[1, "dialog-overlay"], [1, "dialog-overlay", 3, "click"], [1, "dialog-container", 3, "click"], [1, "dialog-header"], [1, "header-content"], [1, "header-icon"], [1, "fa-solid", "fa-rectangle-list"], [1, "header-text"], [1, "dialog-title"], [1, "dialog-subtitle"], ["title", "Close", 1, "close-button", 3, "click"], [1, "fa-solid", "fa-times"], [1, "search-section"], [1, "search-bar"], [1, "fa-solid", "fa-search", "search-icon"], ["type", "text", "placeholder", "Search lists...", 1, "search-input", 3, "input", "value"], [1, "clear-search"], [1, "create-button", 3, "disabled"], [1, "filter-tabs"], [1, "tabs-left"], [1, "tab-button", 3, "click"], [1, "tabs-right"], [1, "sort-select", 3, "change", "value"], ["value", "name"], ["value", "recent"], ["value", "item-count"], [1, "create-form"], [1, "list-content"], [1, "loading-state"], [1, "list-items"], [1, "dialog-footer"], [1, "footer-summary"], [1, "summary-empty"], [1, "footer-actions"], [1, "btn", "btn-secondary", 3, "click", "disabled"], [1, "btn", "btn-primary", 3, "click", "disabled"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "clear-search", 3, "click"], [1, "fa-solid", "fa-times-circle"], [1, "create-button", 3, "click", "disabled"], [1, "fa-solid", "fa-plus"], [1, "button-text"], [1, "create-form-header"], [1, "fa-solid", "fa-plus-circle"], [1, "create-form-body"], [1, "form-group"], ["type", "text", "placeholder", "List name *", 1, "form-input", 3, "ngModelChange", "keyup.enter", "ngModel", "disabled"], ["placeholder", "Description (optional)", "rows", "2", 1, "form-input", "form-textarea", 3, "ngModelChange", "ngModel", "disabled"], [1, "create-form-actions"], [1, "form-input", 3, "ngModelChange", "ngModel", "disabled"], [3, "ngValue"], ["text", "Loading lists...", "size", "medium"], ["Variant", "no-results", "Icon", "fa-solid fa-magnifying-glass", "Title", "No lists found", "Message", "Try a different search term"], ["Icon", "fa-solid fa-rectangle-list", "Title", "No lists yet", "Message", "Create your first list to get started", "ActionIcon", "fa-solid fa-plus", 3, "ActionText"], ["Icon", "fa-solid fa-rectangle-list", "Title", "No lists yet", "Message", "Create your first list to get started", "ActionIcon", "fa-solid fa-plus", 3, "Action", "ActionText"], [1, "list-item", 3, "selected-add", "selected-remove", "is-member"], [1, "list-item"], [1, "list-item-select"], [1, "select-btn", "add-btn", 3, "selected", "title"], [1, "select-btn", "remove-btn", 3, "selected", "title"], [1, "list-item-content"], [1, "list-item-header"], [1, "fa-solid", "fa-folder", "list-icon"], [1, "list-name"], [1, "badge", "badge-new"], [1, "list-item-meta"], [1, "list-count"], [1, "meta-separator"], [1, "list-updated"], [1, "membership-indicator", 3, "class"], [1, "select-btn", "add-btn", 3, "click", "title"], [1, "fa-solid", "fa-check"], [1, "select-btn", "remove-btn", 3, "click", "title"], [1, "fa-solid", "fa-undo"], [1, "fa-solid", "fa-minus"], [1, "list-description"], [1, "membership-indicator"], [1, "membership-text"], [1, "summary-item", "add"], [1, "summary-item", "remove"], [1, "fa-solid", "fa-minus-circle"]], template: function ListManagementDialogComponent_Template(rf, ctx) { if (rf & 1) {
|
|
937
1145
|
i0.ɵɵconditionalCreate(0, ListManagementDialogComponent_Conditional_0_Template, 50, 18, "div", 0);
|
|
938
1146
|
} if (rf & 2) {
|
|
939
1147
|
i0.ɵɵconditional(ctx.visible ? 0 : -1);
|
|
@@ -944,8 +1152,12 @@ export class ListManagementDialogComponent extends BaseAngularComponent {
|
|
|
944
1152
|
args: [{ standalone: false, selector: 'mj-list-management-dialog', template: "@if (visible) {\n <div class=\"dialog-overlay\" (click)=\"onCancel()\">\n <div class=\"dialog-container\" (click)=\"$event.stopPropagation()\">\n <!-- Header -->\n <div class=\"dialog-header\">\n <div class=\"header-content\">\n <div class=\"header-icon\">\n <span class=\"fa-solid fa-rectangle-list\"></span>\n </div>\n <div class=\"header-text\">\n <h2 class=\"dialog-title\">{{ dialogTitle }}</h2>\n <p class=\"dialog-subtitle\">{{ dialogSubtitle }}</p>\n </div>\n </div>\n <button class=\"close-button\" (click)=\"onCancel()\" title=\"Close\">\n <span class=\"fa-solid fa-times\"></span>\n </button>\n </div>\n\n <!-- Search and Filters -->\n <div class=\"search-section\">\n <div class=\"search-bar\">\n <span class=\"fa-solid fa-search search-icon\"></span>\n <input\n type=\"text\"\n class=\"search-input\"\n placeholder=\"Search lists...\"\n [value]=\"searchText\"\n (input)=\"onSearchInput($event)\"\n />\n @if (searchText) {\n <button class=\"clear-search\" (click)=\"clearSearch()\">\n <span class=\"fa-solid fa-times-circle\"></span>\n </button>\n }\n </div>\n\n @if (config.allowCreate !== false) {\n <button class=\"create-button\" (click)=\"showCreateListForm()\" [disabled]=\"showCreateForm\">\n <span class=\"fa-solid fa-plus\"></span>\n <span class=\"button-text\">New</span>\n </button>\n }\n </div>\n\n <!-- Filter Tabs -->\n <div class=\"filter-tabs\">\n <div class=\"tabs-left\">\n <button\n class=\"tab-button\"\n [class.active]=\"activeTab === 'all'\"\n (click)=\"setActiveTab('all')\">\n All\n </button>\n <button\n class=\"tab-button\"\n [class.active]=\"activeTab === 'my-lists'\"\n (click)=\"setActiveTab('my-lists')\">\n My Lists\n </button>\n <button\n class=\"tab-button\"\n [class.active]=\"activeTab === 'recent'\"\n (click)=\"setActiveTab('recent')\">\n Recent\n </button>\n </div>\n <div class=\"tabs-right\">\n <select class=\"sort-select\" [value]=\"sortOption\" (change)=\"setSortOption($any($event.target).value)\">\n <option value=\"name\">Sort: Name</option>\n <option value=\"recent\">Sort: Recent</option>\n <option value=\"item-count\">Sort: Items</option>\n </select>\n </div>\n </div>\n\n <!-- Create List Form -->\n @if (showCreateForm) {\n <div class=\"create-form\">\n <div class=\"create-form-header\">\n <span class=\"fa-solid fa-plus-circle\"></span>\n <span>Create New List</span>\n </div>\n <div class=\"create-form-body\">\n <div class=\"form-group\">\n <input\n type=\"text\"\n class=\"form-input\"\n placeholder=\"List name *\"\n [(ngModel)]=\"newListName\"\n [disabled]=\"saving\"\n (keyup.enter)=\"createList()\"\n />\n </div>\n <div class=\"form-group\">\n <textarea\n class=\"form-input form-textarea\"\n placeholder=\"Description (optional)\"\n [(ngModel)]=\"newListDescription\"\n [disabled]=\"saving\"\n rows=\"2\">\n </textarea>\n </div>\n @if (categories.length > 0) {\n <div class=\"form-group\">\n <select class=\"form-input\" [(ngModel)]=\"newListCategoryId\" [disabled]=\"saving\">\n <option [ngValue]=\"null\">No category</option>\n @for (category of categories; track category.ID) {\n <option [ngValue]=\"category.ID\">{{ category.Name }}</option>\n }\n </select>\n </div>\n }\n <div class=\"create-form-actions\">\n <button\n class=\"btn btn-primary\"\n (click)=\"createList()\"\n [disabled]=\"!newListName.trim() || saving\">\n @if (saving) {\n <span class=\"fa-solid fa-spinner fa-spin\"></span>\n }\n Create List\n </button>\n <button class=\"btn btn-secondary\" (click)=\"cancelCreateList()\" [disabled]=\"saving\">\n Cancel\n </button>\n </div>\n </div>\n </div>\n }\n\n <!-- List Content -->\n <div class=\"list-content\">\n @if (loading) {\n <div class=\"loading-state\">\n <mj-loading text=\"Loading lists...\" size=\"medium\"></mj-loading>\n </div>\n } @else if (filteredLists.length === 0) {\n @if (searchText) {\n <mj-empty-state\n Variant=\"no-results\"\n Icon=\"fa-solid fa-magnifying-glass\"\n Title=\"No lists found\"\n Message=\"Try a different search term\" />\n } @else {\n <mj-empty-state\n Icon=\"fa-solid fa-rectangle-list\"\n Title=\"No lists yet\"\n Message=\"Create your first list to get started\"\n [ActionText]=\"config.allowCreate !== false ? 'Create List' : ''\"\n ActionIcon=\"fa-solid fa-plus\"\n (Action)=\"showCreateListForm()\" />\n }\n } @else {\n <div class=\"list-items\">\n @for (vm of filteredLists; track vm.list.ID) {\n <div\n class=\"list-item\"\n [class.selected-add]=\"vm.isSelectedForAdd || addedToLists.has(vm.list.ID)\"\n [class.selected-remove]=\"vm.isSelectedForRemove || removedFromLists.has(vm.list.ID)\"\n [class.is-member]=\"vm.isFullMember || vm.isPartialMember\">\n\n <!-- Checkbox / Selection Area -->\n <div class=\"list-item-select\">\n @if (showAddButton(vm)) {\n <button\n class=\"select-btn add-btn\"\n [class.selected]=\"vm.isSelectedForAdd || addedToLists.has(vm.list.ID)\"\n (click)=\"toggleListForAdd(vm)\"\n [title]=\"(vm.isSelectedForAdd || addedToLists.has(vm.list.ID)) ? 'Remove from selection' : 'Add to this list'\">\n @if (vm.isSelectedForAdd || addedToLists.has(vm.list.ID)) {\n <span class=\"fa-solid fa-check\"></span>\n } @else {\n <span class=\"fa-solid fa-plus\"></span>\n }\n </button>\n }\n @if (showRemoveButton(vm) && (vm.isFullMember || vm.isPartialMember)) {\n <button\n class=\"select-btn remove-btn\"\n [class.selected]=\"vm.isSelectedForRemove || removedFromLists.has(vm.list.ID)\"\n (click)=\"toggleListForRemove(vm)\"\n [title]=\"(vm.isSelectedForRemove || removedFromLists.has(vm.list.ID)) ? 'Cancel removal' : 'Remove from this list'\">\n @if (vm.isSelectedForRemove || removedFromLists.has(vm.list.ID)) {\n <span class=\"fa-solid fa-undo\"></span>\n } @else {\n <span class=\"fa-solid fa-minus\"></span>\n }\n </button>\n }\n </div>\n\n <!-- List Info -->\n <div class=\"list-item-content\">\n <div class=\"list-item-header\">\n <span class=\"fa-solid fa-folder list-icon\"></span>\n <span class=\"list-name\">{{ vm.list.Name }}</span>\n @if (newlyCreatedLists.includes(vm.list)) {\n <span class=\"badge badge-new\">New</span>\n }\n </div>\n <div class=\"list-item-meta\">\n @if (vm.list.Description) {\n <span class=\"list-description\">{{ vm.list.Description }}</span>\n <span class=\"meta-separator\">\u2022</span>\n }\n <span class=\"list-count\">{{ vm.itemCount }} item{{ vm.itemCount !== 1 ? 's' : '' }}</span>\n <span class=\"meta-separator\">\u2022</span>\n <span class=\"list-updated\">{{ formatDate(vm.lastUpdated) }}</span>\n </div>\n </div>\n\n <!-- Membership Indicator -->\n @if (config.showMembership !== false) {\n <div class=\"membership-indicator\" [class]=\"getMembershipClass(vm)\">\n <span [class]=\"getMembershipIcon(vm)\"></span>\n <span class=\"membership-text\">{{ getMembershipText(vm) }}</span>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Footer -->\n <div class=\"dialog-footer\">\n <div class=\"footer-summary\">\n @if (hasChanges) {\n @if (addCount > 0) {\n <span class=\"summary-item add\">\n <span class=\"fa-solid fa-plus-circle\"></span>\n {{ addCount }} list{{ addCount !== 1 ? 's' : '' }}\n </span>\n }\n @if (removeCount > 0) {\n <span class=\"summary-item remove\">\n <span class=\"fa-solid fa-minus-circle\"></span>\n {{ removeCount }} list{{ removeCount !== 1 ? 's' : '' }}\n </span>\n }\n } @else {\n <span class=\"summary-empty\">No changes</span>\n }\n </div>\n <div class=\"footer-actions\">\n <button class=\"btn btn-secondary\" (click)=\"onCancel()\" [disabled]=\"saving\">\n Cancel\n </button>\n <button\n class=\"btn btn-primary\"\n (click)=\"applyChanges()\"\n [disabled]=\"!hasChanges || saving\">\n @if (saving) {\n <span class=\"fa-solid fa-spinner fa-spin\"></span>\n }\n Apply Changes\n </button>\n </div>\n </div>\n </div>\n </div>\n}\n", styles: ["/* ============================================\n List Management Dialog - Gorgeous Responsive Design\n ============================================ */\n\n/* Overlay */\n.dialog-overlay {\n position: fixed;\n inset: 0;\n background: var(--mj-bg-overlay);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10000;\n animation: fadeIn 0.2s ease-out;\n backdrop-filter: blur(2px);\n}\n\n@keyframes fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n/* Dialog Container */\n.dialog-container {\n background: var(--mj-bg-surface-card);\n border-radius: 16px;\n box-shadow: 0 25px 50px -12px var(--mj-shadow-lg);\n width: 90vw;\n max-width: 600px;\n max-height: 85vh;\n display: flex;\n flex-direction: column;\n animation: slideUp 0.3s ease-out;\n overflow: hidden;\n}\n\n@keyframes slideUp {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n/* Header */\n.dialog-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 20px 24px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.header-content {\n display: flex;\n align-items: center;\n gap: 16px;\n}\n\n.header-icon {\n width: 48px;\n height: 48px;\n background: rgba(255, 255, 255, 0.2);\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 22px;\n}\n\n.header-text {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.dialog-title {\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n letter-spacing: -0.01em;\n}\n\n.dialog-subtitle {\n margin: 0;\n font-size: 13px;\n opacity: 0.85;\n}\n\n.close-button {\n width: 36px;\n height: 36px;\n border: none;\n background: rgba(255, 255, 255, 0.15);\n border-radius: 8px;\n color: var(--mj-text-inverse);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 16px;\n transition: background 0.2s;\n}\n\n.close-button:hover {\n background: rgba(255, 255, 255, 0.25);\n}\n\n/* Search Section */\n.search-section {\n display: flex;\n gap: 12px;\n padding: 16px 20px;\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.search-bar {\n flex: 1;\n position: relative;\n display: flex;\n align-items: center;\n}\n\n.search-icon {\n position: absolute;\n left: 14px;\n color: var(--mj-text-muted);\n font-size: 14px;\n pointer-events: none;\n}\n\n.search-input {\n width: 100%;\n padding: 12px 40px 12px 42px;\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n font-size: 14px;\n background: var(--mj-bg-surface-card);\n transition: all 0.2s;\n}\n\n.search-input:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.search-input::placeholder {\n color: var(--mj-text-muted);\n}\n\n.clear-search {\n position: absolute;\n right: 12px;\n border: none;\n background: none;\n color: var(--mj-text-muted);\n cursor: pointer;\n padding: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.clear-search:hover {\n color: var(--mj-text-secondary);\n}\n\n.create-button {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 18px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border: none;\n border-radius: 10px;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s;\n white-space: nowrap;\n}\n\n.create-button:hover:not(:disabled) {\n transform: translateY(-1px);\n box-shadow: 0 4px 12px color-mix(in srgb, var(--mj-brand-primary) 40%, transparent);\n}\n\n.create-button:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n/* Filter Tabs */\n.filter-tabs {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n}\n\n.tabs-left {\n display: flex;\n gap: 4px;\n}\n\n.tab-button {\n padding: 8px 16px;\n border: none;\n background: none;\n color: var(--mj-text-secondary);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n border-radius: 6px;\n transition: all 0.2s;\n}\n\n.tab-button:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n}\n\n.tab-button.active {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.sort-select {\n padding: 8px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 13px;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-card);\n cursor: pointer;\n}\n\n.sort-select:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n}\n\n/* Create Form */\n.create-form {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n border-bottom: 1px solid color-mix(in srgb, var(--mj-status-warning) 30%, transparent);\n animation: slideDown 0.2s ease-out;\n}\n\n@keyframes slideDown {\n from {\n opacity: 0;\n max-height: 0;\n }\n to {\n opacity: 1;\n max-height: 300px;\n }\n}\n\n.create-form-header {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 20px;\n font-weight: 600;\n color: var(--mj-status-warning);\n font-size: 14px;\n border-bottom: 1px solid color-mix(in srgb, var(--mj-status-warning) 30%, transparent);\n}\n\n.create-form-body {\n padding: 16px 20px;\n}\n\n.form-group {\n margin-bottom: 12px;\n}\n\n.form-group:last-of-type {\n margin-bottom: 16px;\n}\n\n.form-input {\n width: 100%;\n padding: 12px 14px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n font-size: 14px;\n background: var(--mj-bg-surface-card);\n transition: all 0.2s;\n box-sizing: border-box;\n}\n\n.form-input:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.form-textarea {\n resize: vertical;\n min-height: 60px;\n}\n\n.create-form-actions {\n display: flex;\n gap: 10px;\n justify-content: flex-end;\n}\n\n/* List Content */\n.list-content {\n flex: 1;\n overflow-y: auto;\n min-height: 200px;\n max-height: 400px;\n}\n\n/* Loading State */\n.loading-state {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 60px 20px;\n}\n\n/* List Items */\n.list-items {\n padding: 8px 12px;\n}\n\n.list-item {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 14px 16px;\n margin-bottom: 8px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n transition: all 0.2s;\n}\n\n.list-item:last-child {\n margin-bottom: 0;\n}\n\n.list-item:hover {\n border-color: var(--mj-border-strong);\n box-shadow: 0 2px 8px var(--mj-shadow-sm);\n}\n\n.list-item.selected-add {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n border-color: var(--mj-status-success);\n}\n\n.list-item.selected-remove {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n border-color: var(--mj-status-error);\n}\n\n.list-item.is-member {\n border-left: 3px solid var(--mj-brand-primary);\n}\n\n/* Selection Buttons */\n.list-item-select {\n display: flex;\n gap: 6px;\n}\n\n.select-btn {\n width: 32px;\n height: 32px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-secondary);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 12px;\n transition: all 0.2s;\n}\n\n.select-btn.add-btn:hover {\n border-color: var(--mj-status-success);\n color: var(--mj-status-success);\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n}\n\n.select-btn.add-btn.selected {\n background: var(--mj-status-success);\n border-color: var(--mj-status-success);\n color: var(--mj-text-inverse);\n}\n\n.select-btn.remove-btn:hover {\n border-color: var(--mj-status-error);\n color: var(--mj-status-error);\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n}\n\n.select-btn.remove-btn.selected {\n background: var(--mj-status-error);\n border-color: var(--mj-status-error);\n color: var(--mj-text-inverse);\n}\n\n/* List Item Content */\n.list-item-content {\n flex: 1;\n min-width: 0;\n}\n\n.list-item-header {\n display: flex;\n align-items: center;\n gap: 10px;\n margin-bottom: 4px;\n}\n\n.list-icon {\n color: var(--mj-brand-primary);\n font-size: 14px;\n}\n\n.list-name {\n font-weight: 600;\n font-size: 14px;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.badge {\n padding: 2px 8px;\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.02em;\n}\n\n.badge-new {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.list-item-meta {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 4px;\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.list-description {\n max-width: 180px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.meta-separator {\n color: var(--mj-border-strong);\n}\n\n/* Membership Indicator */\n.membership-indicator {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n border-radius: 20px;\n font-size: 12px;\n font-weight: 500;\n white-space: nowrap;\n}\n\n.membership-indicator.full-member {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.membership-indicator.partial-member {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.membership-indicator.not-member {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n}\n\n.membership-text {\n font-variant-numeric: tabular-nums;\n}\n\n/* Footer */\n.dialog-footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n background: var(--mj-bg-surface-sunken);\n border-top: 1px solid var(--mj-border-default);\n}\n\n.footer-summary {\n display: flex;\n align-items: center;\n gap: 16px;\n}\n\n.summary-item {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 13px;\n font-weight: 500;\n}\n\n.summary-item.add {\n color: var(--mj-status-success);\n}\n\n.summary-item.remove {\n color: var(--mj-status-error);\n}\n\n.summary-empty {\n color: var(--mj-text-muted);\n font-size: 13px;\n}\n\n.footer-actions {\n display: flex;\n gap: 10px;\n}\n\n/* Buttons */\n.btn {\n padding: 10px 20px;\n border-radius: 8px;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 8px;\n transition: all 0.2s;\n border: none;\n}\n\n.btn-primary {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.btn-primary:hover:not(:disabled) {\n box-shadow: 0 4px 12px color-mix(in srgb, var(--mj-brand-primary) 40%, transparent);\n transform: translateY(-1px);\n}\n\n.btn-primary:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n transform: none;\n}\n\n.btn-secondary {\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-secondary);\n border: 1px solid var(--mj-border-default);\n}\n\n.btn-secondary:hover:not(:disabled) {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-strong);\n}\n\n.btn-secondary:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n/* ============================================\n Mobile Responsive - Bottom Sheet Pattern\n ============================================ */\n\n@media (max-width: 640px) {\n .dialog-overlay {\n align-items: flex-end;\n }\n\n .dialog-container {\n width: 100%;\n max-width: 100%;\n max-height: 90vh;\n border-radius: 24px 24px 0 0;\n animation: slideUpMobile 0.3s ease-out;\n }\n\n @keyframes slideUpMobile {\n from {\n transform: translateY(100%);\n }\n to {\n transform: translateY(0);\n }\n }\n\n .dialog-header {\n padding: 16px 20px;\n border-radius: 24px 24px 0 0;\n }\n\n .header-icon {\n width: 40px;\n height: 40px;\n font-size: 18px;\n }\n\n .dialog-title {\n font-size: 16px;\n }\n\n .dialog-subtitle {\n font-size: 12px;\n }\n\n .search-section {\n padding: 12px 16px;\n flex-wrap: wrap;\n }\n\n .search-bar {\n width: 100%;\n order: 1;\n }\n\n .create-button {\n order: 2;\n width: 100%;\n justify-content: center;\n margin-top: 8px;\n }\n\n .button-text {\n display: inline;\n }\n\n .filter-tabs {\n padding: 10px 16px;\n flex-wrap: wrap;\n gap: 8px;\n }\n\n .tabs-left {\n width: 100%;\n justify-content: space-between;\n }\n\n .tab-button {\n flex: 1;\n text-align: center;\n padding: 10px 8px;\n }\n\n .tabs-right {\n width: 100%;\n }\n\n .sort-select {\n width: 100%;\n }\n\n .list-content {\n max-height: 50vh;\n }\n\n .list-items {\n padding: 8px;\n }\n\n .list-item {\n padding: 12px;\n gap: 10px;\n }\n\n .list-item-content {\n flex: 1;\n min-width: 0;\n }\n\n .list-description {\n display: none;\n }\n\n .membership-indicator {\n padding: 4px 8px;\n font-size: 11px;\n }\n\n .dialog-footer {\n padding: 12px 16px;\n flex-direction: column;\n gap: 12px;\n }\n\n .footer-summary {\n width: 100%;\n justify-content: center;\n }\n\n .footer-actions {\n width: 100%;\n }\n\n .footer-actions .btn {\n flex: 1;\n justify-content: center;\n }\n\n .create-form-body {\n padding: 12px 16px;\n }\n\n .create-form-actions {\n flex-direction: column;\n }\n\n .create-form-actions .btn {\n width: 100%;\n justify-content: center;\n }\n}\n\n/* Tablet adjustments */\n@media (min-width: 641px) and (max-width: 1024px) {\n .dialog-container {\n max-width: 550px;\n }\n\n .list-description {\n max-width: 140px;\n }\n}\n\n/* Large screen enhancements */\n@media (min-width: 1025px) {\n .list-content {\n max-height: 450px;\n }\n\n .list-item:hover {\n transform: translateX(4px);\n }\n}\n\n/* Accessibility - Focus states */\n.search-input:focus-visible,\n.tab-button:focus-visible,\n.select-btn:focus-visible,\n.btn:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n/* Reduced motion preference */\n@media (prefers-reduced-motion: reduce) {\n .dialog-overlay,\n .dialog-container,\n .create-form,\n .list-item,\n .btn {\n animation: none;\n transition: none;\n }\n}\n"] }]
|
|
945
1153
|
}], () => [{ type: i1.ListManagementService }, { type: i0.ChangeDetectorRef }], { config: [{
|
|
946
1154
|
type: Input
|
|
1155
|
+
}], Visible: [{
|
|
1156
|
+
type: Input
|
|
947
1157
|
}], visible: [{
|
|
948
1158
|
type: Input
|
|
1159
|
+
}], Complete: [{
|
|
1160
|
+
type: Output
|
|
949
1161
|
}], complete: [{
|
|
950
1162
|
type: Output
|
|
951
1163
|
}], cancel: [{
|