osl-base-extended 1.1.57 → 1.1.59
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.
|
@@ -2603,6 +2603,8 @@ class OslSetup {
|
|
|
2603
2603
|
formFooterTpl;
|
|
2604
2604
|
customFooterWrapperTpl;
|
|
2605
2605
|
searchbar;
|
|
2606
|
+
gridRef;
|
|
2607
|
+
cardContainerRef;
|
|
2606
2608
|
// ── Inputs ────────────────────────────────────────────────────
|
|
2607
2609
|
title = '';
|
|
2608
2610
|
columns = [];
|
|
@@ -2613,8 +2615,7 @@ class OslSetup {
|
|
|
2613
2615
|
tableHeight = 'calc(100vh - 220px)';
|
|
2614
2616
|
totalRecords = 0;
|
|
2615
2617
|
loading = false;
|
|
2616
|
-
dialogWidth =
|
|
2617
|
-
/** Dynamic form elements — when provided, enables Add/Edit dialog and action column. */
|
|
2618
|
+
dialogWidth = '50vw';
|
|
2618
2619
|
formElements = [];
|
|
2619
2620
|
beforeDisplay;
|
|
2620
2621
|
onAddEditFn;
|
|
@@ -2628,10 +2629,14 @@ class OslSetup {
|
|
|
2628
2629
|
partialCustomHeaderTemp;
|
|
2629
2630
|
stateKey = '';
|
|
2630
2631
|
primaryKey = 'id';
|
|
2632
|
+
onSave;
|
|
2633
|
+
/** Fixed page size used for card view infinite scroll. Defaults to pageSize. */
|
|
2634
|
+
cardPageSize;
|
|
2635
|
+
/** Optional custom card template. Context: { $implicit: row, index: number } */
|
|
2636
|
+
cardTemplate;
|
|
2631
2637
|
// ── Outputs ───────────────────────────────────────────────────
|
|
2632
2638
|
onSearch = new EventEmitter();
|
|
2633
2639
|
onAdd = new EventEmitter();
|
|
2634
|
-
// @Output() onSave = new EventEmitter<OslSetupSaveEvent>();
|
|
2635
2640
|
onEdit = new EventEmitter();
|
|
2636
2641
|
onDelete = new EventEmitter();
|
|
2637
2642
|
pageChange = new EventEmitter();
|
|
@@ -2639,15 +2644,231 @@ class OslSetup {
|
|
|
2639
2644
|
sortChange = new EventEmitter();
|
|
2640
2645
|
onRowClick = new EventEmitter();
|
|
2641
2646
|
onStateRestored = new EventEmitter();
|
|
2642
|
-
gridRef;
|
|
2643
|
-
onSave;
|
|
2644
2647
|
// ── Dialog state ──────────────────────────────────────────────
|
|
2645
2648
|
dialogModel = {};
|
|
2646
2649
|
dialogMode = 'add';
|
|
2647
2650
|
_dialogRef = null;
|
|
2651
|
+
// ── View mode ─────────────────────────────────────────────────
|
|
2652
|
+
viewMode = 'table';
|
|
2653
|
+
// ── Card view state ───────────────────────────────────────────
|
|
2654
|
+
cardDatasource = [];
|
|
2655
|
+
cardPage = 0;
|
|
2656
|
+
allCardsLoaded = false;
|
|
2657
|
+
cardOpenMenuIndex = null;
|
|
2658
|
+
cardMenuPosition = { top: 0, left: 0 };
|
|
2659
|
+
_cardExpectedPage = 0;
|
|
2660
|
+
_cardRestoreTargetPage = 0;
|
|
2661
|
+
_needsInitialCardLoad = false;
|
|
2662
|
+
onDocumentClick() {
|
|
2663
|
+
this.cardOpenMenuIndex = null;
|
|
2664
|
+
}
|
|
2648
2665
|
get hasForm() {
|
|
2649
2666
|
return this.formElements?.length > 0 || !!this.onAddEditFn;
|
|
2650
2667
|
}
|
|
2668
|
+
get _effectiveCardPageSize() {
|
|
2669
|
+
return this.cardPageSize ?? this.pageSize;
|
|
2670
|
+
}
|
|
2671
|
+
get _displayColumns() {
|
|
2672
|
+
return this.columns.filter(c => !c.isActions);
|
|
2673
|
+
}
|
|
2674
|
+
get cardTitleColumn() {
|
|
2675
|
+
return this._displayColumns[0];
|
|
2676
|
+
}
|
|
2677
|
+
get cardBodyColumns() {
|
|
2678
|
+
return this._displayColumns.slice(1);
|
|
2679
|
+
}
|
|
2680
|
+
get skeletonCardRows() {
|
|
2681
|
+
return Array.from({ length: 6 });
|
|
2682
|
+
}
|
|
2683
|
+
// ── Lifecycle ─────────────────────────────────────────────────
|
|
2684
|
+
ngOnInit() {
|
|
2685
|
+
this._loadViewMode();
|
|
2686
|
+
if (this.viewMode === 'card') {
|
|
2687
|
+
this._needsInitialCardLoad = true;
|
|
2688
|
+
}
|
|
2689
|
+
}
|
|
2690
|
+
ngAfterViewInit() {
|
|
2691
|
+
this.statemainTain();
|
|
2692
|
+
if (this._needsInitialCardLoad) {
|
|
2693
|
+
this._needsInitialCardLoad = false;
|
|
2694
|
+
setTimeout(() => { this._startCardLoad(); });
|
|
2695
|
+
}
|
|
2696
|
+
}
|
|
2697
|
+
ngOnChanges(changes) {
|
|
2698
|
+
if (changes['datasource']) {
|
|
2699
|
+
if (this.viewMode === 'card') {
|
|
2700
|
+
if (this.autoMode) {
|
|
2701
|
+
// Local pagination: datasource changed (search filtered or initial load), reset
|
|
2702
|
+
if (!changes['datasource'].firstChange) {
|
|
2703
|
+
this._loadCardPageLocally(1);
|
|
2704
|
+
}
|
|
2705
|
+
}
|
|
2706
|
+
else if (this._cardExpectedPage !== 0) {
|
|
2707
|
+
const newData = changes['datasource'].currentValue ?? [];
|
|
2708
|
+
const isFirstPage = this._cardExpectedPage === 1;
|
|
2709
|
+
this._cardExpectedPage = 0;
|
|
2710
|
+
if (isFirstPage) {
|
|
2711
|
+
this.cardDatasource = [...newData];
|
|
2712
|
+
this.cardPage = 1;
|
|
2713
|
+
this.allCardsLoaded = false;
|
|
2714
|
+
}
|
|
2715
|
+
else if (newData.length > 0) {
|
|
2716
|
+
this.cardDatasource = [...this.cardDatasource, ...newData];
|
|
2717
|
+
this.cardPage++;
|
|
2718
|
+
}
|
|
2719
|
+
if (newData.length === 0 || (this.totalRecords > 0 && this.cardDatasource.length >= this.totalRecords)) {
|
|
2720
|
+
this.allCardsLoaded = true;
|
|
2721
|
+
}
|
|
2722
|
+
// Multi-page state restore: continue loading until target page is reached
|
|
2723
|
+
if (this._cardRestoreTargetPage > 0 && this.cardPage < this._cardRestoreTargetPage && !this.allCardsLoaded) {
|
|
2724
|
+
const nextPage = this.cardPage + 1;
|
|
2725
|
+
this._cardExpectedPage = nextPage;
|
|
2726
|
+
this.pageChange.emit({ page: nextPage, pageSize: this._effectiveCardPageSize, searchValue: this.searchbar?.searchControl?.value ?? '' });
|
|
2727
|
+
}
|
|
2728
|
+
else if (this._cardRestoreTargetPage > 0 && (this.cardPage >= this._cardRestoreTargetPage || this.allCardsLoaded)) {
|
|
2729
|
+
this._cardRestoreTargetPage = 0;
|
|
2730
|
+
if (this._pendingScrollTop !== null) {
|
|
2731
|
+
const top = this._pendingScrollTop;
|
|
2732
|
+
this._pendingScrollTop = null;
|
|
2733
|
+
setTimeout(() => { this.cardContainerRef?.nativeElement?.scrollTo({ top }); }, 50);
|
|
2734
|
+
}
|
|
2735
|
+
}
|
|
2736
|
+
}
|
|
2737
|
+
}
|
|
2738
|
+
else if (this._pendingScrollTop !== null) {
|
|
2739
|
+
const ds = changes['datasource'].currentValue;
|
|
2740
|
+
if (ds?.length > 0) {
|
|
2741
|
+
const top = this._pendingScrollTop;
|
|
2742
|
+
this._pendingScrollTop = null;
|
|
2743
|
+
setTimeout(() => { this.gridRef?.scrollTo(top); }, 50);
|
|
2744
|
+
}
|
|
2745
|
+
}
|
|
2746
|
+
}
|
|
2747
|
+
}
|
|
2748
|
+
// ── View persistence ──────────────────────────────────────────
|
|
2749
|
+
_getViewKey() {
|
|
2750
|
+
return this.stateKey ? `osl-view-${this.stateKey}` : '';
|
|
2751
|
+
}
|
|
2752
|
+
_loadViewMode() {
|
|
2753
|
+
const key = this._getViewKey();
|
|
2754
|
+
if (!key)
|
|
2755
|
+
return;
|
|
2756
|
+
const saved = localStorage.getItem(key);
|
|
2757
|
+
if (saved === 'card' || saved === 'table') {
|
|
2758
|
+
this.viewMode = saved;
|
|
2759
|
+
}
|
|
2760
|
+
}
|
|
2761
|
+
toggleView(mode) {
|
|
2762
|
+
if (this.viewMode === mode)
|
|
2763
|
+
return;
|
|
2764
|
+
this.viewMode = mode;
|
|
2765
|
+
const key = this._getViewKey();
|
|
2766
|
+
if (key)
|
|
2767
|
+
localStorage.setItem(key, mode);
|
|
2768
|
+
if (mode === 'card') {
|
|
2769
|
+
this._startCardLoad();
|
|
2770
|
+
}
|
|
2771
|
+
else {
|
|
2772
|
+
this._cardExpectedPage = 0;
|
|
2773
|
+
if (this.gridRef)
|
|
2774
|
+
this.gridRef.currentPage = 1;
|
|
2775
|
+
this.pageChange.emit({ page: 1, pageSize: this.pageSize, searchValue: this.searchbar?.searchControl?.value ?? '' });
|
|
2776
|
+
}
|
|
2777
|
+
}
|
|
2778
|
+
// ── Card view helpers ─────────────────────────────────────────
|
|
2779
|
+
_startCardLoad() {
|
|
2780
|
+
this.cardDatasource = [];
|
|
2781
|
+
this.cardPage = 0;
|
|
2782
|
+
this.allCardsLoaded = false;
|
|
2783
|
+
this._cardRestoreTargetPage = 0;
|
|
2784
|
+
if (this.autoMode) {
|
|
2785
|
+
this._loadCardPageLocally(1);
|
|
2786
|
+
}
|
|
2787
|
+
else {
|
|
2788
|
+
this._cardExpectedPage = 1;
|
|
2789
|
+
this.pageChange.emit({ page: 1, pageSize: this._effectiveCardPageSize, searchValue: this.searchbar?.searchControl?.value ?? '' });
|
|
2790
|
+
}
|
|
2791
|
+
}
|
|
2792
|
+
_loadCardPageLocally(page) {
|
|
2793
|
+
const ps = this._effectiveCardPageSize;
|
|
2794
|
+
const slice = this.datasource.slice((page - 1) * ps, page * ps);
|
|
2795
|
+
if (page === 1) {
|
|
2796
|
+
this.cardDatasource = [...slice];
|
|
2797
|
+
this.allCardsLoaded = false;
|
|
2798
|
+
}
|
|
2799
|
+
else {
|
|
2800
|
+
this.cardDatasource = [...this.cardDatasource, ...slice];
|
|
2801
|
+
}
|
|
2802
|
+
this.cardPage = page;
|
|
2803
|
+
if (this.datasource.length > 0 && (this.cardDatasource.length >= this.datasource.length || slice.length < ps)) {
|
|
2804
|
+
this.allCardsLoaded = true;
|
|
2805
|
+
}
|
|
2806
|
+
}
|
|
2807
|
+
loadMoreCards() {
|
|
2808
|
+
if (this.loading || this.allCardsLoaded)
|
|
2809
|
+
return;
|
|
2810
|
+
if (this.autoMode) {
|
|
2811
|
+
if (this.cardDatasource.length >= this.datasource.length) {
|
|
2812
|
+
this.allCardsLoaded = true;
|
|
2813
|
+
return;
|
|
2814
|
+
}
|
|
2815
|
+
this._loadCardPageLocally(this.cardPage + 1);
|
|
2816
|
+
return;
|
|
2817
|
+
}
|
|
2818
|
+
if (this._cardExpectedPage !== 0)
|
|
2819
|
+
return;
|
|
2820
|
+
if (this.totalRecords > 0 && this.cardDatasource.length >= this.totalRecords) {
|
|
2821
|
+
this.allCardsLoaded = true;
|
|
2822
|
+
return;
|
|
2823
|
+
}
|
|
2824
|
+
const nextPage = this.cardPage + 1;
|
|
2825
|
+
this._cardExpectedPage = nextPage;
|
|
2826
|
+
this.pageChange.emit({ page: nextPage, pageSize: this._effectiveCardPageSize, searchValue: this.searchbar?.searchControl?.value ?? '' });
|
|
2827
|
+
}
|
|
2828
|
+
onCardScroll(event) {
|
|
2829
|
+
const el = event.target;
|
|
2830
|
+
if (el.scrollHeight - el.scrollTop - el.clientHeight < 150) {
|
|
2831
|
+
this.loadMoreCards();
|
|
2832
|
+
}
|
|
2833
|
+
}
|
|
2834
|
+
isHighlightedCard(row) {
|
|
2835
|
+
if (!this.restoredRow || !this.primaryKey)
|
|
2836
|
+
return false;
|
|
2837
|
+
const val = row[this.primaryKey];
|
|
2838
|
+
return val !== undefined && val === this.restoredRow[this.primaryKey];
|
|
2839
|
+
}
|
|
2840
|
+
toggleCardMenu(index, event) {
|
|
2841
|
+
event.stopPropagation();
|
|
2842
|
+
if (this.cardOpenMenuIndex === index) {
|
|
2843
|
+
this.cardOpenMenuIndex = null;
|
|
2844
|
+
return;
|
|
2845
|
+
}
|
|
2846
|
+
const rect = event.currentTarget.getBoundingClientRect();
|
|
2847
|
+
const menuWidth = 190;
|
|
2848
|
+
const left = Math.min(Math.max(rect.right - menuWidth, 8), window.innerWidth - menuWidth - 8);
|
|
2849
|
+
this.cardMenuPosition = { top: rect.bottom + 6, left };
|
|
2850
|
+
this.cardOpenMenuIndex = index;
|
|
2851
|
+
}
|
|
2852
|
+
getCellValue(row, col) {
|
|
2853
|
+
const raw = row[col.key];
|
|
2854
|
+
if (col.displayFn)
|
|
2855
|
+
return col.displayFn(raw, row);
|
|
2856
|
+
if (col.enums?.length) {
|
|
2857
|
+
const match = col.enums.find(e => e.value === raw);
|
|
2858
|
+
return match ? match.label : (raw ?? '--');
|
|
2859
|
+
}
|
|
2860
|
+
return raw !== null && raw !== undefined && raw !== '' ? raw : '--';
|
|
2861
|
+
}
|
|
2862
|
+
getCardInitial(row) {
|
|
2863
|
+
if (!this.cardTitleColumn)
|
|
2864
|
+
return '?';
|
|
2865
|
+
const val = this.getCellValue(row, this.cardTitleColumn);
|
|
2866
|
+
return val && val !== '--' ? val[0].toUpperCase() : '?';
|
|
2867
|
+
}
|
|
2868
|
+
hasVisibleActions(row) {
|
|
2869
|
+
return this.moreMenuActions.some(a => !a.hideIf || !a.hideIf(row));
|
|
2870
|
+
}
|
|
2871
|
+
// ── State maintenance ─────────────────────────────────────────
|
|
2651
2872
|
statemainTain() {
|
|
2652
2873
|
if (!this.stateKey)
|
|
2653
2874
|
return;
|
|
@@ -2656,51 +2877,84 @@ class OslSetup {
|
|
|
2656
2877
|
return;
|
|
2657
2878
|
this._pendingScrollTop = state.scrollTop;
|
|
2658
2879
|
this.restoredRow = state.highlightedRow;
|
|
2659
|
-
if (this.
|
|
2660
|
-
this.
|
|
2661
|
-
this.
|
|
2662
|
-
this.
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2880
|
+
if (this.viewMode === 'card') {
|
|
2881
|
+
this._needsInitialCardLoad = false;
|
|
2882
|
+
this.cardDatasource = [];
|
|
2883
|
+
this.cardPage = 0;
|
|
2884
|
+
this.allCardsLoaded = false;
|
|
2885
|
+
if (this.autoMode) {
|
|
2886
|
+
// Restore pages locally from current datasource
|
|
2887
|
+
const targetCount = state.page * this._effectiveCardPageSize;
|
|
2888
|
+
this.cardDatasource = this.datasource.slice(0, targetCount);
|
|
2889
|
+
this.cardPage = state.page;
|
|
2890
|
+
this.allCardsLoaded = this.cardDatasource.length >= this.datasource.length;
|
|
2891
|
+
if (this._pendingScrollTop !== null) {
|
|
2892
|
+
const top = this._pendingScrollTop;
|
|
2893
|
+
this._pendingScrollTop = null;
|
|
2894
|
+
setTimeout(() => { this.cardContainerRef?.nativeElement?.scrollTo({ top }); }, 50);
|
|
2895
|
+
}
|
|
2896
|
+
this.onStateRestored.emit(state);
|
|
2897
|
+
}
|
|
2898
|
+
else {
|
|
2899
|
+
this._cardRestoreTargetPage = state.page;
|
|
2900
|
+
if (this.searchbar && state.searchValue) {
|
|
2901
|
+
this._isRestoring = true;
|
|
2902
|
+
this.searchbar.searchControl.setValue(state.searchValue, { emitEvent: false });
|
|
2903
|
+
}
|
|
2904
|
+
this._cardExpectedPage = 1;
|
|
2905
|
+
if (state.searchValue) {
|
|
2906
|
+
this.onSearchSetup(state.searchValue);
|
|
2907
|
+
}
|
|
2908
|
+
else {
|
|
2909
|
+
this.pageChange.emit({ page: 1, pageSize: this._effectiveCardPageSize, searchValue: '' });
|
|
2910
|
+
}
|
|
2911
|
+
this.onStateRestored.emit(state);
|
|
2912
|
+
}
|
|
2672
2913
|
}
|
|
2673
2914
|
else {
|
|
2674
|
-
|
|
2675
|
-
|
|
2915
|
+
if (this.gridRef) {
|
|
2916
|
+
this.gridRef.currentPage = state.page;
|
|
2917
|
+
this.gridRef.pageSize = state.pageSize;
|
|
2918
|
+
this.gridRef.setRestorePage(state.page);
|
|
2919
|
+
}
|
|
2920
|
+
if (this.searchbar && state.searchValue) {
|
|
2921
|
+
this._isRestoring = true;
|
|
2922
|
+
this.searchbar.searchControl.setValue(state.searchValue, { emitEvent: false });
|
|
2923
|
+
}
|
|
2924
|
+
if (state.searchValue) {
|
|
2925
|
+
this.onSearchSetup(state.searchValue);
|
|
2926
|
+
}
|
|
2927
|
+
else {
|
|
2928
|
+
this.pageChange.emit({ page: state.page, pageSize: state.pageSize, searchValue: '' });
|
|
2929
|
+
}
|
|
2930
|
+
this.onStateRestored.emit(state);
|
|
2676
2931
|
}
|
|
2677
|
-
// Also emit the dedicated restore event for apps that want fine-grained control.
|
|
2678
|
-
this.onStateRestored.emit(state);
|
|
2679
2932
|
setTimeout(() => {
|
|
2680
2933
|
this.restoredRow = null;
|
|
2681
2934
|
this.gridRef?.clearRestorePage();
|
|
2682
2935
|
}, 3000);
|
|
2683
2936
|
}
|
|
2684
|
-
|
|
2685
|
-
this.statemainTain();
|
|
2686
|
-
}
|
|
2687
|
-
ngOnChanges(changes) {
|
|
2688
|
-
if (changes['datasource'] && this._pendingScrollTop !== null) {
|
|
2689
|
-
const ds = changes['datasource'].currentValue;
|
|
2690
|
-
// Only restore scroll once real data has arrived (not on intermediate empty/loading states)
|
|
2691
|
-
if (ds?.length > 0) {
|
|
2692
|
-
const scrollTop = this._pendingScrollTop;
|
|
2693
|
-
this._pendingScrollTop = null;
|
|
2694
|
-
setTimeout(() => { this.gridRef?.scrollTo(scrollTop); }, 50);
|
|
2695
|
-
}
|
|
2696
|
-
}
|
|
2697
|
-
}
|
|
2937
|
+
// ── Search ────────────────────────────────────────────────────
|
|
2698
2938
|
onSearchSetup(event) {
|
|
2939
|
+
if (this.viewMode === 'card' && this.autoMode) {
|
|
2940
|
+
// Local mode: parent filters datasource; ngOnChanges will repopulate cards
|
|
2941
|
+
this.onSearch.emit(event);
|
|
2942
|
+
return;
|
|
2943
|
+
}
|
|
2944
|
+
if (this.viewMode === 'card') {
|
|
2945
|
+
this.cardDatasource = [];
|
|
2946
|
+
this.cardPage = 0;
|
|
2947
|
+
this.allCardsLoaded = false;
|
|
2948
|
+
this._cardExpectedPage = 1;
|
|
2949
|
+
}
|
|
2699
2950
|
if (this._isRestoring) {
|
|
2700
|
-
|
|
2701
|
-
const restoredPage = this.gridRef?.currentPage ?? 1;
|
|
2951
|
+
const restoredPage = this.viewMode === 'card' ? 1 : (this.gridRef?.currentPage ?? 1);
|
|
2702
2952
|
this._isRestoring = false;
|
|
2703
|
-
this.pageChange.emit({
|
|
2953
|
+
this.pageChange.emit({
|
|
2954
|
+
page: restoredPage,
|
|
2955
|
+
pageSize: this.viewMode === 'card' ? this._effectiveCardPageSize : (this.gridRef?.pageSize ?? this.pageSize),
|
|
2956
|
+
searchValue: event,
|
|
2957
|
+
});
|
|
2704
2958
|
this.onSearch.emit(event);
|
|
2705
2959
|
return;
|
|
2706
2960
|
}
|
|
@@ -2710,12 +2964,12 @@ class OslSetup {
|
|
|
2710
2964
|
}
|
|
2711
2965
|
this.pageChange.emit({
|
|
2712
2966
|
page: 1,
|
|
2713
|
-
pageSize: this.gridRef?.pageSize || 10,
|
|
2714
|
-
searchValue: event
|
|
2967
|
+
pageSize: this.viewMode === 'card' ? this._effectiveCardPageSize : (this.gridRef?.pageSize || 10),
|
|
2968
|
+
searchValue: event,
|
|
2715
2969
|
});
|
|
2716
2970
|
this.onSearch.emit(event);
|
|
2717
2971
|
}
|
|
2718
|
-
|
|
2972
|
+
// ── Table helpers ─────────────────────────────────────────────
|
|
2719
2973
|
get columnsWithActions() {
|
|
2720
2974
|
if (!this.hasForm)
|
|
2721
2975
|
return this.columns;
|
|
@@ -2728,6 +2982,7 @@ class OslSetup {
|
|
|
2728
2982
|
onPageChange(eventEmitter, event) {
|
|
2729
2983
|
eventEmitter.emit({ ...event, searchValue: this.searchbar?.searchControl?.value });
|
|
2730
2984
|
}
|
|
2985
|
+
// ── Dialog actions ────────────────────────────────────────────
|
|
2731
2986
|
openAddDialog() {
|
|
2732
2987
|
this.dialogMode = 'add';
|
|
2733
2988
|
if (this.beforeDisplay) {
|
|
@@ -2747,10 +3002,12 @@ class OslSetup {
|
|
|
2747
3002
|
this.dialogMode = 'edit';
|
|
2748
3003
|
if (this.stateKey) {
|
|
2749
3004
|
this._stateService.save(this.stateKey, {
|
|
2750
|
-
page: this.gridRef?.currentPage ?? 1,
|
|
2751
|
-
pageSize: this.gridRef?.pageSize ?? this.pageSize,
|
|
3005
|
+
page: this.viewMode === 'card' ? this.cardPage : (this.gridRef?.currentPage ?? 1),
|
|
3006
|
+
pageSize: this.viewMode === 'card' ? this._effectiveCardPageSize : (this.gridRef?.pageSize ?? this.pageSize),
|
|
2752
3007
|
searchValue: this.searchbar?.searchControl?.value ?? '',
|
|
2753
|
-
scrollTop: this.
|
|
3008
|
+
scrollTop: this.viewMode === 'card'
|
|
3009
|
+
? (this.cardContainerRef?.nativeElement?.scrollTop ?? 0)
|
|
3010
|
+
: (this.gridRef?.getScrollTop() ?? 0),
|
|
2754
3011
|
highlightedRow: row,
|
|
2755
3012
|
});
|
|
2756
3013
|
}
|
|
@@ -2761,7 +3018,6 @@ class OslSetup {
|
|
|
2761
3018
|
}
|
|
2762
3019
|
this._openDialog();
|
|
2763
3020
|
if (this.beforeDisplay) {
|
|
2764
|
-
// this.datasource.find(x=>x[this.primaryKey]==)
|
|
2765
3021
|
this.formLoading = true;
|
|
2766
3022
|
this.dialogModel = await this.beforeDisplay(row);
|
|
2767
3023
|
this.formLoading = false;
|
|
@@ -2813,16 +3069,16 @@ class OslSetup {
|
|
|
2813
3069
|
formFooter: this.customFormFooter ? this.customFooterWrapperTpl : this.formFooterTpl,
|
|
2814
3070
|
},
|
|
2815
3071
|
});
|
|
2816
|
-
this._dialogRef.afterClosed().subscribe(
|
|
3072
|
+
this._dialogRef.afterClosed().subscribe(() => {
|
|
2817
3073
|
this.statemainTain();
|
|
2818
3074
|
});
|
|
2819
3075
|
}
|
|
2820
3076
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: OslSetup, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2821
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: OslSetup, isStandalone: false, selector: "osl-setup", inputs: { title: "title", columns: "columns", datasource: "datasource", isPaginated: "isPaginated", pageSize: "pageSize", autoMode: "autoMode", tableHeight: "tableHeight", totalRecords: "totalRecords", loading: "loading", dialogWidth: "dialogWidth", formElements: "formElements", beforeDisplay: "beforeDisplay", onAddEditFn: "onAddEditFn", isLister: "isLister", canAdd: "canAdd", canEdit: "canEdit", canDelete: "canDelete", moreMenuActions: "moreMenuActions", customFormFooter: "customFormFooter", customHeaderTemp: "customHeaderTemp", partialCustomHeaderTemp: "partialCustomHeaderTemp", stateKey: "stateKey", primaryKey: "primaryKey", onSave: "onSave" }, outputs: { onSearch: "onSearch", onAdd: "onAdd", onEdit: "onEdit", onDelete: "onDelete", pageChange: "pageChange", pageSizeChange: "pageSizeChange", sortChange: "sortChange", onRowClick: "onRowClick", onStateRestored: "onStateRestored" }, viewQueries: [{ propertyName: "formBodyTpl", first: true, predicate: ["formBodyTpl"], descendants: true }, { propertyName: "formFooterTpl", first: true, predicate: ["formFooterTpl"], descendants: true }, { propertyName: "customFooterWrapperTpl", first: true, predicate: ["customFooterWrapperTpl"], descendants: true }, { propertyName: "searchbar", first: true, predicate: ["searchbar"], descendants: true }, { propertyName: "gridRef", first: true, predicate: ["gridRef"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"p-2\">\r\n\r\n <!-- Header -->\r\n <div class=\"osl-setup-header\">\r\n <h5 class=\"mb-0\">{{ title }}</h5>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <osl-searchbar #searchbar class=\"mx-2\" (onSearch)=\"onSearchSetup($event)\"></osl-searchbar>\r\n @if(!isLister && canAdd){\r\n <osl-button\r\n variant=\"secondary\"\r\n size=\"sm\"\r\n [label]=\"'Add ' + title\"\r\n (clickEv)=\"openAddDialog()\"\r\n ></osl-button>\r\n\r\n }\r\n </div>\r\n </div>\r\n\r\n <!-- Grid -->\r\n <div class=\"osl-setup-body my-2\">\r\n <osl-grid\r\n #gridRef\r\n [columns]=\"columnsWithActions\"\r\n [(datasource)]=\"datasource\"\r\n [isPaginated]=\"isPaginated\"\r\n [pageSize]=\"pageSize\"\r\n [autoMode]=\"autoMode\"\r\n [tableHeight]=\"tableHeight\"\r\n [totalRecords]=\"totalRecords\"\r\n [loading]=\"loading\"\r\n [moreMenuActions]=\"moreMenuActions\"\r\n [canEdit]=\"canEdit\"\r\n [canDelete]=\"canDelete\"\r\n [highlightedRow]=\"restoredRow\"\r\n [primaryKey]=\"primaryKey\"\r\n (editClick)=\"openEditDialog($event)\"\r\n (deleteClick)=\"onDeleteClick($event)\"\r\n (pageChange)=\"onPageChange(pageChange,$event)\"\r\n (pageSizeChange)=\"onPageChange(pageSizeChange,$event)\"\r\n (sortChange)=\"sortChange.emit($event)\"\r\n [isSelectable]=\"isLister\";\r\n (onRowClick)=\"onRowClick.emit($event)\"\r\n />\r\n </div>\r\n\r\n</div>\r\n\r\n<!-- Dialog: Form Body -->\r\n<ng-template #formBodyTpl>\r\n <osl-dynamic-form\r\n [skeletonLoading]=\"formLoading\"\r\n [elements]=\"formElements\"\r\n [(model)]=\"dialogModel\"\r\n ></osl-dynamic-form>\r\n</ng-template>\r\n\r\n<!-- Dialog: Form Footer -->\r\n<ng-template #formFooterTpl>\r\n <div class=\"osl-setup-dialog-footer\">\r\n\r\n\r\n <osl-button [loading]=\"saveLoading\" variant=\"secondary\" label=\"Save\" (click)=\"saveDialog()\"></osl-button>\r\n\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Wrapper that bridges DialogWrapper's implicit context to the custom footer template -->\r\n<ng-template #customFooterWrapperTpl let-data>\r\n <ng-container *ngTemplateOutlet=\"customFormFooter!; context: { $implicit: { dialogModel: dialogModel, dialogMode: dialogMode, dialogRef: data.dialogRef } }\"></ng-container>\r\n</ng-template>\r\n", styles: [".osl-setup-header{display:flex;align-items:center;justify-content:space-between}.osl-setup-dialog-footer{display:flex;align-items:center;justify-content:flex-end;gap:10px;width:100%}.dialog-cancel-btn{display:flex;align-items:center;gap:6px;height:38px;font-size:13px;font-weight:500;border-color:var(--osl-border-color, #d1d5db);color:var(--osl-secondary, #6b7280);border-radius:var(--osl-border-radius, 4px);padding:0 16px;transition:all .2s ease}.dialog-cancel-btn mat-icon{font-size:17px;width:17px;height:17px}.dialog-cancel-btn:hover{border-color:#9ca3af;background:#f9fafb;color:#374151}.dialog-save-btn{display:flex;align-items:center;gap:6px;height:38px;font-size:13px;font-weight:500;background:linear-gradient(135deg,var(--osl-primary, #2563eb),#3b82f6);color:#fff;border-radius:var(--osl-border-radius, 4px);padding:0 18px;transition:all .2s ease;box-shadow:0 2px 8px #2563eb40}.dialog-save-btn mat-icon{font-size:17px;width:17px;height:17px}.dialog-save-btn:hover{background:linear-gradient(135deg,var(--osl-primary-hover, #1d4ed8),#2563eb);box-shadow:0 4px 14px #2563eb66;transform:translateY(-1px)}.dialog-save-btn:active{transform:translateY(0);box-shadow:0 2px 8px #2563eb40}\n"], dependencies: [{ kind: "directive", type: i1$2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: DynamicForm, selector: "osl-dynamic-form", inputs: ["elements", "model", "skeletonLoading", "skeletonTheme"], outputs: ["modelChange"] }, { kind: "component", type: OslButton, selector: "osl-button", inputs: ["label", "icon", "variant", "size", "disabled", "loading", "type", "fullWidth"], outputs: ["clickEv"] }, { kind: "component", type: OslSearchbar, selector: "osl-searchbar", inputs: ["label"], outputs: ["onSearch"] }, { kind: "component", type: OslGrid, selector: "osl-grid", inputs: ["columns", "datasource", "isPaginated", "pageSize", "autoMode", "totalRecords", "tableHeight", "loading", "isSelectable", "moreMenuActions", "canEdit", "canDelete", "highlightedRow", "primaryKey"], outputs: ["datasourceChange", "pageChange", "pageSizeChange", "sortChange", "editClick", "deleteClick", "onRowClick"] }] });
|
|
3077
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: OslSetup, isStandalone: false, selector: "osl-setup", inputs: { title: "title", columns: "columns", datasource: "datasource", isPaginated: "isPaginated", pageSize: "pageSize", autoMode: "autoMode", tableHeight: "tableHeight", totalRecords: "totalRecords", loading: "loading", dialogWidth: "dialogWidth", formElements: "formElements", beforeDisplay: "beforeDisplay", onAddEditFn: "onAddEditFn", isLister: "isLister", canAdd: "canAdd", canEdit: "canEdit", canDelete: "canDelete", moreMenuActions: "moreMenuActions", customFormFooter: "customFormFooter", customHeaderTemp: "customHeaderTemp", partialCustomHeaderTemp: "partialCustomHeaderTemp", stateKey: "stateKey", primaryKey: "primaryKey", onSave: "onSave", cardPageSize: "cardPageSize", cardTemplate: "cardTemplate" }, outputs: { onSearch: "onSearch", onAdd: "onAdd", onEdit: "onEdit", onDelete: "onDelete", pageChange: "pageChange", pageSizeChange: "pageSizeChange", sortChange: "sortChange", onRowClick: "onRowClick", onStateRestored: "onStateRestored" }, host: { listeners: { "document:click": "onDocumentClick()" } }, viewQueries: [{ propertyName: "formBodyTpl", first: true, predicate: ["formBodyTpl"], descendants: true }, { propertyName: "formFooterTpl", first: true, predicate: ["formFooterTpl"], descendants: true }, { propertyName: "customFooterWrapperTpl", first: true, predicate: ["customFooterWrapperTpl"], descendants: true }, { propertyName: "searchbar", first: true, predicate: ["searchbar"], descendants: true }, { propertyName: "gridRef", first: true, predicate: ["gridRef"], descendants: true }, { propertyName: "cardContainerRef", first: true, predicate: ["cardContainerRef"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"p-2\">\n\n <!-- \u2500\u2500 Header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"osl-setup-header\">\n <h5 class=\"mb-0\">{{ title }}</h5>\n <div class=\"d-flex align-items-center gap-2\">\n <osl-searchbar #searchbar class=\"mx-2\" (onSearch)=\"onSearchSetup($event)\"></osl-searchbar>\n\n <!-- View Toggle -->\n <div class=\"osl-view-toggle\">\n <button class=\"osl-view-toggle-btn\" [class.osl-view-toggle-btn--active]=\"viewMode === 'table'\"\n (click)=\"toggleView('table')\" title=\"Table view\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\"/>\n <line x1=\"3\" y1=\"9\" x2=\"21\" y2=\"9\"/>\n <line x1=\"3\" y1=\"15\" x2=\"21\" y2=\"15\"/>\n <line x1=\"9\" y1=\"9\" x2=\"9\" y2=\"21\"/>\n </svg>\n </button>\n <button class=\"osl-view-toggle-btn\" [class.osl-view-toggle-btn--active]=\"viewMode === 'card'\"\n (click)=\"toggleView('card')\" title=\"Card view\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <rect x=\"3\" y=\"3\" width=\"7\" height=\"7\" rx=\"1.5\"/>\n <rect x=\"14\" y=\"3\" width=\"7\" height=\"7\" rx=\"1.5\"/>\n <rect x=\"3\" y=\"14\" width=\"7\" height=\"7\" rx=\"1.5\"/>\n <rect x=\"14\" y=\"14\" width=\"7\" height=\"7\" rx=\"1.5\"/>\n </svg>\n </button>\n </div>\n\n @if (!isLister && canAdd) {\n <osl-button variant=\"secondary\" size=\"sm\" [label]=\"'Add ' + title\" (clickEv)=\"openAddDialog()\"></osl-button>\n }\n </div>\n </div>\n\n <!-- \u2500\u2500 Table View \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n @if (viewMode === 'table') {\n <div class=\"osl-setup-body my-2\">\n <osl-grid\n #gridRef\n [columns]=\"columnsWithActions\"\n [(datasource)]=\"datasource\"\n [isPaginated]=\"isPaginated\"\n [pageSize]=\"pageSize\"\n [autoMode]=\"autoMode\"\n [tableHeight]=\"tableHeight\"\n [totalRecords]=\"totalRecords\"\n [loading]=\"loading\"\n [moreMenuActions]=\"moreMenuActions\"\n [canEdit]=\"canEdit\"\n [canDelete]=\"canDelete\"\n [highlightedRow]=\"restoredRow\"\n [primaryKey]=\"primaryKey\"\n (editClick)=\"openEditDialog($event)\"\n (deleteClick)=\"onDeleteClick($event)\"\n (pageChange)=\"onPageChange(pageChange, $event)\"\n (pageSizeChange)=\"onPageChange(pageSizeChange, $event)\"\n (sortChange)=\"sortChange.emit($event)\"\n [isSelectable]=\"isLister\"\n (onRowClick)=\"onRowClick.emit($event)\"\n />\n </div>\n }\n\n <!-- \u2500\u2500 Card View \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n @if (viewMode === 'card') {\n <div #cardContainerRef class=\"osl-card-container my-2\" [style.height]=\"tableHeight\" (scroll)=\"onCardScroll($event)\">\n\n <!-- Skeleton cards on initial load -->\n @if (loading && cardDatasource.length === 0) {\n <div class=\"osl-card-grid\">\n @for (sk of skeletonCardRows; track $index) {\n <div class=\"osl-card osl-card--skeleton\">\n <div class=\"osl-card-inner\">\n <div class=\"osl-card-header\">\n <div class=\"osl-card-avatar osl-card-avatar--skeleton\"></div>\n <div style=\"flex:1\">\n <div class=\"osl-sk-line osl-sk-line--title\"></div>\n </div>\n </div>\n <div class=\"osl-card-divider\"></div>\n <div class=\"osl-card-body\">\n <div class=\"osl-card-field\"><div class=\"osl-sk-line osl-sk-line--label\"></div><div class=\"osl-sk-line\"></div></div>\n <div class=\"osl-card-field\"><div class=\"osl-sk-line osl-sk-line--label\"></div><div class=\"osl-sk-line osl-sk-line--short\"></div></div>\n <div class=\"osl-card-field\"><div class=\"osl-sk-line osl-sk-line--label\"></div><div class=\"osl-sk-line\"></div></div>\n </div>\n </div>\n </div>\n }\n </div>\n }\n\n <!-- Empty state -->\n @else if (cardDatasource.length === 0 && !loading) {\n <div class=\"osl-card-empty\">\n <svg class=\"osl-card-empty-svg\" viewBox=\"0 0 180 160\" fill=\"none\">\n <ellipse cx=\"90\" cy=\"140\" rx=\"60\" ry=\"8\" fill=\"#f3f4f6\"/>\n <rect x=\"30\" y=\"30\" width=\"120\" height=\"96\" rx=\"10\" fill=\"#f9fafb\" stroke=\"#e5e7eb\" stroke-width=\"2\"/>\n <rect x=\"44\" y=\"48\" width=\"92\" height=\"10\" rx=\"5\" fill=\"#e5e7eb\"/>\n <rect x=\"44\" y=\"66\" width=\"72\" height=\"8\" rx=\"4\" fill=\"#f3f4f6\"/>\n <rect x=\"44\" y=\"82\" width=\"84\" height=\"8\" rx=\"4\" fill=\"#f3f4f6\"/>\n <rect x=\"44\" y=\"98\" width=\"56\" height=\"8\" rx=\"4\" fill=\"#f3f4f6\"/>\n <circle cx=\"140\" cy=\"108\" r=\"26\" fill=\"#fff\" stroke=\"#e5e7eb\" stroke-width=\"2\"/>\n <line x1=\"133\" y1=\"101\" x2=\"147\" y2=\"115\" stroke=\"#d1d5db\" stroke-width=\"2.5\" stroke-linecap=\"round\"/>\n <line x1=\"147\" y1=\"101\" x2=\"133\" y2=\"115\" stroke=\"#d1d5db\" stroke-width=\"2.5\" stroke-linecap=\"round\"/>\n </svg>\n <p class=\"osl-card-empty-title\">No records found</p>\n <p class=\"osl-card-empty-desc\">Try adjusting your search or filter criteria</p>\n </div>\n }\n\n <!-- Card grid -->\n @else {\n <div class=\"osl-card-grid\">\n\n @if (cardTemplate) {\n @for (row of cardDatasource; track row[primaryKey]; let i = $index) {\n <ng-container *ngTemplateOutlet=\"cardTemplate; context: { $implicit: row, index: i }\"></ng-container>\n }\n } @else {\n @for (row of cardDatasource; track row[primaryKey]; let i = $index) {\n <div class=\"osl-card\"\n [class.osl-card--highlighted]=\"isHighlightedCard(row)\"\n [class.osl-card--selectable]=\"isLister\"\n (click)=\"isLister ? onRowClick.emit(row) : null\">\n\n <div class=\"osl-card-inner\">\n\n <!-- Card header -->\n <div class=\"osl-card-header\">\n <!-- Avatar circle -->\n @if (cardTitleColumn) {\n <div class=\"osl-card-avatar\">{{ getCardInitial(row) }}</div>\n }\n\n <!-- Title -->\n <div class=\"osl-card-title-wrap\">\n <span class=\"osl-card-title\">\n @if (cardTitleColumn) {\n @switch (cardTitleColumn.displayType) {\n @case ('date') { {{ row[cardTitleColumn.key] | date }} }\n @case ('datetime') { {{ row[cardTitleColumn.key] | date:'medium' }} }\n @case ('time') { {{ row[cardTitleColumn.key] | date:'shortTime' }} }\n @default { {{ getCellValue(row, cardTitleColumn) }} }\n }\n }\n </span>\n </div>\n\n <!-- Action buttons -->\n @if (!isLister && ((hasForm && (canEdit || canDelete)) || (moreMenuActions.length > 0 && hasVisibleActions(row)))) {\n <div class=\"osl-card-actions\">\n\n <!-- More-actions trigger (menu rendered at root to avoid transform containment) -->\n @if (moreMenuActions.length > 0 && hasVisibleActions(row)) {\n <button class=\"osl-card-action-btn osl-card-action-btn--more\"\n (click)=\"toggleCardMenu(i, $event)\" title=\"More actions\">\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <circle cx=\"12\" cy=\"5\" r=\"2.2\"/>\n <circle cx=\"12\" cy=\"12\" r=\"2.2\"/>\n <circle cx=\"12\" cy=\"19\" r=\"2.2\"/>\n </svg>\n </button>\n }\n\n <!-- Edit -->\n @if (hasForm && canEdit) {\n <button class=\"osl-card-action-btn osl-card-action-btn--edit\"\n (click)=\"$event.stopPropagation(); openEditDialog(row)\" title=\"Edit\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\"/>\n <path d=\"M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z\"/>\n </svg>\n </button>\n }\n\n <!-- Delete -->\n @if (hasForm && canDelete) {\n <button class=\"osl-card-action-btn osl-card-action-btn--delete\"\n (click)=\"$event.stopPropagation(); onDeleteClick(row)\" title=\"Delete\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <polyline points=\"3 6 5 6 21 6\"/>\n <path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\"/>\n </svg>\n </button>\n }\n </div>\n }\n </div>\n\n <!-- Divider -->\n <div class=\"osl-card-divider\"></div>\n\n <!-- Card body: remaining fields -->\n <div class=\"osl-card-body\">\n @for (col of cardBodyColumns; track col.key) {\n <div class=\"osl-card-field\">\n <span class=\"osl-card-label\">{{ col.label }}</span>\n <span class=\"osl-card-value\" [class.link]=\"col.displayType === 'link'\" (click)=\"col.click ? col.click(row, col) : null\">\n @switch (col.displayType) {\n @case ('date') { {{ row[col.key] | date }} }\n @case ('datetime') { {{ row[col.key] | date:'medium' }} }\n @case ('time') { {{ row[col.key] | date:'shortTime' }} }\n @default { {{ getCellValue(row, col) }} }\n }\n </span>\n </div>\n }\n </div>\n\n </div>\n </div>\n }\n }\n </div>\n\n <!-- Infinite scroll bottom loader -->\n @if (loading) {\n <div class=\"osl-card-loader\">\n <div class=\"osl-card-loader-track\">\n <div class=\"osl-card-loader-bar\"></div>\n </div>\n <span class=\"osl-card-loader-text\">Loading more\u2026</span>\n </div>\n }\n\n <!-- All loaded footer -->\n @if (allCardsLoaded && !loading && cardDatasource.length > 0) {\n <div class=\"osl-card-all-loaded\">\n <span class=\"osl-card-all-loaded-line\"></span>\n <span class=\"osl-card-all-loaded-text\">All {{ totalRecords || cardDatasource.length }} records loaded</span>\n <span class=\"osl-card-all-loaded-line\"></span>\n </div>\n }\n }\n </div>\n }\n\n</div>\n\n<!-- Dialog: Form Body -->\n<ng-template #formBodyTpl>\n <osl-dynamic-form\n [skeletonLoading]=\"formLoading\"\n [elements]=\"formElements\"\n [(model)]=\"dialogModel\"\n ></osl-dynamic-form>\n</ng-template>\n\n<!-- Dialog: Form Footer -->\n<ng-template #formFooterTpl>\n <div class=\"osl-setup-dialog-footer\">\n <osl-button [loading]=\"saveLoading\" variant=\"secondary\" label=\"Save\" (click)=\"saveDialog()\"></osl-button>\n </div>\n</ng-template>\n\n<ng-template #customFooterWrapperTpl let-data>\n <ng-container *ngTemplateOutlet=\"customFormFooter!; context: { $implicit: { dialogModel: dialogModel, dialogMode: dialogMode, dialogRef: data.dialogRef } }\"></ng-container>\n</ng-template>\n\n<!-- Floating card more-actions menu \u2014 rendered outside card DOM to avoid transform containment -->\n@if (viewMode === 'card' && cardOpenMenuIndex !== null && moreMenuActions.length > 0) {\n <div class=\"osl-card-menu\"\n [style.top.px]=\"cardMenuPosition.top\"\n [style.left.px]=\"cardMenuPosition.left\"\n (click)=\"$event.stopPropagation()\">\n <div class=\"osl-card-menu-header\">Actions</div>\n @for (action of moreMenuActions; track $index) {\n @if (!action.hideIf || !action.hideIf(cardDatasource[cardOpenMenuIndex])) {\n <button class=\"osl-card-menu-item\"\n (click)=\"action.click(cardDatasource[cardOpenMenuIndex]); cardOpenMenuIndex = null\">\n <span class=\"osl-card-menu-dot\"></span>\n {{ action.labelIf ? action.labelIf(cardDatasource[cardOpenMenuIndex]) : action.label }}\n </button>\n }\n }\n </div>\n}\n", styles: [".osl-setup-header{display:flex;align-items:center;justify-content:space-between}.osl-setup-dialog-footer{display:flex;align-items:center;justify-content:flex-end;gap:10px;width:100%}.dialog-cancel-btn{display:flex;align-items:center;gap:6px;height:38px;font-size:13px;font-weight:500;border-color:var(--osl-border-color, #d1d5db);color:var(--osl-secondary, #6b7280);border-radius:var(--osl-border-radius, 4px);padding:0 16px;transition:all .2s ease}.dialog-cancel-btn mat-icon{font-size:17px;width:17px;height:17px}.dialog-cancel-btn:hover{border-color:#9ca3af;background:#f9fafb;color:#374151}.dialog-save-btn{display:flex;align-items:center;gap:6px;height:38px;font-size:13px;font-weight:500;background:linear-gradient(135deg,var(--osl-primary, #2563eb),#3b82f6);color:#fff;border-radius:var(--osl-border-radius, 4px);padding:0 18px;transition:all .2s ease;box-shadow:0 2px 8px #2563eb40}.dialog-save-btn mat-icon{font-size:17px;width:17px;height:17px}.dialog-save-btn:hover{background:linear-gradient(135deg,var(--osl-primary-hover, #1d4ed8),#2563eb);box-shadow:0 4px 14px #2563eb66;transform:translateY(-1px)}.dialog-save-btn:active{transform:translateY(0);box-shadow:0 2px 8px #2563eb40}.osl-view-toggle{display:flex;border:1.5px solid var(--osl-border-color, #e5e7eb);border-radius:8px;overflow:hidden;flex-shrink:0;background:#fff}.osl-view-toggle-btn{display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;border:none;background:transparent;cursor:pointer;color:#9ca3af;transition:background .15s,color .15s;padding:0}.osl-view-toggle-btn svg{width:16px;height:16px;transition:stroke .15s}.osl-view-toggle-btn:first-child{border-right:1.5px solid var(--osl-border-color, #e5e7eb)}.osl-view-toggle-btn--active{background:var(--osl-primary, #6366f1);color:#fff}.osl-view-toggle-btn--active svg{stroke:#fff}.osl-view-toggle-btn:not(.osl-view-toggle-btn--active):hover{background:#f3f4f6;color:#374151}.osl-card-container{overflow-y:auto;overflow-x:hidden;border-radius:12px;padding:4px 2px 16px;box-sizing:border-box}.osl-card-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:16px;padding:4px}@keyframes osl-card-enter{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.osl-card-grid .osl-card:nth-child(1){animation-delay:0s}.osl-card-grid .osl-card:nth-child(2){animation-delay:.04s}.osl-card-grid .osl-card:nth-child(3){animation-delay:.08s}.osl-card-grid .osl-card:nth-child(4){animation-delay:.12s}.osl-card-grid .osl-card:nth-child(5){animation-delay:.16s}.osl-card-grid .osl-card:nth-child(6){animation-delay:.2s}.osl-card-grid .osl-card:nth-child(7){animation-delay:.24s}.osl-card-grid .osl-card:nth-child(8){animation-delay:.28s}.osl-card-grid .osl-card:nth-child(9){animation-delay:.32s}.osl-card-grid .osl-card:nth-child(10){animation-delay:.36s}.osl-card-grid .osl-card:nth-child(11){animation-delay:.4s}.osl-card-grid .osl-card:nth-child(12){animation-delay:.44s}.osl-card{position:relative;background:#fff;border-radius:14px;border:1px solid #eaecf0;box-shadow:0 1px 4px #1018280f,0 1px 2px #1018280a;overflow:hidden;transition:transform .22s cubic-bezier(.34,1.56,.64,1),box-shadow .22s ease;animation:osl-card-enter .28s ease both}.osl-card:nth-child(6n+1){--card-accent: #6366f1;--card-accent-bg: #eef2ff}.osl-card:nth-child(6n+2){--card-accent: #0ea5e9;--card-accent-bg: #f0f9ff}.osl-card:nth-child(6n+3){--card-accent: #10b981;--card-accent-bg: #ecfdf5}.osl-card:nth-child(6n+4){--card-accent: #f59e0b;--card-accent-bg: #fffbeb}.osl-card:nth-child(6n+5){--card-accent: #f43f5e;--card-accent-bg: #fff1f2}.osl-card:nth-child(6n){--card-accent: #8b5cf6;--card-accent-bg: #faf5ff}.osl-card:before{content:\"\";position:absolute;top:0;left:0;bottom:0;width:4px;background:var(--card-accent, var(--osl-primary, #6366f1))}.osl-card:hover{transform:translateY(-4px);box-shadow:0 12px 32px #1018281a,0 4px 12px #1018280f;border-color:#d0d5dd}.osl-card--highlighted{outline:2px solid var(--osl-primary, #6366f1);outline-offset:2px;animation:osl-card-enter .28s ease both,osl-card-highlight-pulse 2.5s ease-out .3s both}.osl-card--selectable{cursor:pointer}.osl-card--skeleton{pointer-events:none;animation:osl-card-enter .28s ease both}.osl-card--skeleton:hover{transform:none;box-shadow:0 1px 4px #1018280f}@keyframes osl-card-highlight-pulse{0%{box-shadow:0 0 0 4px #6366f14d}to{box-shadow:none}}.osl-card-inner{padding:16px 16px 16px 20px;display:flex;flex-direction:column;height:100%}.osl-card-header{display:flex;align-items:center;gap:12px;margin-bottom:0}.osl-card-avatar{width:40px;height:40px;border-radius:10px;background:var(--card-accent, var(--osl-primary, #6366f1));color:#fff;font-size:16px;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0;letter-spacing:0;box-shadow:0 4px 10px #00000026}.osl-card-avatar--skeleton{background:#e5e7eb;box-shadow:none;animation:osl-sk-pulse 1.4s ease-in-out infinite}.osl-card-title-wrap{flex:1;min-width:0}.osl-card-title{display:block;font-weight:700;font-size:14px;color:#101828;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:1.4}.osl-card-actions{display:flex;align-items:center;gap:6px;flex-shrink:0}.osl-card-action-btn{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;border-radius:8px;border:1.5px solid #e4e7ec;background:#fff;cursor:pointer;transition:background .15s,border-color .15s,transform .15s,box-shadow .15s;padding:0}.osl-card-action-btn svg{width:14px;height:14px;transition:stroke .15s,fill .15s}.osl-card-action-btn--more svg{fill:#9ca3af;stroke:none}.osl-card-action-btn--more:hover{background:var(--card-accent-bg, #eef2ff);border-color:var(--card-accent, var(--osl-primary, #6366f1));box-shadow:0 2px 6px #00000014;transform:scale(1.05)}.osl-card-action-btn--more:hover svg{fill:var(--card-accent, var(--osl-primary, #6366f1))}.osl-card-action-btn--edit svg{stroke:#6b7280}.osl-card-action-btn--edit:hover{background:var(--card-accent-bg, #eef2ff);border-color:var(--card-accent, var(--osl-primary, #6366f1));box-shadow:0 2px 6px #00000014;transform:scale(1.05)}.osl-card-action-btn--edit:hover svg{stroke:var(--card-accent, var(--osl-primary, #6366f1))}.osl-card-action-btn--delete svg{stroke:#9ca3af}.osl-card-action-btn--delete:hover{background:#fff1f2;border-color:#f43f5e;box-shadow:0 2px 6px #f43f5e26;transform:scale(1.05)}.osl-card-action-btn--delete:hover svg{stroke:#f43f5e}.osl-card-divider{height:1px;background:#f2f4f7;margin:14px 0}.osl-card-body{display:flex;flex-direction:column;gap:10px;flex:1}.osl-card-field{display:grid;grid-template-columns:100px 1fr;gap:6px;align-items:baseline}.osl-card-label{font-size:10px;font-weight:600;color:#9ca3af;text-transform:uppercase;letter-spacing:.06em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.osl-card-value{font-size:13px;font-weight:500;color:#374151;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.osl-card-value.link{text-decoration:underline;color:#2563eb;cursor:pointer}.osl-card-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:320px;gap:12px;padding:40px 20px}.osl-card-empty-svg{width:180px;height:auto;opacity:.85}.osl-card-empty-title{font-size:16px;font-weight:600;color:#374151;margin:4px 0 0;text-align:center}.osl-card-empty-desc{font-size:13px;color:#9ca3af;margin:0;text-align:center}.osl-card-loader{display:flex;flex-direction:column;align-items:center;gap:10px;padding:28px 20px 16px}.osl-card-loader-track{width:160px;height:3px;background:#f3f4f6;border-radius:99px;overflow:hidden}.osl-card-loader-bar{height:100%;width:40%;background:linear-gradient(90deg,transparent,var(--osl-primary, #6366f1),transparent);border-radius:99px;animation:osl-loader-sweep 1.2s ease-in-out infinite}@keyframes osl-loader-sweep{0%{transform:translate(-200%)}to{transform:translate(500%)}}.osl-card-loader-text{font-size:12px;color:#9ca3af;font-weight:500}.osl-card-all-loaded{display:flex;align-items:center;gap:12px;padding:20px 16px 8px;justify-content:center}.osl-card-all-loaded-line{flex:1;max-width:80px;height:1px;background:#e5e7eb}.osl-card-all-loaded-text{font-size:11px;color:#d1d5db;font-weight:600;text-transform:uppercase;letter-spacing:.06em;white-space:nowrap}@keyframes osl-sk-pulse{0%,to{opacity:1}50%{opacity:.4}}.osl-sk-line{height:12px;background:#e9eaec;border-radius:6px;animation:osl-sk-pulse 1.4s ease-in-out infinite;width:80%}.osl-sk-line--title{height:14px;width:65%}.osl-sk-line--label{width:40%;height:10px}.osl-sk-line--short{width:50%}.osl-card-menu{position:fixed;z-index:9999;min-width:196px;background:#fff;border:1px solid #eaecf0;border-radius:12px;box-shadow:0 12px 32px #10182824,0 4px 12px #1018280f;overflow:hidden;animation:osl-menu-pop .16s cubic-bezier(.16,1,.3,1)}@keyframes osl-menu-pop{0%{opacity:0;transform:translateY(-8px) scale(.96)}to{opacity:1;transform:translateY(0) scale(1)}}.osl-card-menu-header{padding:10px 14px 7px;font-size:10px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:#9ca3af;border-bottom:1px solid #f2f4f7;-webkit-user-select:none;user-select:none}.osl-card-menu-item{display:flex;align-items:center;gap:10px;width:100%;padding:10px 14px;background:transparent;border:none;border-left:3px solid transparent;border-bottom:1px solid #f9fafb;text-align:left;font-size:13px;font-weight:500;font-family:inherit;color:#374151;cursor:pointer;white-space:nowrap;transition:background .12s,color .12s,border-left-color .12s}.osl-card-menu-item:last-child{border-bottom:none}.osl-card-menu-item:hover{background:var(--card-accent-bg, #f5f3ff);color:var(--card-accent, var(--osl-primary, #6366f1));border-left-color:var(--card-accent, var(--osl-primary, #6366f1))}.osl-card-menu-item:hover .osl-card-menu-dot{background:var(--card-accent, var(--osl-primary, #6366f1));box-shadow:0 0 0 3px #6366f129}.osl-card-menu-dot{flex-shrink:0;width:6px;height:6px;border-radius:50%;background:#d1d5db;transition:background .12s,box-shadow .12s}\n"], dependencies: [{ kind: "directive", type: i1$2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: DynamicForm, selector: "osl-dynamic-form", inputs: ["elements", "model", "skeletonLoading", "skeletonTheme"], outputs: ["modelChange"] }, { kind: "component", type: OslButton, selector: "osl-button", inputs: ["label", "icon", "variant", "size", "disabled", "loading", "type", "fullWidth"], outputs: ["clickEv"] }, { kind: "component", type: OslSearchbar, selector: "osl-searchbar", inputs: ["label"], outputs: ["onSearch"] }, { kind: "component", type: OslGrid, selector: "osl-grid", inputs: ["columns", "datasource", "isPaginated", "pageSize", "autoMode", "totalRecords", "tableHeight", "loading", "isSelectable", "moreMenuActions", "canEdit", "canDelete", "highlightedRow", "primaryKey"], outputs: ["datasourceChange", "pageChange", "pageSizeChange", "sortChange", "editClick", "deleteClick", "onRowClick"] }, { kind: "pipe", type: i1$2.DatePipe, name: "date" }] });
|
|
2822
3078
|
}
|
|
2823
3079
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: OslSetup, decorators: [{
|
|
2824
3080
|
type: Component,
|
|
2825
|
-
args: [{ selector: 'osl-setup', standalone: false, template: "<div class=\"p-2\">\r\n\r\n <!-- Header -->\r\n <div class=\"osl-setup-header\">\r\n <h5 class=\"mb-0\">{{ title }}</h5>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <osl-searchbar #searchbar class=\"mx-2\" (onSearch)=\"onSearchSetup($event)\"></osl-searchbar>\r\n @if(!isLister && canAdd){\r\n <osl-button\r\n variant=\"secondary\"\r\n size=\"sm\"\r\n [label]=\"'Add ' + title\"\r\n (clickEv)=\"openAddDialog()\"\r\n ></osl-button>\r\n\r\n }\r\n </div>\r\n </div>\r\n\r\n <!-- Grid -->\r\n <div class=\"osl-setup-body my-2\">\r\n <osl-grid\r\n #gridRef\r\n [columns]=\"columnsWithActions\"\r\n [(datasource)]=\"datasource\"\r\n [isPaginated]=\"isPaginated\"\r\n [pageSize]=\"pageSize\"\r\n [autoMode]=\"autoMode\"\r\n [tableHeight]=\"tableHeight\"\r\n [totalRecords]=\"totalRecords\"\r\n [loading]=\"loading\"\r\n [moreMenuActions]=\"moreMenuActions\"\r\n [canEdit]=\"canEdit\"\r\n [canDelete]=\"canDelete\"\r\n [highlightedRow]=\"restoredRow\"\r\n [primaryKey]=\"primaryKey\"\r\n (editClick)=\"openEditDialog($event)\"\r\n (deleteClick)=\"onDeleteClick($event)\"\r\n (pageChange)=\"onPageChange(pageChange,$event)\"\r\n (pageSizeChange)=\"onPageChange(pageSizeChange,$event)\"\r\n (sortChange)=\"sortChange.emit($event)\"\r\n [isSelectable]=\"isLister\";\r\n (onRowClick)=\"onRowClick.emit($event)\"\r\n />\r\n </div>\r\n\r\n</div>\r\n\r\n<!-- Dialog: Form Body -->\r\n<ng-template #formBodyTpl>\r\n <osl-dynamic-form\r\n [skeletonLoading]=\"formLoading\"\r\n [elements]=\"formElements\"\r\n [(model)]=\"dialogModel\"\r\n ></osl-dynamic-form>\r\n</ng-template>\r\n\r\n<!-- Dialog: Form Footer -->\r\n<ng-template #formFooterTpl>\r\n <div class=\"osl-setup-dialog-footer\">\r\n\r\n\r\n <osl-button [loading]=\"saveLoading\" variant=\"secondary\" label=\"Save\" (click)=\"saveDialog()\"></osl-button>\r\n\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Wrapper that bridges DialogWrapper's implicit context to the custom footer template -->\r\n<ng-template #customFooterWrapperTpl let-data>\r\n <ng-container *ngTemplateOutlet=\"customFormFooter!; context: { $implicit: { dialogModel: dialogModel, dialogMode: dialogMode, dialogRef: data.dialogRef } }\"></ng-container>\r\n</ng-template>\r\n", styles: [".osl-setup-header{display:flex;align-items:center;justify-content:space-between}.osl-setup-dialog-footer{display:flex;align-items:center;justify-content:flex-end;gap:10px;width:100%}.dialog-cancel-btn{display:flex;align-items:center;gap:6px;height:38px;font-size:13px;font-weight:500;border-color:var(--osl-border-color, #d1d5db);color:var(--osl-secondary, #6b7280);border-radius:var(--osl-border-radius, 4px);padding:0 16px;transition:all .2s ease}.dialog-cancel-btn mat-icon{font-size:17px;width:17px;height:17px}.dialog-cancel-btn:hover{border-color:#9ca3af;background:#f9fafb;color:#374151}.dialog-save-btn{display:flex;align-items:center;gap:6px;height:38px;font-size:13px;font-weight:500;background:linear-gradient(135deg,var(--osl-primary, #2563eb),#3b82f6);color:#fff;border-radius:var(--osl-border-radius, 4px);padding:0 18px;transition:all .2s ease;box-shadow:0 2px 8px #2563eb40}.dialog-save-btn mat-icon{font-size:17px;width:17px;height:17px}.dialog-save-btn:hover{background:linear-gradient(135deg,var(--osl-primary-hover, #1d4ed8),#2563eb);box-shadow:0 4px 14px #2563eb66;transform:translateY(-1px)}.dialog-save-btn:active{transform:translateY(0);box-shadow:0 2px 8px #2563eb40}\n"] }]
|
|
3081
|
+
args: [{ selector: 'osl-setup', standalone: false, template: "<div class=\"p-2\">\n\n <!-- \u2500\u2500 Header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"osl-setup-header\">\n <h5 class=\"mb-0\">{{ title }}</h5>\n <div class=\"d-flex align-items-center gap-2\">\n <osl-searchbar #searchbar class=\"mx-2\" (onSearch)=\"onSearchSetup($event)\"></osl-searchbar>\n\n <!-- View Toggle -->\n <div class=\"osl-view-toggle\">\n <button class=\"osl-view-toggle-btn\" [class.osl-view-toggle-btn--active]=\"viewMode === 'table'\"\n (click)=\"toggleView('table')\" title=\"Table view\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\"/>\n <line x1=\"3\" y1=\"9\" x2=\"21\" y2=\"9\"/>\n <line x1=\"3\" y1=\"15\" x2=\"21\" y2=\"15\"/>\n <line x1=\"9\" y1=\"9\" x2=\"9\" y2=\"21\"/>\n </svg>\n </button>\n <button class=\"osl-view-toggle-btn\" [class.osl-view-toggle-btn--active]=\"viewMode === 'card'\"\n (click)=\"toggleView('card')\" title=\"Card view\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <rect x=\"3\" y=\"3\" width=\"7\" height=\"7\" rx=\"1.5\"/>\n <rect x=\"14\" y=\"3\" width=\"7\" height=\"7\" rx=\"1.5\"/>\n <rect x=\"3\" y=\"14\" width=\"7\" height=\"7\" rx=\"1.5\"/>\n <rect x=\"14\" y=\"14\" width=\"7\" height=\"7\" rx=\"1.5\"/>\n </svg>\n </button>\n </div>\n\n @if (!isLister && canAdd) {\n <osl-button variant=\"secondary\" size=\"sm\" [label]=\"'Add ' + title\" (clickEv)=\"openAddDialog()\"></osl-button>\n }\n </div>\n </div>\n\n <!-- \u2500\u2500 Table View \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n @if (viewMode === 'table') {\n <div class=\"osl-setup-body my-2\">\n <osl-grid\n #gridRef\n [columns]=\"columnsWithActions\"\n [(datasource)]=\"datasource\"\n [isPaginated]=\"isPaginated\"\n [pageSize]=\"pageSize\"\n [autoMode]=\"autoMode\"\n [tableHeight]=\"tableHeight\"\n [totalRecords]=\"totalRecords\"\n [loading]=\"loading\"\n [moreMenuActions]=\"moreMenuActions\"\n [canEdit]=\"canEdit\"\n [canDelete]=\"canDelete\"\n [highlightedRow]=\"restoredRow\"\n [primaryKey]=\"primaryKey\"\n (editClick)=\"openEditDialog($event)\"\n (deleteClick)=\"onDeleteClick($event)\"\n (pageChange)=\"onPageChange(pageChange, $event)\"\n (pageSizeChange)=\"onPageChange(pageSizeChange, $event)\"\n (sortChange)=\"sortChange.emit($event)\"\n [isSelectable]=\"isLister\"\n (onRowClick)=\"onRowClick.emit($event)\"\n />\n </div>\n }\n\n <!-- \u2500\u2500 Card View \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n @if (viewMode === 'card') {\n <div #cardContainerRef class=\"osl-card-container my-2\" [style.height]=\"tableHeight\" (scroll)=\"onCardScroll($event)\">\n\n <!-- Skeleton cards on initial load -->\n @if (loading && cardDatasource.length === 0) {\n <div class=\"osl-card-grid\">\n @for (sk of skeletonCardRows; track $index) {\n <div class=\"osl-card osl-card--skeleton\">\n <div class=\"osl-card-inner\">\n <div class=\"osl-card-header\">\n <div class=\"osl-card-avatar osl-card-avatar--skeleton\"></div>\n <div style=\"flex:1\">\n <div class=\"osl-sk-line osl-sk-line--title\"></div>\n </div>\n </div>\n <div class=\"osl-card-divider\"></div>\n <div class=\"osl-card-body\">\n <div class=\"osl-card-field\"><div class=\"osl-sk-line osl-sk-line--label\"></div><div class=\"osl-sk-line\"></div></div>\n <div class=\"osl-card-field\"><div class=\"osl-sk-line osl-sk-line--label\"></div><div class=\"osl-sk-line osl-sk-line--short\"></div></div>\n <div class=\"osl-card-field\"><div class=\"osl-sk-line osl-sk-line--label\"></div><div class=\"osl-sk-line\"></div></div>\n </div>\n </div>\n </div>\n }\n </div>\n }\n\n <!-- Empty state -->\n @else if (cardDatasource.length === 0 && !loading) {\n <div class=\"osl-card-empty\">\n <svg class=\"osl-card-empty-svg\" viewBox=\"0 0 180 160\" fill=\"none\">\n <ellipse cx=\"90\" cy=\"140\" rx=\"60\" ry=\"8\" fill=\"#f3f4f6\"/>\n <rect x=\"30\" y=\"30\" width=\"120\" height=\"96\" rx=\"10\" fill=\"#f9fafb\" stroke=\"#e5e7eb\" stroke-width=\"2\"/>\n <rect x=\"44\" y=\"48\" width=\"92\" height=\"10\" rx=\"5\" fill=\"#e5e7eb\"/>\n <rect x=\"44\" y=\"66\" width=\"72\" height=\"8\" rx=\"4\" fill=\"#f3f4f6\"/>\n <rect x=\"44\" y=\"82\" width=\"84\" height=\"8\" rx=\"4\" fill=\"#f3f4f6\"/>\n <rect x=\"44\" y=\"98\" width=\"56\" height=\"8\" rx=\"4\" fill=\"#f3f4f6\"/>\n <circle cx=\"140\" cy=\"108\" r=\"26\" fill=\"#fff\" stroke=\"#e5e7eb\" stroke-width=\"2\"/>\n <line x1=\"133\" y1=\"101\" x2=\"147\" y2=\"115\" stroke=\"#d1d5db\" stroke-width=\"2.5\" stroke-linecap=\"round\"/>\n <line x1=\"147\" y1=\"101\" x2=\"133\" y2=\"115\" stroke=\"#d1d5db\" stroke-width=\"2.5\" stroke-linecap=\"round\"/>\n </svg>\n <p class=\"osl-card-empty-title\">No records found</p>\n <p class=\"osl-card-empty-desc\">Try adjusting your search or filter criteria</p>\n </div>\n }\n\n <!-- Card grid -->\n @else {\n <div class=\"osl-card-grid\">\n\n @if (cardTemplate) {\n @for (row of cardDatasource; track row[primaryKey]; let i = $index) {\n <ng-container *ngTemplateOutlet=\"cardTemplate; context: { $implicit: row, index: i }\"></ng-container>\n }\n } @else {\n @for (row of cardDatasource; track row[primaryKey]; let i = $index) {\n <div class=\"osl-card\"\n [class.osl-card--highlighted]=\"isHighlightedCard(row)\"\n [class.osl-card--selectable]=\"isLister\"\n (click)=\"isLister ? onRowClick.emit(row) : null\">\n\n <div class=\"osl-card-inner\">\n\n <!-- Card header -->\n <div class=\"osl-card-header\">\n <!-- Avatar circle -->\n @if (cardTitleColumn) {\n <div class=\"osl-card-avatar\">{{ getCardInitial(row) }}</div>\n }\n\n <!-- Title -->\n <div class=\"osl-card-title-wrap\">\n <span class=\"osl-card-title\">\n @if (cardTitleColumn) {\n @switch (cardTitleColumn.displayType) {\n @case ('date') { {{ row[cardTitleColumn.key] | date }} }\n @case ('datetime') { {{ row[cardTitleColumn.key] | date:'medium' }} }\n @case ('time') { {{ row[cardTitleColumn.key] | date:'shortTime' }} }\n @default { {{ getCellValue(row, cardTitleColumn) }} }\n }\n }\n </span>\n </div>\n\n <!-- Action buttons -->\n @if (!isLister && ((hasForm && (canEdit || canDelete)) || (moreMenuActions.length > 0 && hasVisibleActions(row)))) {\n <div class=\"osl-card-actions\">\n\n <!-- More-actions trigger (menu rendered at root to avoid transform containment) -->\n @if (moreMenuActions.length > 0 && hasVisibleActions(row)) {\n <button class=\"osl-card-action-btn osl-card-action-btn--more\"\n (click)=\"toggleCardMenu(i, $event)\" title=\"More actions\">\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <circle cx=\"12\" cy=\"5\" r=\"2.2\"/>\n <circle cx=\"12\" cy=\"12\" r=\"2.2\"/>\n <circle cx=\"12\" cy=\"19\" r=\"2.2\"/>\n </svg>\n </button>\n }\n\n <!-- Edit -->\n @if (hasForm && canEdit) {\n <button class=\"osl-card-action-btn osl-card-action-btn--edit\"\n (click)=\"$event.stopPropagation(); openEditDialog(row)\" title=\"Edit\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\"/>\n <path d=\"M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z\"/>\n </svg>\n </button>\n }\n\n <!-- Delete -->\n @if (hasForm && canDelete) {\n <button class=\"osl-card-action-btn osl-card-action-btn--delete\"\n (click)=\"$event.stopPropagation(); onDeleteClick(row)\" title=\"Delete\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <polyline points=\"3 6 5 6 21 6\"/>\n <path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\"/>\n </svg>\n </button>\n }\n </div>\n }\n </div>\n\n <!-- Divider -->\n <div class=\"osl-card-divider\"></div>\n\n <!-- Card body: remaining fields -->\n <div class=\"osl-card-body\">\n @for (col of cardBodyColumns; track col.key) {\n <div class=\"osl-card-field\">\n <span class=\"osl-card-label\">{{ col.label }}</span>\n <span class=\"osl-card-value\" [class.link]=\"col.displayType === 'link'\" (click)=\"col.click ? col.click(row, col) : null\">\n @switch (col.displayType) {\n @case ('date') { {{ row[col.key] | date }} }\n @case ('datetime') { {{ row[col.key] | date:'medium' }} }\n @case ('time') { {{ row[col.key] | date:'shortTime' }} }\n @default { {{ getCellValue(row, col) }} }\n }\n </span>\n </div>\n }\n </div>\n\n </div>\n </div>\n }\n }\n </div>\n\n <!-- Infinite scroll bottom loader -->\n @if (loading) {\n <div class=\"osl-card-loader\">\n <div class=\"osl-card-loader-track\">\n <div class=\"osl-card-loader-bar\"></div>\n </div>\n <span class=\"osl-card-loader-text\">Loading more\u2026</span>\n </div>\n }\n\n <!-- All loaded footer -->\n @if (allCardsLoaded && !loading && cardDatasource.length > 0) {\n <div class=\"osl-card-all-loaded\">\n <span class=\"osl-card-all-loaded-line\"></span>\n <span class=\"osl-card-all-loaded-text\">All {{ totalRecords || cardDatasource.length }} records loaded</span>\n <span class=\"osl-card-all-loaded-line\"></span>\n </div>\n }\n }\n </div>\n }\n\n</div>\n\n<!-- Dialog: Form Body -->\n<ng-template #formBodyTpl>\n <osl-dynamic-form\n [skeletonLoading]=\"formLoading\"\n [elements]=\"formElements\"\n [(model)]=\"dialogModel\"\n ></osl-dynamic-form>\n</ng-template>\n\n<!-- Dialog: Form Footer -->\n<ng-template #formFooterTpl>\n <div class=\"osl-setup-dialog-footer\">\n <osl-button [loading]=\"saveLoading\" variant=\"secondary\" label=\"Save\" (click)=\"saveDialog()\"></osl-button>\n </div>\n</ng-template>\n\n<ng-template #customFooterWrapperTpl let-data>\n <ng-container *ngTemplateOutlet=\"customFormFooter!; context: { $implicit: { dialogModel: dialogModel, dialogMode: dialogMode, dialogRef: data.dialogRef } }\"></ng-container>\n</ng-template>\n\n<!-- Floating card more-actions menu \u2014 rendered outside card DOM to avoid transform containment -->\n@if (viewMode === 'card' && cardOpenMenuIndex !== null && moreMenuActions.length > 0) {\n <div class=\"osl-card-menu\"\n [style.top.px]=\"cardMenuPosition.top\"\n [style.left.px]=\"cardMenuPosition.left\"\n (click)=\"$event.stopPropagation()\">\n <div class=\"osl-card-menu-header\">Actions</div>\n @for (action of moreMenuActions; track $index) {\n @if (!action.hideIf || !action.hideIf(cardDatasource[cardOpenMenuIndex])) {\n <button class=\"osl-card-menu-item\"\n (click)=\"action.click(cardDatasource[cardOpenMenuIndex]); cardOpenMenuIndex = null\">\n <span class=\"osl-card-menu-dot\"></span>\n {{ action.labelIf ? action.labelIf(cardDatasource[cardOpenMenuIndex]) : action.label }}\n </button>\n }\n }\n </div>\n}\n", styles: [".osl-setup-header{display:flex;align-items:center;justify-content:space-between}.osl-setup-dialog-footer{display:flex;align-items:center;justify-content:flex-end;gap:10px;width:100%}.dialog-cancel-btn{display:flex;align-items:center;gap:6px;height:38px;font-size:13px;font-weight:500;border-color:var(--osl-border-color, #d1d5db);color:var(--osl-secondary, #6b7280);border-radius:var(--osl-border-radius, 4px);padding:0 16px;transition:all .2s ease}.dialog-cancel-btn mat-icon{font-size:17px;width:17px;height:17px}.dialog-cancel-btn:hover{border-color:#9ca3af;background:#f9fafb;color:#374151}.dialog-save-btn{display:flex;align-items:center;gap:6px;height:38px;font-size:13px;font-weight:500;background:linear-gradient(135deg,var(--osl-primary, #2563eb),#3b82f6);color:#fff;border-radius:var(--osl-border-radius, 4px);padding:0 18px;transition:all .2s ease;box-shadow:0 2px 8px #2563eb40}.dialog-save-btn mat-icon{font-size:17px;width:17px;height:17px}.dialog-save-btn:hover{background:linear-gradient(135deg,var(--osl-primary-hover, #1d4ed8),#2563eb);box-shadow:0 4px 14px #2563eb66;transform:translateY(-1px)}.dialog-save-btn:active{transform:translateY(0);box-shadow:0 2px 8px #2563eb40}.osl-view-toggle{display:flex;border:1.5px solid var(--osl-border-color, #e5e7eb);border-radius:8px;overflow:hidden;flex-shrink:0;background:#fff}.osl-view-toggle-btn{display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;border:none;background:transparent;cursor:pointer;color:#9ca3af;transition:background .15s,color .15s;padding:0}.osl-view-toggle-btn svg{width:16px;height:16px;transition:stroke .15s}.osl-view-toggle-btn:first-child{border-right:1.5px solid var(--osl-border-color, #e5e7eb)}.osl-view-toggle-btn--active{background:var(--osl-primary, #6366f1);color:#fff}.osl-view-toggle-btn--active svg{stroke:#fff}.osl-view-toggle-btn:not(.osl-view-toggle-btn--active):hover{background:#f3f4f6;color:#374151}.osl-card-container{overflow-y:auto;overflow-x:hidden;border-radius:12px;padding:4px 2px 16px;box-sizing:border-box}.osl-card-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:16px;padding:4px}@keyframes osl-card-enter{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.osl-card-grid .osl-card:nth-child(1){animation-delay:0s}.osl-card-grid .osl-card:nth-child(2){animation-delay:.04s}.osl-card-grid .osl-card:nth-child(3){animation-delay:.08s}.osl-card-grid .osl-card:nth-child(4){animation-delay:.12s}.osl-card-grid .osl-card:nth-child(5){animation-delay:.16s}.osl-card-grid .osl-card:nth-child(6){animation-delay:.2s}.osl-card-grid .osl-card:nth-child(7){animation-delay:.24s}.osl-card-grid .osl-card:nth-child(8){animation-delay:.28s}.osl-card-grid .osl-card:nth-child(9){animation-delay:.32s}.osl-card-grid .osl-card:nth-child(10){animation-delay:.36s}.osl-card-grid .osl-card:nth-child(11){animation-delay:.4s}.osl-card-grid .osl-card:nth-child(12){animation-delay:.44s}.osl-card{position:relative;background:#fff;border-radius:14px;border:1px solid #eaecf0;box-shadow:0 1px 4px #1018280f,0 1px 2px #1018280a;overflow:hidden;transition:transform .22s cubic-bezier(.34,1.56,.64,1),box-shadow .22s ease;animation:osl-card-enter .28s ease both}.osl-card:nth-child(6n+1){--card-accent: #6366f1;--card-accent-bg: #eef2ff}.osl-card:nth-child(6n+2){--card-accent: #0ea5e9;--card-accent-bg: #f0f9ff}.osl-card:nth-child(6n+3){--card-accent: #10b981;--card-accent-bg: #ecfdf5}.osl-card:nth-child(6n+4){--card-accent: #f59e0b;--card-accent-bg: #fffbeb}.osl-card:nth-child(6n+5){--card-accent: #f43f5e;--card-accent-bg: #fff1f2}.osl-card:nth-child(6n){--card-accent: #8b5cf6;--card-accent-bg: #faf5ff}.osl-card:before{content:\"\";position:absolute;top:0;left:0;bottom:0;width:4px;background:var(--card-accent, var(--osl-primary, #6366f1))}.osl-card:hover{transform:translateY(-4px);box-shadow:0 12px 32px #1018281a,0 4px 12px #1018280f;border-color:#d0d5dd}.osl-card--highlighted{outline:2px solid var(--osl-primary, #6366f1);outline-offset:2px;animation:osl-card-enter .28s ease both,osl-card-highlight-pulse 2.5s ease-out .3s both}.osl-card--selectable{cursor:pointer}.osl-card--skeleton{pointer-events:none;animation:osl-card-enter .28s ease both}.osl-card--skeleton:hover{transform:none;box-shadow:0 1px 4px #1018280f}@keyframes osl-card-highlight-pulse{0%{box-shadow:0 0 0 4px #6366f14d}to{box-shadow:none}}.osl-card-inner{padding:16px 16px 16px 20px;display:flex;flex-direction:column;height:100%}.osl-card-header{display:flex;align-items:center;gap:12px;margin-bottom:0}.osl-card-avatar{width:40px;height:40px;border-radius:10px;background:var(--card-accent, var(--osl-primary, #6366f1));color:#fff;font-size:16px;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0;letter-spacing:0;box-shadow:0 4px 10px #00000026}.osl-card-avatar--skeleton{background:#e5e7eb;box-shadow:none;animation:osl-sk-pulse 1.4s ease-in-out infinite}.osl-card-title-wrap{flex:1;min-width:0}.osl-card-title{display:block;font-weight:700;font-size:14px;color:#101828;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:1.4}.osl-card-actions{display:flex;align-items:center;gap:6px;flex-shrink:0}.osl-card-action-btn{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;border-radius:8px;border:1.5px solid #e4e7ec;background:#fff;cursor:pointer;transition:background .15s,border-color .15s,transform .15s,box-shadow .15s;padding:0}.osl-card-action-btn svg{width:14px;height:14px;transition:stroke .15s,fill .15s}.osl-card-action-btn--more svg{fill:#9ca3af;stroke:none}.osl-card-action-btn--more:hover{background:var(--card-accent-bg, #eef2ff);border-color:var(--card-accent, var(--osl-primary, #6366f1));box-shadow:0 2px 6px #00000014;transform:scale(1.05)}.osl-card-action-btn--more:hover svg{fill:var(--card-accent, var(--osl-primary, #6366f1))}.osl-card-action-btn--edit svg{stroke:#6b7280}.osl-card-action-btn--edit:hover{background:var(--card-accent-bg, #eef2ff);border-color:var(--card-accent, var(--osl-primary, #6366f1));box-shadow:0 2px 6px #00000014;transform:scale(1.05)}.osl-card-action-btn--edit:hover svg{stroke:var(--card-accent, var(--osl-primary, #6366f1))}.osl-card-action-btn--delete svg{stroke:#9ca3af}.osl-card-action-btn--delete:hover{background:#fff1f2;border-color:#f43f5e;box-shadow:0 2px 6px #f43f5e26;transform:scale(1.05)}.osl-card-action-btn--delete:hover svg{stroke:#f43f5e}.osl-card-divider{height:1px;background:#f2f4f7;margin:14px 0}.osl-card-body{display:flex;flex-direction:column;gap:10px;flex:1}.osl-card-field{display:grid;grid-template-columns:100px 1fr;gap:6px;align-items:baseline}.osl-card-label{font-size:10px;font-weight:600;color:#9ca3af;text-transform:uppercase;letter-spacing:.06em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.osl-card-value{font-size:13px;font-weight:500;color:#374151;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.osl-card-value.link{text-decoration:underline;color:#2563eb;cursor:pointer}.osl-card-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:320px;gap:12px;padding:40px 20px}.osl-card-empty-svg{width:180px;height:auto;opacity:.85}.osl-card-empty-title{font-size:16px;font-weight:600;color:#374151;margin:4px 0 0;text-align:center}.osl-card-empty-desc{font-size:13px;color:#9ca3af;margin:0;text-align:center}.osl-card-loader{display:flex;flex-direction:column;align-items:center;gap:10px;padding:28px 20px 16px}.osl-card-loader-track{width:160px;height:3px;background:#f3f4f6;border-radius:99px;overflow:hidden}.osl-card-loader-bar{height:100%;width:40%;background:linear-gradient(90deg,transparent,var(--osl-primary, #6366f1),transparent);border-radius:99px;animation:osl-loader-sweep 1.2s ease-in-out infinite}@keyframes osl-loader-sweep{0%{transform:translate(-200%)}to{transform:translate(500%)}}.osl-card-loader-text{font-size:12px;color:#9ca3af;font-weight:500}.osl-card-all-loaded{display:flex;align-items:center;gap:12px;padding:20px 16px 8px;justify-content:center}.osl-card-all-loaded-line{flex:1;max-width:80px;height:1px;background:#e5e7eb}.osl-card-all-loaded-text{font-size:11px;color:#d1d5db;font-weight:600;text-transform:uppercase;letter-spacing:.06em;white-space:nowrap}@keyframes osl-sk-pulse{0%,to{opacity:1}50%{opacity:.4}}.osl-sk-line{height:12px;background:#e9eaec;border-radius:6px;animation:osl-sk-pulse 1.4s ease-in-out infinite;width:80%}.osl-sk-line--title{height:14px;width:65%}.osl-sk-line--label{width:40%;height:10px}.osl-sk-line--short{width:50%}.osl-card-menu{position:fixed;z-index:9999;min-width:196px;background:#fff;border:1px solid #eaecf0;border-radius:12px;box-shadow:0 12px 32px #10182824,0 4px 12px #1018280f;overflow:hidden;animation:osl-menu-pop .16s cubic-bezier(.16,1,.3,1)}@keyframes osl-menu-pop{0%{opacity:0;transform:translateY(-8px) scale(.96)}to{opacity:1;transform:translateY(0) scale(1)}}.osl-card-menu-header{padding:10px 14px 7px;font-size:10px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:#9ca3af;border-bottom:1px solid #f2f4f7;-webkit-user-select:none;user-select:none}.osl-card-menu-item{display:flex;align-items:center;gap:10px;width:100%;padding:10px 14px;background:transparent;border:none;border-left:3px solid transparent;border-bottom:1px solid #f9fafb;text-align:left;font-size:13px;font-weight:500;font-family:inherit;color:#374151;cursor:pointer;white-space:nowrap;transition:background .12s,color .12s,border-left-color .12s}.osl-card-menu-item:last-child{border-bottom:none}.osl-card-menu-item:hover{background:var(--card-accent-bg, #f5f3ff);color:var(--card-accent, var(--osl-primary, #6366f1));border-left-color:var(--card-accent, var(--osl-primary, #6366f1))}.osl-card-menu-item:hover .osl-card-menu-dot{background:var(--card-accent, var(--osl-primary, #6366f1));box-shadow:0 0 0 3px #6366f129}.osl-card-menu-dot{flex-shrink:0;width:6px;height:6px;border-radius:50%;background:#d1d5db;transition:background .12s,box-shadow .12s}\n"] }]
|
|
2826
3082
|
}], propDecorators: { formBodyTpl: [{
|
|
2827
3083
|
type: ViewChild,
|
|
2828
3084
|
args: ['formBodyTpl']
|
|
@@ -2835,6 +3091,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
2835
3091
|
}], searchbar: [{
|
|
2836
3092
|
type: ViewChild,
|
|
2837
3093
|
args: ['searchbar']
|
|
3094
|
+
}], gridRef: [{
|
|
3095
|
+
type: ViewChild,
|
|
3096
|
+
args: ['gridRef']
|
|
3097
|
+
}], cardContainerRef: [{
|
|
3098
|
+
type: ViewChild,
|
|
3099
|
+
args: ['cardContainerRef']
|
|
2838
3100
|
}], title: [{
|
|
2839
3101
|
type: Input,
|
|
2840
3102
|
args: ['title']
|
|
@@ -2904,6 +3166,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
2904
3166
|
}], primaryKey: [{
|
|
2905
3167
|
type: Input,
|
|
2906
3168
|
args: ['primaryKey']
|
|
3169
|
+
}], onSave: [{
|
|
3170
|
+
type: Input,
|
|
3171
|
+
args: ['onSave']
|
|
3172
|
+
}], cardPageSize: [{
|
|
3173
|
+
type: Input,
|
|
3174
|
+
args: ['cardPageSize']
|
|
3175
|
+
}], cardTemplate: [{
|
|
3176
|
+
type: Input,
|
|
3177
|
+
args: ['cardTemplate']
|
|
2907
3178
|
}], onSearch: [{
|
|
2908
3179
|
type: Output
|
|
2909
3180
|
}], onAdd: [{
|
|
@@ -2922,12 +3193,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
2922
3193
|
type: Output
|
|
2923
3194
|
}], onStateRestored: [{
|
|
2924
3195
|
type: Output
|
|
2925
|
-
}],
|
|
2926
|
-
type:
|
|
2927
|
-
args: ['
|
|
2928
|
-
}], onSave: [{
|
|
2929
|
-
type: Input,
|
|
2930
|
-
args: ['onSave']
|
|
3196
|
+
}], onDocumentClick: [{
|
|
3197
|
+
type: HostListener,
|
|
3198
|
+
args: ['document:click']
|
|
2931
3199
|
}] } });
|
|
2932
3200
|
|
|
2933
3201
|
class OslFormGrid {
|
|
@@ -3148,7 +3416,7 @@ class OslAutocompleteLister {
|
|
|
3148
3416
|
this.dialogRef.close(event);
|
|
3149
3417
|
}
|
|
3150
3418
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: OslAutocompleteLister, deps: [{ token: i1.MatDialogRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
3151
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.9", type: OslAutocompleteLister, isStandalone: false, selector: "osl-autocomplete-lister", inputs: { data: "data" }, ngImport: i0, template: "<div class=\"p-4\">\r\n <osl-setup [loading]=\"loader\" [autoMode]=\"false\" [title]=\"autocompleteData?.title\" [totalRecords]=\"recordCount\" (pageSizeChange)=\"onPageChange($event)\" (pageChange)=\"onPageChange($event)\" (onRowClick)=\"onRowClick($event)\" [columns]=\"column\" [datasource]=\"datasource\" [isLister]=\"true\"></osl-setup>\r\n \r\n</div>", styles: [""], dependencies: [{ kind: "component", type: OslSetup, selector: "osl-setup", inputs: ["title", "columns", "datasource", "isPaginated", "pageSize", "autoMode", "tableHeight", "totalRecords", "loading", "dialogWidth", "formElements", "beforeDisplay", "onAddEditFn", "isLister", "canAdd", "canEdit", "canDelete", "moreMenuActions", "customFormFooter", "customHeaderTemp", "partialCustomHeaderTemp", "stateKey", "primaryKey", "onSave"], outputs: ["onSearch", "onAdd", "onEdit", "onDelete", "pageChange", "pageSizeChange", "sortChange", "onRowClick", "onStateRestored"] }] });
|
|
3419
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.9", type: OslAutocompleteLister, isStandalone: false, selector: "osl-autocomplete-lister", inputs: { data: "data" }, ngImport: i0, template: "<div class=\"p-4\">\r\n <osl-setup [loading]=\"loader\" [autoMode]=\"false\" [title]=\"autocompleteData?.title\" [totalRecords]=\"recordCount\" (pageSizeChange)=\"onPageChange($event)\" (pageChange)=\"onPageChange($event)\" (onRowClick)=\"onRowClick($event)\" [columns]=\"column\" [datasource]=\"datasource\" [isLister]=\"true\"></osl-setup>\r\n \r\n</div>", styles: [""], dependencies: [{ kind: "component", type: OslSetup, selector: "osl-setup", inputs: ["title", "columns", "datasource", "isPaginated", "pageSize", "autoMode", "tableHeight", "totalRecords", "loading", "dialogWidth", "formElements", "beforeDisplay", "onAddEditFn", "isLister", "canAdd", "canEdit", "canDelete", "moreMenuActions", "customFormFooter", "customHeaderTemp", "partialCustomHeaderTemp", "stateKey", "primaryKey", "onSave", "cardPageSize", "cardTemplate"], outputs: ["onSearch", "onAdd", "onEdit", "onDelete", "pageChange", "pageSizeChange", "sortChange", "onRowClick", "onStateRestored"] }] });
|
|
3152
3420
|
}
|
|
3153
3421
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: OslAutocompleteLister, decorators: [{
|
|
3154
3422
|
type: Component,
|