@servicemind.tis/tis-smart-table-viewer 2.1.2 → 2.3.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.
@@ -5,7 +5,7 @@ import * as i6 from '@angular/forms';
5
5
  import { FormGroup, FormControl, Validators, FormsModule, ReactiveFormsModule } from '@angular/forms';
6
6
  import * as i3$1 from '@angular/router';
7
7
  import { RouterLink, RouterOutlet } from '@angular/router';
8
- import { BehaviorSubject, of, Subject, takeUntil, tap, map, shareReplay, debounceTime, distinctUntilChanged } from 'rxjs';
8
+ import { BehaviorSubject, of, takeUntil, Subject, tap, map, shareReplay, debounceTime, distinctUntilChanged } from 'rxjs';
9
9
  import { SelectionModel } from '@angular/cdk/collections';
10
10
  import * as i13 from '@angular/cdk/drag-drop';
11
11
  import { moveItemInArray, DragDropModule } from '@angular/cdk/drag-drop';
@@ -78,9 +78,9 @@ class ApiDataSource {
78
78
  this.apiSubject.complete();
79
79
  this.extraDataSubject.complete();
80
80
  this.loadingSubject.complete();
81
- // if(this.apiSubs) {
82
- // this.apiSubs.unsubscribe();
83
- // }
81
+ if (this.apiSubs) {
82
+ this.apiSubs.unsubscribe();
83
+ }
84
84
  }
85
85
  load(url, pageIndex, pageSize, search, filter, sortFilter) {
86
86
  if (this.apiSubs) {
@@ -99,6 +99,28 @@ class ApiDataSource {
99
99
  this.extraDataSubject.next(r?.extraData);
100
100
  });
101
101
  }
102
+ loadWithCancellation(url, pageIndex, pageSize, search, filter, sortFilter, cancelSubject) {
103
+ if (this.apiSubs) {
104
+ this.apiSubs.unsubscribe();
105
+ }
106
+ this.loadingSubject.next(true);
107
+ let apiCall$ = this.apiService.getList(url, (pageIndex + 1), pageSize, search, { filter }, { sortFilter }).pipe(catchError(() => of([])), finalize(() => this.loadingSubject.next(false)));
108
+ // Add cancellation capability if provided
109
+ if (cancelSubject) {
110
+ apiCall$ = apiCall$.pipe(takeUntil(cancelSubject));
111
+ }
112
+ this.apiSubs = apiCall$.subscribe(r => {
113
+ console.log(`DataSource: Url: ${url}, Reply:`, r);
114
+ if (r?.data?.length > 0) {
115
+ this.totalDataLength.next(r?.total);
116
+ }
117
+ else {
118
+ this.totalDataLength.next(0);
119
+ }
120
+ this.apiSubject.next(r?.data);
121
+ this.extraDataSubject.next(r?.extraData);
122
+ });
123
+ }
102
124
  }
103
125
 
104
126
  class ApiService {
@@ -166,6 +188,943 @@ const removeMultipleKeys = (keys) => {
166
188
  });
167
189
  };
168
190
 
191
+ /**
192
+ * TimeoutManager - A utility class for managing timeouts to prevent memory leaks
193
+ *
194
+ * This class provides a centralized way to create, track, and clean up setTimeout calls.
195
+ * It automatically handles cleanup when component is destroyed to prevent memory leaks.
196
+ *
197
+ * @example
198
+ * ```typescript
199
+ * export class MyComponent implements OnDestroy {
200
+ * private timeoutManager = new TimeoutManager();
201
+ *
202
+ * someMethod() {
203
+ * this.timeoutManager.createTimeout(() => {
204
+ * console.log('Delayed execution');
205
+ * }, 1000);
206
+ * }
207
+ *
208
+ * ngOnDestroy() {
209
+ * this.timeoutManager.clearAll(); // Clean up all pending timeouts
210
+ * }
211
+ * }
212
+ * ```
213
+ */
214
+ class TimeoutManager {
215
+ activeTimeouts = new Set();
216
+ /**
217
+ * Creates a tracked timeout that will be automatically cleaned up
218
+ * @param callback - Function to execute after delay
219
+ * @param delay - Delay in milliseconds
220
+ * @returns The timeout ID (same as setTimeout return value)
221
+ */
222
+ createTimeout(callback, delay) {
223
+ const timeoutId = setTimeout(() => {
224
+ // Auto-remove from tracking when timeout executes naturally
225
+ this.activeTimeouts.delete(timeoutId);
226
+ callback();
227
+ }, delay);
228
+ // Add to tracking set
229
+ this.activeTimeouts.add(timeoutId);
230
+ return timeoutId;
231
+ }
232
+ /**
233
+ * Manually clear a specific timeout
234
+ * @param timeoutId - The timeout ID returned from createTimeout
235
+ */
236
+ clearTimeout(timeoutId) {
237
+ if (this.activeTimeouts.has(timeoutId)) {
238
+ clearTimeout(timeoutId);
239
+ this.activeTimeouts.delete(timeoutId);
240
+ }
241
+ }
242
+ /**
243
+ * Clear all pending timeouts
244
+ * This should be called in ngOnDestroy to prevent memory leaks
245
+ */
246
+ clearAll() {
247
+ this.activeTimeouts.forEach(timeoutId => clearTimeout(timeoutId));
248
+ this.activeTimeouts.clear();
249
+ }
250
+ /**
251
+ * Get the number of active (pending) timeouts
252
+ * Useful for debugging and testing
253
+ */
254
+ get activeCount() {
255
+ return this.activeTimeouts.size;
256
+ }
257
+ /**
258
+ * Check if a specific timeout is still active
259
+ * @param timeoutId - The timeout ID to check
260
+ */
261
+ isActive(timeoutId) {
262
+ return this.activeTimeouts.has(timeoutId);
263
+ }
264
+ }
265
+ /**
266
+ * Static helper functions for one-off timeout usage
267
+ * Use the TimeoutManager class for more comprehensive timeout management
268
+ */
269
+ class TimeoutHelper {
270
+ /**
271
+ * Create a single tracked timeout with external cleanup responsibility
272
+ * @param callback - Function to execute after delay
273
+ * @param delay - Delay in milliseconds
274
+ * @param trackingSet - Set to track the timeout for cleanup
275
+ * @returns The timeout ID
276
+ */
277
+ static createTrackedTimeout(callback, delay, trackingSet) {
278
+ const timeoutId = setTimeout(() => {
279
+ trackingSet.delete(timeoutId);
280
+ callback();
281
+ }, delay);
282
+ trackingSet.add(timeoutId);
283
+ return timeoutId;
284
+ }
285
+ /**
286
+ * Clear all timeouts in a tracking set
287
+ * @param trackingSet - Set containing timeout IDs to clear
288
+ */
289
+ static clearAllTimeouts(trackingSet) {
290
+ trackingSet.forEach(timeoutId => clearTimeout(timeoutId));
291
+ trackingSet.clear();
292
+ }
293
+ }
294
+
295
+ /**
296
+ * Centralized date/time utility helper for consistent date handling across the library.
297
+ * Provides common date formatting and conversion functions to avoid code duplication.
298
+ */
299
+ class DateTimeHelper {
300
+ /**
301
+ * Formats a date value for display based on form control type
302
+ * @param value - The date value (Date, DateTime, string, number)
303
+ * @param formControlType - The type of form control ('date', 'date-time', etc.)
304
+ * @returns Formatted date string
305
+ */
306
+ static formatForDisplay(value, formControlType) {
307
+ if (!value)
308
+ return '';
309
+ const dateTime = this.toDateTime(value);
310
+ if (!dateTime?.isValid)
311
+ return '';
312
+ switch (formControlType) {
313
+ case 'date':
314
+ return dateTime.toFormat('dd-MM-yyyy');
315
+ case 'date-time':
316
+ return dateTime.toFormat('dd-MM-yyyy HH:mm');
317
+ case 'date-time-with-seconds':
318
+ return dateTime.toFormat('dd-MM-yyyy HH:mm:ss');
319
+ default:
320
+ return dateTime.toFormat('dd-MM-yyyy');
321
+ }
322
+ }
323
+ /**
324
+ * Converts various date formats to DateTime object
325
+ * @param value - Date value in various formats
326
+ * @returns DateTime object or null if invalid
327
+ */
328
+ static toDateTime(value) {
329
+ if (!value)
330
+ return null;
331
+ if (DateTime.isDateTime(value)) {
332
+ return value;
333
+ }
334
+ if (value instanceof Date) {
335
+ return DateTime.fromJSDate(value);
336
+ }
337
+ if (typeof value === 'string' && value !== '') {
338
+ // Try parsing as milliseconds first (if numeric string)
339
+ const numValue = Number(value);
340
+ if (!isNaN(numValue) && numValue > 0) {
341
+ return DateTime.fromMillis(numValue);
342
+ }
343
+ // Try parsing as ISO string
344
+ return DateTime.fromISO(value);
345
+ }
346
+ if (typeof value === 'number') {
347
+ return DateTime.fromMillis(value);
348
+ }
349
+ return null;
350
+ }
351
+ /**
352
+ * Converts date/DateTime objects to milliseconds for API calls
353
+ * @param value - Date value
354
+ * @returns Milliseconds or original value if not a date
355
+ */
356
+ static toMilliseconds(value) {
357
+ if (!value)
358
+ return value;
359
+ if (value instanceof Date) {
360
+ return DateTime.fromJSDate(value).toMillis();
361
+ }
362
+ if (DateTime.isDateTime(value)) {
363
+ return value.toMillis();
364
+ }
365
+ return value;
366
+ }
367
+ /**
368
+ * Checks if a query parameter key represents a date field
369
+ * @param key - Query parameter key
370
+ * @param value - Query parameter value
371
+ * @returns True if it's a date field
372
+ */
373
+ static isDateQueryParam(key, value) {
374
+ return key.toLowerCase().includes('date') && value.length === 13;
375
+ }
376
+ /**
377
+ * Parses date from query parameters
378
+ * @param value - Query parameter value (milliseconds as string)
379
+ * @returns DateTime object
380
+ */
381
+ static parseFromQueryParam(value) {
382
+ return DateTime.fromMillis(Number(value));
383
+ }
384
+ }
385
+
386
+ /**
387
+ * Centralized query parameter utility helper for consistent URL parameter handling.
388
+ * Provides common functions for parsing, validating, and transforming query parameters.
389
+ */
390
+ class QueryParamsHelper {
391
+ /**
392
+ * Parses query parameters from URL and handles type conversions
393
+ * @param url - Full URL string
394
+ * @returns Parsed query parameters object
395
+ */
396
+ static parseQueryParams(url) {
397
+ const urlObj = new URL(url);
398
+ const params = new URLSearchParams(urlObj.search);
399
+ const paramsObj = {};
400
+ params.forEach((value, key) => {
401
+ // Check if the parameter already exists (for handling multiple values)
402
+ if (paramsObj.hasOwnProperty(key)) {
403
+ // If it's not already an array, convert it to an array
404
+ if (!Array.isArray(paramsObj[key])) {
405
+ paramsObj[key] = [paramsObj[key]];
406
+ }
407
+ // Push the new value to the existing array
408
+ paramsObj[key].push(value);
409
+ }
410
+ else {
411
+ // Assign the value to the key in the object
412
+ paramsObj[key] = value;
413
+ }
414
+ });
415
+ return paramsObj;
416
+ }
417
+ /**
418
+ * Checks if a query parameter value is valid (not empty, null, or undefined)
419
+ * @param value - Query parameter value
420
+ * @returns True if valid
421
+ */
422
+ static isValidParam(value) {
423
+ return value && value !== '' && value !== 'null' && value !== 'undefined';
424
+ }
425
+ /**
426
+ * Processes a query parameter value and handles arrays
427
+ * @param value - Raw query parameter value
428
+ * @returns Processed value (string or array)
429
+ */
430
+ static processParamValue(value) {
431
+ if (value.includes(',')) {
432
+ return value.split(',');
433
+ }
434
+ return value;
435
+ }
436
+ /**
437
+ * Processes query parameters for filter form with type conversions
438
+ * @param queryParams - Raw query parameters
439
+ * @param columnsCodeMapping - Column mapping for transformations
440
+ * @returns Processed filter and sort objects
441
+ */
442
+ static processForFilters(queryParams, columnsCodeMapping) {
443
+ const filterParams = {};
444
+ const sortParams = {};
445
+ let pageIndex = 0;
446
+ let pageSize = 10;
447
+ let search = '';
448
+ for (const key in queryParams) {
449
+ if (!this.isValidParam(queryParams[key]))
450
+ continue;
451
+ let fixedKeyMatched = false;
452
+ const value = queryParams[key];
453
+ // Handle fixed parameters
454
+ if (key.toLowerCase() === 'pageindex') {
455
+ pageIndex = Number(value);
456
+ fixedKeyMatched = true;
457
+ }
458
+ else if (key.toLowerCase() === 'pagesize') {
459
+ pageSize = Number(value);
460
+ fixedKeyMatched = true;
461
+ }
462
+ else if (key.toLowerCase() === 'sortby') {
463
+ sortParams.sortBy = value;
464
+ fixedKeyMatched = true;
465
+ }
466
+ else if (key.toLowerCase() === 'sortorder') {
467
+ sortParams.sortOrder = value;
468
+ fixedKeyMatched = true;
469
+ }
470
+ else if (key.toLowerCase() === 'search') {
471
+ search = value;
472
+ fixedKeyMatched = true;
473
+ }
474
+ else if (DateTimeHelper.isDateQueryParam(key, value)) {
475
+ // Handle date parameters
476
+ filterParams[key] = DateTimeHelper.parseFromQueryParam(value);
477
+ fixedKeyMatched = true;
478
+ }
479
+ if (!fixedKeyMatched) {
480
+ filterParams[key] = this.processParamValue(value);
481
+ // Apply transformation if mapping exists
482
+ const mapping = columnsCodeMapping.find(ccm => ccm.filterFormKey === key);
483
+ if (mapping?.transformQueryParamFn) {
484
+ filterParams[key] = mapping.transformQueryParamFn(filterParams[key]);
485
+ }
486
+ }
487
+ }
488
+ return { filterParams, sortParams, pageIndex, pageSize, search };
489
+ }
490
+ /**
491
+ * Builds query string from filter data with proper encoding
492
+ * @param filterData - Filter form data
493
+ * @param sortParams - Sort parameters
494
+ * @param pageIndex - Current page index
495
+ * @param pageSize - Current page size
496
+ * @param search - Search term
497
+ * @returns URLSearchParams object
498
+ */
499
+ static buildQueryString(filterData, sortParams, pageIndex, pageSize, search) {
500
+ const qs = new URLSearchParams();
501
+ // Process filter data
502
+ if (filterData) {
503
+ const processedFilter = { ...filterData };
504
+ // Convert date objects to milliseconds
505
+ for (const key in processedFilter) {
506
+ processedFilter[key] = DateTimeHelper.toMilliseconds(processedFilter[key]);
507
+ }
508
+ // Append filter parameters
509
+ Object.keys(processedFilter).forEach(key => {
510
+ const value = processedFilter[key];
511
+ if (this.isValidParam(value)) {
512
+ if (value === '*') {
513
+ qs.append(key, '');
514
+ }
515
+ else {
516
+ qs.append(key, value);
517
+ }
518
+ }
519
+ });
520
+ }
521
+ // Append sort parameters
522
+ if (sortParams) {
523
+ Object.keys(sortParams).forEach(key => {
524
+ if (this.isValidParam(sortParams[key])) {
525
+ qs.append(key, sortParams[key]);
526
+ }
527
+ });
528
+ }
529
+ // Append pagination and search
530
+ qs.append('pageIndex', pageIndex.toString());
531
+ qs.append('pageSize', pageSize.toString());
532
+ if (search !== '') {
533
+ qs.append('search', search);
534
+ }
535
+ return qs;
536
+ }
537
+ }
538
+
539
+ /**
540
+ * Centralized filter display utility helper for managing filter value formatting and grouping.
541
+ * Handles the complex logic of grouping and displaying filter values in a consistent manner.
542
+ */
543
+ class FilterDisplayHelper {
544
+ /**
545
+ * Formats filter values based on form control type for display
546
+ * @param items - Array of filter display values
547
+ * @returns Processed array with formatted display values
548
+ */
549
+ static formatFilterValuesForDisplay(items) {
550
+ return items.map(item => {
551
+ const processedItem = { ...item };
552
+ // Handle different form control types
553
+ switch (item.formControlType) {
554
+ case 'input':
555
+ case 'checkbox':
556
+ // No special formatting needed
557
+ break;
558
+ case 'date':
559
+ processedItem.valueKey = DateTimeHelper.formatForDisplay(item.value, 'date');
560
+ break;
561
+ case 'date-time':
562
+ processedItem.valueKey = DateTimeHelper.formatForDisplay(item.value, 'date-time');
563
+ break;
564
+ default:
565
+ // Keep original valueKey if no special handling needed
566
+ break;
567
+ }
568
+ return processedItem;
569
+ });
570
+ }
571
+ /**
572
+ * Groups filter values by form control attributes
573
+ * @param data - Array of filter display values
574
+ * @returns Grouped filter values
575
+ */
576
+ static groupByFormControlAttributes(data) {
577
+ const groups = {};
578
+ // First format the data for display
579
+ const formattedData = this.formatFilterValuesForDisplay(data);
580
+ formattedData.forEach(item => {
581
+ const key = `${item.formControlName}-${item.formControlType}`;
582
+ if (!groups[key]) {
583
+ groups[key] = {
584
+ formControlName: item.formControlName,
585
+ formControlType: item.formControlType,
586
+ arrValues: []
587
+ };
588
+ }
589
+ const isSingleValue = this.isSingleValueFormControl(item.formControlType, item.isSingleValue);
590
+ // Check if only the last value should be kept due to isSingleValue or duplicated value/valueKey
591
+ if (isSingleValue) {
592
+ groups[key].arrValues = [item]; // Replace with the current item
593
+ }
594
+ else {
595
+ // Check for duplicate value and valueKey in the current array
596
+ const existingIndex = groups[key].arrValues.findIndex(x => x.value === item.value && x.valueKey === item.valueKey);
597
+ if (existingIndex !== -1) {
598
+ groups[key].arrValues[existingIndex] = item; // Replace the duplicate
599
+ }
600
+ else {
601
+ groups[key].arrValues.push(item); // Add new item
602
+ }
603
+ }
604
+ });
605
+ return Object.values(groups);
606
+ }
607
+ /**
608
+ * Determines if a form control should only have single values
609
+ * @param formControlType - Type of form control
610
+ * @param explicitSingleValue - Explicit single value flag
611
+ * @returns True if single value control
612
+ */
613
+ static isSingleValueFormControl(formControlType, explicitSingleValue) {
614
+ if (explicitSingleValue !== undefined) {
615
+ return explicitSingleValue;
616
+ }
617
+ return ['input', 'radio', 'date', 'date-time', 'toggle'].includes(formControlType);
618
+ }
619
+ /**
620
+ * Updates selected filter values by replacing values for a specific form control
621
+ * @param currentValues - Current selected filter values
622
+ * @param newValues - New values to add/update
623
+ * @param formControlName - Name of the form control being updated
624
+ * @returns Updated filter values and grouped values
625
+ */
626
+ static updateSelectedFilterValues(currentValues, newValues, formControlName) {
627
+ let targetFormControlName;
628
+ let newValuesArray;
629
+ if (Array.isArray(newValues)) {
630
+ newValuesArray = newValues;
631
+ targetFormControlName = formControlName || newValues[0]?.formControlName;
632
+ }
633
+ else {
634
+ newValuesArray = [newValues];
635
+ targetFormControlName = formControlName || newValues?.formControlName;
636
+ }
637
+ // Remove existing values for this form control
638
+ const filteredValues = currentValues.filter(sfv => sfv.formControlName !== targetFormControlName);
639
+ // Group the new values
640
+ const newGroupedValues = this.groupByFormControlAttributes(newValuesArray);
641
+ // Add new values for the target form control
642
+ newGroupedValues.forEach(gv => {
643
+ if (gv.formControlName === targetFormControlName) {
644
+ gv.arrValues.forEach(v => {
645
+ filteredValues.push(v);
646
+ });
647
+ }
648
+ });
649
+ // Return updated values and all grouped values
650
+ const allGroupedValues = this.groupByFormControlAttributes(filteredValues);
651
+ return {
652
+ selectedFilterValues: filteredValues,
653
+ selectedFilterGroupedValues: allGroupedValues
654
+ };
655
+ }
656
+ /**
657
+ * Filters selected values to only show those present in query parameters
658
+ * @param selectedValues - All selected filter values
659
+ * @param queryParams - Current query parameters
660
+ * @returns Filtered values for display
661
+ */
662
+ static getValuesForDisplay(selectedValues, queryParams) {
663
+ return selectedValues.filter(sf => queryParams.hasOwnProperty(sf.formControlName));
664
+ }
665
+ /**
666
+ * Removes a specific filter value from the collection
667
+ * @param selectedValues - Current selected filter values
668
+ * @param filterToRemove - Filter value to remove
669
+ * @returns Updated filter values
670
+ */
671
+ static removeFilterValue(selectedValues, filterToRemove) {
672
+ return selectedValues.filter(sfv => !(sfv.formControlName === filterToRemove.formControlName &&
673
+ sfv.valueKey === filterToRemove.valueKey));
674
+ }
675
+ }
676
+
677
+ /**
678
+ * Centralized validation utility helper for common validation tasks.
679
+ * Provides reusable validation functions to avoid code duplication.
680
+ */
681
+ class ValidationHelper {
682
+ /**
683
+ * Checks if a value is not null, undefined, or empty string
684
+ * @param value - Value to check
685
+ * @returns True if value has content
686
+ */
687
+ static hasValue(value) {
688
+ return value !== null && value !== undefined && value !== '';
689
+ }
690
+ /**
691
+ * Checks if any values in an object are non-empty
692
+ * @param obj - Object to check
693
+ * @returns True if any value is non-empty
694
+ */
695
+ static hasNonEmptyValue(obj) {
696
+ if (!obj)
697
+ return false;
698
+ return Object.values(obj).some(value => this.hasValue(value));
699
+ }
700
+ /**
701
+ * Checks if a form has any non-empty values
702
+ * @param formData - Form data object
703
+ * @returns True if form has any data
704
+ */
705
+ static hasFormData(formData) {
706
+ if (!formData)
707
+ return false;
708
+ return this.hasNonEmptyValue(formData);
709
+ }
710
+ /**
711
+ * Validates if an array has items
712
+ * @param array - Array to check
713
+ * @returns True if array exists and has items
714
+ */
715
+ static hasItems(array) {
716
+ return Array.isArray(array) && array.length > 0;
717
+ }
718
+ /**
719
+ * Checks if a URL is valid
720
+ * @param url - URL string to validate
721
+ * @returns True if URL is valid
722
+ */
723
+ static isValidUrl(url) {
724
+ if (!url || typeof url !== 'string')
725
+ return false;
726
+ try {
727
+ new URL(url);
728
+ return true;
729
+ }
730
+ catch {
731
+ return false;
732
+ }
733
+ }
734
+ /**
735
+ * Validates if a string is a valid number
736
+ * @param value - Value to check
737
+ * @returns True if value is a valid number
738
+ */
739
+ static isValidNumber(value) {
740
+ return !isNaN(Number(value)) && isFinite(Number(value));
741
+ }
742
+ /**
743
+ * Checks if an object has a specific property with a valid value
744
+ * @param obj - Object to check
745
+ * @param property - Property name
746
+ * @returns True if property exists and has a value
747
+ */
748
+ static hasProperty(obj, property) {
749
+ return obj && obj.hasOwnProperty(property) && this.hasValue(obj[property]);
750
+ }
751
+ /**
752
+ * Validates if a selection model row has the required key
753
+ * @param row - Row object
754
+ * @param keyName - Key property name
755
+ * @returns True if row has the key property with a value
756
+ */
757
+ static hasRowKey(row, keyName) {
758
+ return row && this.hasProperty(row, keyName);
759
+ }
760
+ /**
761
+ * Checks if a filter value should be processed (not null, empty, or invalid)
762
+ * @param value - Filter value
763
+ * @returns True if filter value is valid for processing
764
+ */
765
+ static isValidFilterValue(value) {
766
+ if (!this.hasValue(value))
767
+ return false;
768
+ // Check for common invalid filter values
769
+ const invalidValues = ['null', 'undefined', '*'];
770
+ if (typeof value === 'string' && invalidValues.includes(value)) {
771
+ return value === '*'; // Special case: '*' is valid but gets converted to empty string
772
+ }
773
+ return true;
774
+ }
775
+ /**
776
+ * Validates pagination parameters
777
+ * @param pageIndex - Page index
778
+ * @param pageSize - Page size
779
+ * @returns Object with validation results
780
+ */
781
+ static validatePagination(pageIndex, pageSize) {
782
+ const validPageIndex = this.isValidNumber(pageIndex) ? Number(pageIndex) : 0;
783
+ const validPageSize = this.isValidNumber(pageSize) ? Number(pageSize) : 10;
784
+ return {
785
+ isValid: validPageIndex >= 0 && validPageSize > 0,
786
+ pageIndex: Math.max(0, validPageIndex),
787
+ pageSize: Math.max(1, validPageSize)
788
+ };
789
+ }
790
+ }
791
+
792
+ /**
793
+ * Centralized collection management utility helper for common array and object operations.
794
+ * Provides reusable functions for managing collections, selections, and data structures.
795
+ */
796
+ class CollectionHelper {
797
+ /**
798
+ * Safely clears an array if it exists
799
+ * @param array - Array to clear
800
+ */
801
+ static clearArray(array) {
802
+ if (Array.isArray(array)) {
803
+ array.length = 0;
804
+ }
805
+ }
806
+ /**
807
+ * Safely clears a Set if it exists
808
+ * @param set - Set to clear
809
+ */
810
+ static clearSet(set) {
811
+ if (set instanceof Set) {
812
+ set.clear();
813
+ }
814
+ }
815
+ /**
816
+ * Safely clears a Map if it exists
817
+ * @param map - Map to clear
818
+ */
819
+ static clearMap(map) {
820
+ if (map instanceof Map) {
821
+ map.clear();
822
+ }
823
+ }
824
+ /**
825
+ * Gets a consistent identifier for a row based on available keys
826
+ * @param row - Row object
827
+ * @param primaryKey - Primary key property name (default: 'id')
828
+ * @param fallbackKey - Fallback key property name
829
+ * @returns Row identifier or JSON string as last resort
830
+ */
831
+ static getRowIdentifier(row, primaryKey = 'id', fallbackKey) {
832
+ if (!row)
833
+ return '';
834
+ // Try primary key first
835
+ if (row[primaryKey] !== undefined && row[primaryKey] !== null) {
836
+ return row[primaryKey];
837
+ }
838
+ // Try fallback key if provided
839
+ if (fallbackKey && row[fallbackKey] !== undefined && row[fallbackKey] !== null) {
840
+ return row[fallbackKey];
841
+ }
842
+ // Last resort: stringify the object (not recommended for large objects)
843
+ return JSON.stringify(row);
844
+ }
845
+ /**
846
+ * Creates a hash from an array of objects for cache validation
847
+ * @param items - Array of items to hash
848
+ * @param keyExtractor - Function to extract key from each item
849
+ * @returns Hash string
850
+ */
851
+ static createArrayHash(items, keyExtractor) {
852
+ if (!Array.isArray(items))
853
+ return '';
854
+ return JSON.stringify(items.map(keyExtractor));
855
+ }
856
+ /**
857
+ * Safely filters an array with predicate function
858
+ * @param array - Array to filter
859
+ * @param predicate - Filter predicate function
860
+ * @returns Filtered array or empty array if input is invalid
861
+ */
862
+ static safeFilter(array, predicate) {
863
+ if (!Array.isArray(array))
864
+ return [];
865
+ return array.filter(predicate);
866
+ }
867
+ /**
868
+ * Safely maps an array with transform function
869
+ * @param array - Array to map
870
+ * @param transform - Transform function
871
+ * @returns Mapped array or empty array if input is invalid
872
+ */
873
+ static safeMap(array, transform) {
874
+ if (!Array.isArray(array))
875
+ return [];
876
+ return array.map(transform);
877
+ }
878
+ /**
879
+ * Safely finds an item in array
880
+ * @param array - Array to search
881
+ * @param predicate - Find predicate function
882
+ * @returns Found item or undefined
883
+ */
884
+ static safeFind(array, predicate) {
885
+ if (!Array.isArray(array))
886
+ return undefined;
887
+ return array.find(predicate);
888
+ }
889
+ /**
890
+ * Creates a Map from an array for O(1) lookups
891
+ * @param array - Array to convert
892
+ * @param keyExtractor - Function to extract key from each item
893
+ * @returns Map with keys and items
894
+ */
895
+ static createLookupMap(array, keyExtractor) {
896
+ const map = new Map();
897
+ if (!Array.isArray(array))
898
+ return map;
899
+ array.forEach(item => {
900
+ const key = keyExtractor(item);
901
+ map.set(key, item);
902
+ });
903
+ return map;
904
+ }
905
+ /**
906
+ * Checks if two arrays have the same items (order doesn't matter)
907
+ * @param array1 - First array
908
+ * @param array2 - Second array
909
+ * @param keyExtractor - Function to extract comparison key
910
+ * @returns True if arrays contain same items
911
+ */
912
+ static arraysEqual(array1, array2, keyExtractor) {
913
+ if (!Array.isArray(array1) || !Array.isArray(array2))
914
+ return false;
915
+ if (array1.length !== array2.length)
916
+ return false;
917
+ if (keyExtractor) {
918
+ const keys1 = array1.map(keyExtractor).sort();
919
+ const keys2 = array2.map(keyExtractor).sort();
920
+ return JSON.stringify(keys1) === JSON.stringify(keys2);
921
+ }
922
+ else {
923
+ return JSON.stringify([...array1].sort()) === JSON.stringify([...array2].sort());
924
+ }
925
+ }
926
+ /**
927
+ * Safely removes items from a Set based on a predicate
928
+ * @param set - Set to modify
929
+ * @param predicate - Function to determine if item should be removed
930
+ */
931
+ static removeFromSet(set, predicate) {
932
+ if (!(set instanceof Set))
933
+ return;
934
+ const itemsToRemove = [];
935
+ set.forEach(item => {
936
+ if (predicate(item)) {
937
+ itemsToRemove.push(item);
938
+ }
939
+ });
940
+ itemsToRemove.forEach(item => set.delete(item));
941
+ }
942
+ /**
943
+ * Safely clones an array to prevent mutation issues
944
+ * @param array - Array to clone
945
+ * @returns Cloned array or empty array if input is invalid
946
+ */
947
+ static cloneArray(array) {
948
+ if (!Array.isArray(array))
949
+ return [];
950
+ return [...array];
951
+ }
952
+ /**
953
+ * Performs safe property access with default value
954
+ * @param obj - Object to access
955
+ * @param path - Property path (e.g., 'user.profile.name')
956
+ * @param defaultValue - Default value if property doesn't exist
957
+ * @returns Property value or default
958
+ */
959
+ static getNestedProperty(obj, path, defaultValue = null) {
960
+ if (!obj || !path)
961
+ return defaultValue;
962
+ // If there is no '.', just return the direct property
963
+ if (!path.includes('.')) {
964
+ return obj[path] !== undefined ? obj[path] : defaultValue;
965
+ }
966
+ // Otherwise, traverse the nested properties
967
+ try {
968
+ return path.split('.').reduce((acc, part) => {
969
+ return acc && acc[part] !== undefined ? acc[part] : defaultValue;
970
+ }, obj);
971
+ }
972
+ catch {
973
+ return defaultValue;
974
+ }
975
+ }
976
+ }
977
+
978
+ /**
979
+ * Centralized URL and navigation utility helper.
980
+ * Provides common functions for URL manipulation and navigation.
981
+ */
982
+ class UrlHelper {
983
+ /**
984
+ * Extracts the home URL from current window location
985
+ * @returns Home URL path
986
+ */
987
+ static getHomeUrl() {
988
+ const pathname = window.location.pathname;
989
+ return `/${pathname.split('/')[1]}`;
990
+ }
991
+ /**
992
+ * Safely navigates to a URL if it's valid
993
+ * @param router - Angular Router instance
994
+ * @param url - URL to navigate to
995
+ * @returns Promise<boolean> - Navigation result
996
+ */
997
+ static safeNavigate(router, url) {
998
+ if (!url || typeof url !== 'string') {
999
+ return null;
1000
+ }
1001
+ try {
1002
+ return router.navigateByUrl(url);
1003
+ }
1004
+ catch (error) {
1005
+ console.warn('Navigation error:', error);
1006
+ return null;
1007
+ }
1008
+ }
1009
+ /**
1010
+ * Updates the browser URL without navigation using Location service
1011
+ * @param location - Angular Location service
1012
+ * @param baseUrl - Base URL path
1013
+ * @param queryString - Query string parameters
1014
+ */
1015
+ static updateUrl(location, baseUrl, queryString) {
1016
+ const newUrl = `${baseUrl}?${queryString}`;
1017
+ const currentUrl = window.location.pathname + window.location.search;
1018
+ if (currentUrl !== newUrl) {
1019
+ location.go(newUrl);
1020
+ }
1021
+ }
1022
+ /**
1023
+ * Builds a complete URL with query parameters
1024
+ * @param baseUrl - Base URL path
1025
+ * @param queryParams - URLSearchParams object
1026
+ * @returns Complete URL string
1027
+ */
1028
+ static buildUrl(baseUrl, queryParams) {
1029
+ const queryString = queryParams.toString();
1030
+ return queryString ? `${baseUrl}?${queryString}` : baseUrl;
1031
+ }
1032
+ /**
1033
+ * Gets the base URL without query parameters
1034
+ * @param router - Angular Router instance
1035
+ * @returns Base URL string
1036
+ */
1037
+ static getBaseUrl(router) {
1038
+ return router.url.split('?')[0];
1039
+ }
1040
+ /**
1041
+ * Checks if current URL differs from generated URL
1042
+ * @param generatedUrl - Generated URL to compare
1043
+ * @returns True if URLs are different
1044
+ */
1045
+ static hasUrlChanged(generatedUrl) {
1046
+ const currentUrl = window.location.pathname + window.location.search;
1047
+ return currentUrl !== generatedUrl;
1048
+ }
1049
+ /**
1050
+ * Extracts query parameters from a URL string
1051
+ * @param url - Full URL string
1052
+ * @returns URLSearchParams object
1053
+ */
1054
+ static extractQueryParams(url) {
1055
+ try {
1056
+ const urlObj = new URL(url);
1057
+ return new URLSearchParams(urlObj.search);
1058
+ }
1059
+ catch (error) {
1060
+ console.warn('Invalid URL for query param extraction:', url);
1061
+ return null;
1062
+ }
1063
+ }
1064
+ /**
1065
+ * Handles button click actions (URL navigation or callback execution)
1066
+ * @param router - Angular Router instance
1067
+ * @param config - Button configuration object
1068
+ * @param primaryUrlKey - Primary URL property name (default: 'btnUrl')
1069
+ * @param primaryClickKey - Primary click handler property name (default: 'btnClick')
1070
+ */
1071
+ static handleButtonClick(router, config, primaryUrlKey = 'btnUrl', primaryClickKey = 'btnClick') {
1072
+ if (!config)
1073
+ return;
1074
+ // Try callback first
1075
+ if (config[primaryClickKey] && typeof config[primaryClickKey] === 'function') {
1076
+ try {
1077
+ config[primaryClickKey]();
1078
+ }
1079
+ catch (error) {
1080
+ console.warn('Error executing button callback:', error);
1081
+ }
1082
+ }
1083
+ // Fallback to URL navigation
1084
+ else if (config[primaryUrlKey]) {
1085
+ this.safeNavigate(router, config[primaryUrlKey]);
1086
+ }
1087
+ }
1088
+ /**
1089
+ * Handles secondary button click actions
1090
+ * @param router - Angular Router instance
1091
+ * @param config - Button configuration object
1092
+ */
1093
+ static handleSecondaryButtonClick(router, config) {
1094
+ this.handleButtonClick(router, config, 'secondBtnUrl', 'secondBtnClick');
1095
+ }
1096
+ /**
1097
+ * Validates if a URL string is properly formatted
1098
+ * @param url - URL to validate
1099
+ * @returns True if URL is valid
1100
+ */
1101
+ static isValidUrl(url) {
1102
+ if (!url || typeof url !== 'string')
1103
+ return false;
1104
+ try {
1105
+ // Allow relative URLs starting with '/'
1106
+ if (url.startsWith('/'))
1107
+ return true;
1108
+ // Validate absolute URLs
1109
+ new URL(url);
1110
+ return true;
1111
+ }
1112
+ catch {
1113
+ return false;
1114
+ }
1115
+ }
1116
+ /**
1117
+ * Safely encodes URL parameters
1118
+ * @param value - Value to encode
1119
+ * @returns Encoded string
1120
+ */
1121
+ static encodeParam(value) {
1122
+ if (value === null || value === undefined)
1123
+ return '';
1124
+ return encodeURIComponent(String(value));
1125
+ }
1126
+ }
1127
+
169
1128
  class ScrollingDirective {
170
1129
  el;
171
1130
  constructor(el) {
@@ -924,6 +1883,20 @@ class TisSmartTableViewerComponent {
924
1883
  search = '';
925
1884
  searchCtrl = new FormControl();
926
1885
  _onDestroy = new Subject();
1886
+ // Additional subscriptions that need cleanup
1887
+ _selectionSubscription;
1888
+ _handsetSubscription;
1889
+ _queryParamsSubscription;
1890
+ // Memory-efficient caching
1891
+ _columnMappingCache = new Map();
1892
+ _displayedColumnsCache = [];
1893
+ _lastColumnsCodeMappingHash = '';
1894
+ // Race condition prevention
1895
+ _currentRequestSubject = new Subject();
1896
+ // Timeout management for proper cleanup - prevent memory leaks
1897
+ timeoutManager = new TimeoutManager();
1898
+ // Computed row backgrounds for optimal performance
1899
+ computedRowBackgrounds = new Map();
927
1900
  dataSource;
928
1901
  _sort;
929
1902
  _sortSubscription;
@@ -970,6 +1943,8 @@ class TisSmartTableViewerComponent {
970
1943
  isExpandedRow = false;
971
1944
  expandedTemplate;
972
1945
  isAllExpanded = false;
1946
+ // Expansion state management - avoid direct mutation
1947
+ expandedRowIds = new Set();
973
1948
  isHandset$;
974
1949
  isMobile = false;
975
1950
  constructor(
@@ -981,82 +1956,48 @@ class TisSmartTableViewerComponent {
981
1956
  this.router = router;
982
1957
  this.location = location;
983
1958
  this.breakpointObserver = breakpointObserver;
984
- this.selection.changed.subscribe(change => {
985
- change.added.forEach(item => this.selectedIds.add(item['id']));
986
- change.removed.forEach(item => this.selectedIds.delete(item['id']));
1959
+ // Store subscription reference for proper cleanup
1960
+ this._selectionSubscription = this.selection.changed.subscribe(change => {
1961
+ change.added.forEach(item => {
1962
+ if (item && item[this.selectedRowKey] !== undefined) {
1963
+ this.selectedIds.add(item[this.selectedRowKey]);
1964
+ }
1965
+ });
1966
+ change.removed.forEach(item => {
1967
+ if (item && item[this.selectedRowKey] !== undefined) {
1968
+ this.selectedIds.delete(item[this.selectedRowKey]);
1969
+ }
1970
+ });
987
1971
  });
988
1972
  }
989
1973
  ngOnInit() {
990
1974
  this.isHandset$ = this.breakpointObserver.observe([Breakpoints.Handset])
991
- .pipe(map(result => {
992
- console.log("== result ==", result);
993
- return result.matches;
994
- }), shareReplay());
995
- this.isHandset$.subscribe(r => {
996
- console.log('IS HANDSET:', r);
1975
+ .pipe(map(result => result.matches), shareReplay());
1976
+ this._handsetSubscription = this.isHandset$.subscribe(r => {
997
1977
  this.isMobile = r;
998
1978
  });
999
1979
  this.setDefaultColumns();
1000
1980
  this.getHomeUrl();
1001
- this.route.queryParams.subscribe(qp => {
1981
+ this._queryParamsSubscription = this.route.queryParams.subscribe(qp => {
1982
+ // Initialize objects
1002
1983
  this.filterFromQueryParams = {};
1003
1984
  this.sortFromQueryParams = {};
1004
1985
  if (this.keepFilterInUrl) {
1005
- for (const key in qp) {
1006
- if (qp.hasOwnProperty(key) && qp[key] && qp[key] != '' && qp[key] != 'null' && qp[key] != 'undefined') {
1007
- let fixedKeyMatched = false;
1008
- if (key.toLowerCase() === 'pageIndex'.toLowerCase()) {
1009
- this.pageIndex = Number(qp[key]);
1010
- fixedKeyMatched = true;
1011
- }
1012
- if (key.toLowerCase() === 'pageSize'.toLowerCase()) {
1013
- this.pageSize = Number(qp[key]);
1014
- fixedKeyMatched = true;
1015
- }
1016
- if (key.toLowerCase() === 'sortBy'.toLowerCase()) {
1017
- this.sortFromQueryParams.sortBy = qp[key];
1018
- fixedKeyMatched = true;
1019
- }
1020
- if (key.toLowerCase() === 'sortOrder'.toLowerCase()) {
1021
- this.sortFromQueryParams.sortOrder = qp[key];
1022
- fixedKeyMatched = true;
1023
- }
1024
- if (key.toLowerCase() === 'search'.toLowerCase()) {
1025
- this.search = qp[key];
1026
- this.searchCtrl.patchValue(this.search);
1027
- fixedKeyMatched = true;
1028
- }
1029
- if (key.toLowerCase().includes('date') && qp[key].length == 13) { // To Check if it is a date
1030
- // this.filterFromQueryParams[key] = moment(Number(qp[key]));
1031
- this.filterFromQueryParams[key] = DateTime.fromMillis(Number(qp[key]));
1032
- fixedKeyMatched = true;
1033
- }
1034
- if (!fixedKeyMatched) {
1035
- if ((qp[key]).includes(',')) {
1036
- this.filterFromQueryParams[key] = (qp[key]).split(',');
1037
- }
1038
- else {
1039
- this.filterFromQueryParams[key] = qp[key];
1040
- }
1041
- }
1042
- // Transform Data, before patching in filter Form
1043
- let mapping = this.columnsCodeMapping.find(ccm => ccm.filterFormKey == key);
1044
- if (mapping?.transformQueryParamFn) {
1045
- this.filterFromQueryParams[key] = mapping.transformQueryParamFn(this.filterFromQueryParams[key]);
1046
- }
1047
- }
1048
- }
1986
+ const { filterParams, sortParams, pageIndex, pageSize, search } = QueryParamsHelper.processForFilters(qp, this.columnsCodeMapping);
1987
+ this.filterFromQueryParams = filterParams;
1988
+ this.sortFromQueryParams = sortParams;
1989
+ this.pageIndex = pageIndex;
1990
+ this.pageSize = pageSize;
1991
+ this.search = search;
1992
+ this.searchCtrl.patchValue(this.search);
1049
1993
  this.filterFormGroup.patchValue(this.filterFromQueryParams);
1050
- if (this.sortFromQueryParams && this.sortFromQueryParams.sortBy && this.sortFromQueryParams.sortOrder) {
1994
+ if (ValidationHelper.hasProperty(this.sortFromQueryParams, 'sortBy') &&
1995
+ ValidationHelper.hasProperty(this.sortFromQueryParams, 'sortOrder')) {
1051
1996
  this.sortObj = this.sortFromQueryParams;
1052
- console.log('[table-list-view-wrapper]: Emitting Sort Obj from QP to parent component:', this.sortFromQueryParams);
1053
1997
  this.sortObjChange.emit(this.sortObj);
1054
1998
  }
1055
1999
  }
1056
- let filterHasNonEmptyValue = Object.values(this.filterFromQueryParams).some(value => value !== null && value !== undefined && value !== '');
1057
- if (filterHasNonEmptyValue) {
1058
- this.filterApplied = true;
1059
- }
2000
+ this.filterApplied = ValidationHelper.hasNonEmptyValue(this.filterFromQueryParams);
1060
2001
  this.getList();
1061
2002
  });
1062
2003
  this.searchCtrl.valueChanges
@@ -1070,11 +2011,9 @@ class TisSmartTableViewerComponent {
1070
2011
  ngOnChanges(changes) {
1071
2012
  // console.log(`[table-list-view-wrapper]: ngOnChanges:`, changes);
1072
2013
  if (changes['defaultDisplayedColumns']) {
1073
- console.log(`[table-list-view-wrapper]: changes['defaultDisplayedColumns']:`, changes['defaultDisplayedColumns']);
1074
2014
  this.handleDisplayedColumns();
1075
2015
  }
1076
2016
  if (changes['columnsCodeMapping']) {
1077
- console.log(`[table-list-view-wrapper]: changes['columnsCodeMapping']:`, changes['columnsCodeMapping']);
1078
2017
  this.columnsCodeMapping = changes['columnsCodeMapping'].currentValue;
1079
2018
  this.handleDisplayedColumns();
1080
2019
  this.columns = this.columnsCodeMapping.map(c => c.name);
@@ -1097,7 +2036,6 @@ class TisSmartTableViewerComponent {
1097
2036
  }
1098
2037
  if (changes['loadDataApiBaseUrl']) {
1099
2038
  if (changes['loadDataApiBaseUrl'].currentValue) {
1100
- console.log(`[table-list-view-wrapper]: Datasource changes['loadDataApiBaseUrl'].currentValue:`, changes['loadDataApiBaseUrl'].currentValue);
1101
2039
  if (this.loadingSubscription) {
1102
2040
  this.loadingSubscription.unsubscribe();
1103
2041
  }
@@ -1105,14 +2043,16 @@ class TisSmartTableViewerComponent {
1105
2043
  this.dataLengthSubscription.unsubscribe();
1106
2044
  }
1107
2045
  this.dataSource = new ApiDataSource(this.apiService);
1108
- console.log('[table-list-view-wrapper]: Datasource Initialized:', this.dataSource);
1109
2046
  this.loadingSubscription = this.dataSource.loading$.subscribe(loading => {
1110
- console.log('[table-list-view-wrapper]: dataSource loading:', loading);
1111
2047
  if (!loading) {
1112
2048
  if (this._paginator) {
1113
2049
  this._paginator.pageIndex = this.pageIndex;
1114
2050
  this._paginator.pageSize = this.pageSize;
1115
2051
  }
2052
+ // Clear background cache when new data arrives
2053
+ this.clearRowBackgroundCache();
2054
+ // Pre-compute all row backgrounds for optimal performance
2055
+ this.computeAllRowBackgrounds();
1116
2056
  this.checkAllRowsSelected();
1117
2057
  this.onDataLoaded.emit(true);
1118
2058
  this.onSetExtraData.emit(this.dataSource.extraDataSubject.value);
@@ -1124,7 +2064,6 @@ class TisSmartTableViewerComponent {
1124
2064
  }
1125
2065
  });
1126
2066
  this.dataLengthSubscription = this.dataSource.totalDataLength$.subscribe((total) => {
1127
- console.log('[table-list-view-wrapper]: dataSource total:', total);
1128
2067
  if (total !== null) {
1129
2068
  this.initialLoading = false;
1130
2069
  this.onSetTotal.emit(total);
@@ -1139,7 +2078,7 @@ class TisSmartTableViewerComponent {
1139
2078
  }
1140
2079
  this.filterFormGroupSubscription = this.filterFormGroup.valueChanges
1141
2080
  .pipe(takeUntil(this._onDestroy), distinctUntilChanged()).subscribe(val => {
1142
- this.filterHasNonEmptyValue = Object.values(val).some(value => value !== null && value !== undefined && value !== '');
2081
+ this.filterHasNonEmptyValue = ValidationHelper.hasNonEmptyValue(val);
1143
2082
  });
1144
2083
  }
1145
2084
  if (changes['selectedRows']) {
@@ -1163,12 +2102,42 @@ class TisSmartTableViewerComponent {
1163
2102
  }
1164
2103
  }
1165
2104
  ngOnDestroy() {
2105
+ // Complete the destroy subject first to trigger takeUntil operators
2106
+ this._onDestroy.next();
2107
+ this._onDestroy.complete();
2108
+ // Clean up all subscriptions
1166
2109
  this._sortSubscription?.unsubscribe();
1167
2110
  this._paginatorSubscription?.unsubscribe();
1168
2111
  this.loadingSubscription?.unsubscribe();
1169
2112
  this.dataLengthSubscription?.unsubscribe();
1170
2113
  this.filterFormGroupSubscription?.unsubscribe();
1171
- // this.dataSource.disconnect({} as CollectionViewer); // stops API calls
2114
+ // Clean up additional subscriptions
2115
+ this._selectionSubscription?.unsubscribe();
2116
+ this._handsetSubscription?.unsubscribe();
2117
+ this._queryParamsSubscription?.unsubscribe();
2118
+ // Clean up selection model and data structures using CollectionHelper
2119
+ this.selection.clear();
2120
+ CollectionHelper.clearSet(this.selectedIds);
2121
+ CollectionHelper.clearSet(this.expandedRowIds);
2122
+ // Clear arrays to free memory using CollectionHelper
2123
+ CollectionHelper.clearArray(this.selectedFilterValues);
2124
+ CollectionHelper.clearArray(this.finalSelectedFilterValuesToDisplay);
2125
+ CollectionHelper.clearArray(this.selectedFilterGroupedValues);
2126
+ CollectionHelper.clearArray(this.displayedColumns);
2127
+ // Clear caches to free memory
2128
+ CollectionHelper.clearMap(this._columnMappingCache);
2129
+ CollectionHelper.clearArray(this._displayedColumnsCache);
2130
+ this._lastColumnsCodeMappingHash = '';
2131
+ CollectionHelper.clearMap(this.computedRowBackgrounds);
2132
+ // Complete race condition prevention subject
2133
+ this._currentRequestSubject.next();
2134
+ this._currentRequestSubject.complete();
2135
+ // Clear all pending timeouts to prevent memory leaks
2136
+ this.timeoutManager.clearAll();
2137
+ // Disconnect data source to stop API calls and complete observables
2138
+ if (this.dataSource) {
2139
+ this.dataSource.disconnect({});
2140
+ }
1172
2141
  }
1173
2142
  setDefaultColumns() {
1174
2143
  if (this.defaultDisplayedColumns && this.defaultDisplayedColumns.length) {
@@ -1179,21 +2148,91 @@ class TisSmartTableViewerComponent {
1179
2148
  }
1180
2149
  }
1181
2150
  handleDisplayedColumns() {
1182
- if (this.defaultDisplayedColumns && this.defaultDisplayedColumns.length) {
1183
- const columnsSet = new Set(this.columnsCodeMapping.map(ccm => ccm.name));
1184
- this.displayedColumns = this.defaultDisplayedColumns.filter(c => columnsSet.has(c));
2151
+ // Create a hash of current columns to check if cache is valid
2152
+ const columnsHash = JSON.stringify(this.columnsCodeMapping.map(c => c.name));
2153
+ // Use cache if columns haven't changed
2154
+ if (this._lastColumnsCodeMappingHash === columnsHash && this._displayedColumnsCache.length > 0) {
2155
+ this.displayedColumns = [...this._displayedColumnsCache];
1185
2156
  }
1186
2157
  else {
1187
- this.displayedColumns = this.columnsCodeMapping.map(c => c?.columnDef || c.name);
2158
+ // Update cache
2159
+ this.updateColumnMappingCache();
2160
+ this._lastColumnsCodeMappingHash = columnsHash;
2161
+ if (this.defaultDisplayedColumns && this.defaultDisplayedColumns.length) {
2162
+ this.displayedColumns = this.defaultDisplayedColumns.filter(c => this._columnMappingCache.has(c));
2163
+ }
2164
+ else {
2165
+ this.displayedColumns = this.columnsCodeMapping.map(c => c?.columnDef || c.name);
2166
+ }
2167
+ // Cache the result before adding selection/drag columns
2168
+ this._displayedColumnsCache = [...this.displayedColumns];
1188
2169
  }
2170
+ // Add selection and drag columns (these are dynamic and shouldn't be cached)
2171
+ const finalColumns = [...this.displayedColumns];
1189
2172
  if (this.enableRowsSelection) {
1190
- this.displayedColumns = ['Select', ...this.displayedColumns];
2173
+ finalColumns.unshift('Select');
1191
2174
  }
1192
2175
  if (this.enableDragNDrop) {
1193
- this.displayedColumns = ['drag', ...this.displayedColumns];
2176
+ finalColumns.unshift('drag');
1194
2177
  }
2178
+ this.displayedColumns = finalColumns;
1195
2179
  this.displayedColumnsChange.emit(this.displayedColumns);
1196
2180
  }
2181
+ updateColumnMappingCache() {
2182
+ this._columnMappingCache.clear();
2183
+ this.columnsCodeMapping.forEach(column => {
2184
+ this._columnMappingCache.set(column.name, column);
2185
+ });
2186
+ }
2187
+ // TrackBy functions for optimal rendering performance
2188
+ trackByBreadcrumb(index, breadcrumb) {
2189
+ return breadcrumb.url + breadcrumb.name || index.toString();
2190
+ }
2191
+ trackByFilterValue(index, filterValue) {
2192
+ return `${filterValue.formControlName}_${filterValue.valueKey}_${filterValue.value}`;
2193
+ }
2194
+ trackByAutoColumn(index, column) {
2195
+ return column.name + (column.serverKeyCode || '');
2196
+ }
2197
+ trackByTemplateColumn(index, column) {
2198
+ return column.name + (column.serverKeyCode || '');
2199
+ }
2200
+ trackByTableRow(index, row) {
2201
+ return row.id || row[this.selectedRowKey] || index;
2202
+ }
2203
+ // Helper method to get consistent row identifier for expansion tracking
2204
+ getRowIdentifier(row) {
2205
+ return CollectionHelper.getRowIdentifier(row, 'id', this.selectedRowKey);
2206
+ }
2207
+ // Helper method to check if a row is expanded (non-mutating)
2208
+ isRowExpanded(row) {
2209
+ if (!this.isExpansion)
2210
+ return false;
2211
+ const rowId = this.getRowIdentifier(row);
2212
+ return this.expandedRowIds.has(rowId);
2213
+ }
2214
+ // Clear background cache when data changes to ensure fresh calculations
2215
+ clearRowBackgroundCache() {
2216
+ this.computedRowBackgrounds.clear();
2217
+ }
2218
+ // Compute all row backgrounds when data changes (runs once per data load)
2219
+ computeAllRowBackgrounds() {
2220
+ if (!this.dataSource?.apiSubject.value || !this.rowsConfig.backgroundApplyFunction) {
2221
+ return;
2222
+ }
2223
+ this.computedRowBackgrounds.clear();
2224
+ this.dataSource.apiSubject.value.forEach((row) => {
2225
+ const rowId = row?.id || row?.[this.selectedRowKey] || JSON.stringify(row);
2226
+ try {
2227
+ const background = this.rowsConfig.backgroundApplyFunction(row);
2228
+ this.computedRowBackgrounds.set(rowId, background);
2229
+ }
2230
+ catch (error) {
2231
+ console.warn('Error computing row background:', error);
2232
+ this.computedRowBackgrounds.set(rowId, null);
2233
+ }
2234
+ });
2235
+ }
1197
2236
  handleSortingChanges(ch) {
1198
2237
  this.sortObj = { sortOrder: ch.direction, sortBy: this.columnsCodeMapping.find(c => c.name === ch.active)?.serverKeyCode };
1199
2238
  this.sortFromQueryParams.sortBy = this.sortObj.sortBy;
@@ -1202,90 +2241,30 @@ class TisSmartTableViewerComponent {
1202
2241
  this.getList();
1203
2242
  }
1204
2243
  getHomeUrl() {
1205
- let pathname = window.location.pathname;
1206
- // console.log("=== app-table-list-view-wrapper :: pathname ===", pathname);
1207
- this.homeUrl = `/${pathname.split('/')[1]}`;
2244
+ this.homeUrl = UrlHelper.getHomeUrl();
1208
2245
  }
1209
2246
  getNestedValue(obj, path) {
1210
- if (!path)
1211
- return null;
1212
- // If there is no '.', just return the direct property
1213
- if (!path.includes('.')) {
1214
- return obj && obj[path] ? obj[path] : null;
1215
- }
1216
- // Otherwise, traverse the nested properties
1217
- return path.split('.').reduce((acc, part) => acc && acc[part], obj);
2247
+ return CollectionHelper.getNestedProperty(obj, path);
1218
2248
  }
1219
2249
  groupByFormControlAttributes(data) {
1220
- const groups = {};
1221
- data.forEach(item => {
1222
- if (item.formControlType == 'input') {
1223
- // Do Nothing...
1224
- }
1225
- if (item.formControlType == 'checkbox') {
1226
- // Do Nothing...
1227
- }
1228
- if (item.formControlType == 'date') {
1229
- item.valueKey = DateTime.fromJSDate(item.value).toFormat('dd-MM-yyyy');
1230
- }
1231
- if (item.formControlType == 'date-time') {
1232
- item.valueKey = DateTime.fromJSDate(item.value).toFormat('dd-MM-yyyy HH:mm');
1233
- }
1234
- const key = `${item.formControlName}-${item.formControlType}`;
1235
- if (!groups[key]) {
1236
- groups[key] = {
1237
- formControlName: item.formControlName,
1238
- formControlType: item.formControlType,
1239
- arrValues: []
1240
- };
1241
- }
1242
- const isSingleValue = item.isSingleValue ?? ['input', 'radio', 'date', 'date-time', 'toggle'].includes(item.formControlType);
1243
- // Check if only the last value should be kept due to isSingleValue or duplicated value/valueKey
1244
- if (isSingleValue) {
1245
- groups[key].arrValues = [item]; // Replace with the current item
1246
- }
1247
- else {
1248
- // Check for duplicate value and valueKey in the current array
1249
- const existingIndex = groups[key].arrValues.findIndex(x => x.value === item.value && x.valueKey === item.valueKey);
1250
- if (existingIndex !== -1) {
1251
- groups[key].arrValues[existingIndex] = item; // Replace the duplicate
1252
- }
1253
- else {
1254
- groups[key].arrValues.push(item); // Add new item
1255
- }
1256
- }
1257
- });
1258
- return Object.values(groups);
2250
+ return FilterDisplayHelper.groupByFormControlAttributes(data);
1259
2251
  }
1260
2252
  updateSelectedFilterValues(values) {
1261
2253
  let currentFormControlName;
1262
2254
  if (Array.isArray(values)) {
1263
- this.selectedFilterGroupedValues = this.groupByFormControlAttributes(values);
1264
2255
  currentFormControlName = values[0]?.formControlName;
1265
2256
  }
1266
2257
  else {
1267
2258
  currentFormControlName = values?.formControlName;
1268
- this.selectedFilterGroupedValues = this.groupByFormControlAttributes([values]);
1269
2259
  }
1270
- this.selectedFilterValues = this.selectedFilterValues.filter(sfv => sfv.formControlName != currentFormControlName);
1271
- this.selectedFilterGroupedValues.forEach(gv => {
1272
- if (gv.formControlName = currentFormControlName) {
1273
- gv.arrValues.forEach(v => {
1274
- this.selectedFilterValues.push(v);
1275
- });
1276
- }
1277
- });
2260
+ const result = FilterDisplayHelper.updateSelectedFilterValues(this.selectedFilterValues, values, currentFormControlName);
2261
+ this.selectedFilterValues = result.selectedFilterValues;
2262
+ this.selectedFilterGroupedValues = result.selectedFilterGroupedValues;
1278
2263
  this.displayAfterFilterRemoved = true;
1279
- // this.filterFromQueryParams
1280
2264
  this.getFinalSelectedFilterValuesToDisplay();
1281
2265
  }
1282
2266
  getFinalSelectedFilterValuesToDisplay() {
1283
- this.finalSelectedFilterValuesToDisplay = [];
1284
- this.selectedFilterValues.forEach(sf => {
1285
- if (Object.keys(this.filterFromQueryParams).includes(sf.formControlName)) {
1286
- this.finalSelectedFilterValuesToDisplay.push(sf);
1287
- }
1288
- });
2267
+ this.finalSelectedFilterValuesToDisplay = FilterDisplayHelper.getValuesForDisplay(this.selectedFilterValues, this.filterFromQueryParams);
1289
2268
  }
1290
2269
  removeParticularFilter(f) {
1291
2270
  let val = this.filterFormGroup.get(f.formControlName)?.value;
@@ -1296,23 +2275,27 @@ class TisSmartTableViewerComponent {
1296
2275
  else {
1297
2276
  this.filterFormGroup.get(f.formControlName)?.reset();
1298
2277
  }
1299
- this.selectedFilterValues = this.selectedFilterValues.filter(sfv => !(sfv.formControlName == f.formControlName && sfv.valueKey == f.valueKey));
2278
+ this.selectedFilterValues = FilterDisplayHelper.removeFilterValue(this.selectedFilterValues, f);
1300
2279
  this.displayAfterFilterRemoved = true;
1301
- setTimeout(() => {
2280
+ this.timeoutManager.createTimeout(() => {
1302
2281
  this.filterRecords();
1303
2282
  }, 500);
1304
2283
  }
1305
2284
  filterRecords() {
1306
2285
  this.filterApplied = true;
1307
2286
  this.resetFlag = true;
1308
- setTimeout(() => {
2287
+ // Clear computed backgrounds before loading filtered data
2288
+ this.clearRowBackgroundCache();
2289
+ this.timeoutManager.createTimeout(() => {
1309
2290
  this.getList(true);
1310
2291
  this.isShowFilter = false;
1311
2292
  }, 500);
1312
2293
  }
1313
2294
  resetFilters() {
1314
2295
  this.filterApplied = false;
1315
- setTimeout(() => {
2296
+ // Clear computed backgrounds before reset
2297
+ this.clearRowBackgroundCache();
2298
+ this.timeoutManager.createTimeout(() => {
1316
2299
  this.resetFlag = true;
1317
2300
  this.filterFromQueryParams = {};
1318
2301
  this.sortFromQueryParams = {};
@@ -1322,43 +2305,15 @@ class TisSmartTableViewerComponent {
1322
2305
  }, 250);
1323
2306
  }
1324
2307
  getList(forceFromObject = false) {
2308
+ // Cancel any previous request to prevent race conditions
2309
+ this._currentRequestSubject.next();
1325
2310
  this.isAllExpanded = false;
2311
+ // Clear expansion state when loading new data to avoid stale expansion state
2312
+ CollectionHelper.clearSet(this.expandedRowIds);
1326
2313
  const filterFormData = this.filterFormGroup?.value;
1327
- let qs = new URLSearchParams();
1328
- let filter = { ...filterFormData };
1329
- if (filterFormData) {
1330
- this.filterHasNonEmptyValue = Object.values(filterFormData).some(value => value !== null && value !== undefined && value !== '');
1331
- }
1332
- else {
1333
- this.filterHasNonEmptyValue = false;
1334
- }
1335
- for (const key in filter) {
1336
- if (typeof filter[key] === 'object' && (filter[key] instanceof Date || DateTime.isDateTime(filter[key]))) {
1337
- if (filter[key] instanceof Date) {
1338
- filter[key] = DateTime.fromJSDate(filter[key]).toMillis();
1339
- }
1340
- else if (DateTime.isDateTime(filter[key])) {
1341
- filter[key] = filter[key].toMillis();
1342
- }
1343
- }
1344
- }
1345
- // Append All Filters from filter form
1346
- Object.keys(filter).forEach(key => {
1347
- if (filter[key] != null && filter[key] != '' && filter[key] != 'null' && filter[key] != 'undefined') {
1348
- if (filter[key] === '*') {
1349
- filter[key] = '';
1350
- }
1351
- qs.append(key, filter[key]);
1352
- }
1353
- });
1354
- // Append sorting conditions...
1355
- if (this.sortFromQueryParams) {
1356
- Object.keys(this.sortFromQueryParams).forEach(key => {
1357
- if (this.sortFromQueryParams[key] != null && this.sortFromQueryParams[key] != '' && this.sortFromQueryParams[key] != 'null' && this.sortFromQueryParams[key] != 'undefined') {
1358
- qs.append(key, this.sortFromQueryParams[key]);
1359
- }
1360
- });
1361
- }
2314
+ this.filterHasNonEmptyValue = ValidationHelper.hasFormData(filterFormData);
2315
+ // Build query string using helper
2316
+ const qs = QueryParamsHelper.buildQueryString(filterFormData, this.sortFromQueryParams, this.resetFlag ? 0 : this.pageIndex, this.pageSize, this.search);
1362
2317
  if (this.resetFlag) {
1363
2318
  this.pageIndex = 0;
1364
2319
  }
@@ -1366,33 +2321,31 @@ class TisSmartTableViewerComponent {
1366
2321
  this._paginator.pageIndex = this.pageIndex;
1367
2322
  this._paginator.pageSize = this.pageSize;
1368
2323
  }
1369
- qs.append("pageIndex", this.pageIndex);
1370
- qs.append("pageSize", this.pageSize);
1371
- if (this.search != '') {
1372
- qs.append('search', this.search);
2324
+ // Update URL if needed
2325
+ const baseUrl = UrlHelper.getBaseUrl(this.router);
2326
+ const genUrl = UrlHelper.buildUrl(baseUrl, qs);
2327
+ if (this.keepFilterInUrl && UrlHelper.hasUrlChanged(genUrl)) {
2328
+ UrlHelper.updateUrl(this.location, baseUrl, qs.toString());
2329
+ this.filterFromQueryParams = QueryParamsHelper.parseQueryParams(window.location.href);
1373
2330
  }
1374
- qs = qs.toString();
1375
- let genUrl = this.router.url.split('?')[0] + '?' + qs;
1376
- let currentUrl = window.location.pathname + window.location.search;
1377
- if (currentUrl != genUrl) {
1378
- if (this.keepFilterInUrl) {
1379
- this.location.go(genUrl);
1380
- this.filterFromQueryParams = this.getQueryParams(window.location.href);
1381
- }
1382
- }
1383
- else { }
1384
- this.dataSource.load(this.loadDataApiBaseUrl, this.pageIndex, this.pageSize, this.search, filter, this.sortObj);
2331
+ // Load data with race condition protection
2332
+ this.dataSource.loadWithCancellation(this.loadDataApiBaseUrl, this.pageIndex, this.pageSize, this.search, filterFormData, // Pass original form data - datasource will handle conversions
2333
+ this.sortObj, this._currentRequestSubject);
1385
2334
  this.getFinalSelectedFilterValuesToDisplay();
1386
2335
  this.resetFlag = false;
1387
2336
  }
1388
2337
  onPaginationChanges() {
1389
2338
  if (this.pageIndex != this._paginator.pageIndex) {
1390
2339
  this.pageIndex = this._paginator.pageIndex;
2340
+ // Clear computed backgrounds before loading new page data
2341
+ this.clearRowBackgroundCache();
1391
2342
  this.getList();
1392
2343
  this.pageIndexChange.emit(this.pageIndex);
1393
2344
  }
1394
2345
  if (this.pageSize != this._paginator.pageSize) {
1395
2346
  this.pageSize = this._paginator.pageSize;
2347
+ // Clear computed backgrounds before loading new page size data
2348
+ this.clearRowBackgroundCache();
1396
2349
  this.getList();
1397
2350
  this.pageSizeChange.emit(this.pageSize);
1398
2351
  setToLocalStorageWithExpiry('user_pagination_page_size', this.pageSize, 1000 * 60 * 60 * 24 * 15);
@@ -1409,9 +2362,7 @@ class TisSmartTableViewerComponent {
1409
2362
  this.endStickyColumnCount = columnNumber;
1410
2363
  }
1411
2364
  goToUrl(url) {
1412
- if (url) {
1413
- this.router.navigateByUrl(url);
1414
- }
2365
+ UrlHelper.safeNavigate(this.router, url);
1415
2366
  }
1416
2367
  toggleSelection(status, row) {
1417
2368
  if (this.onlySingleSelection && status.checked) {
@@ -1443,28 +2394,11 @@ class TisSmartTableViewerComponent {
1443
2394
  $event.stopPropagation();
1444
2395
  }
1445
2396
  isChecked(row) {
1446
- return this.selectedIds.has(row['id']);
2397
+ return ValidationHelper.hasRowKey(row, this.selectedRowKey) &&
2398
+ this.selectedIds.has(row[this.selectedRowKey]);
1447
2399
  }
1448
2400
  getQueryParams(url) {
1449
- const urlObj = new URL(url);
1450
- const params = new URLSearchParams(urlObj.search);
1451
- const paramsObj = {};
1452
- params.forEach((value, key) => {
1453
- // Check if the parameter already exists (for handling multiple values)
1454
- if (paramsObj.hasOwnProperty(key)) {
1455
- // If it's not already an array, convert it to an array
1456
- if (!Array.isArray(paramsObj[key])) {
1457
- paramsObj[key] = [paramsObj[key]]; // Cast as string because we know it's not an array here
1458
- }
1459
- // Push the new value to the existing array
1460
- paramsObj[key].push(value); // Cast as string[] to use array methods
1461
- }
1462
- else {
1463
- // Assign the value to the key in the object
1464
- paramsObj[key] = value;
1465
- }
1466
- });
1467
- return paramsObj;
2401
+ return QueryParamsHelper.parseQueryParams(url);
1468
2402
  }
1469
2403
  isStickyStart(columnName) {
1470
2404
  const index = this.displayedColumns.indexOf(columnName);
@@ -1498,10 +2432,26 @@ class TisSmartTableViewerComponent {
1498
2432
  }
1499
2433
  }
1500
2434
  }
2435
+ // Optimized getRowBackground - simple O(1) lookup
1501
2436
  getRowBackground(row) {
1502
- return this.rowsConfig.backgroundApplyFunction
1503
- ? this.rowsConfig.backgroundApplyFunction(row)
1504
- : null;
2437
+ // Early return if no background function is provided
2438
+ if (!this.rowsConfig.backgroundApplyFunction) {
2439
+ return null;
2440
+ }
2441
+ const rowId = row?.id || row?.[this.selectedRowKey] || JSON.stringify(row);
2442
+ // If not computed yet, compute on-demand (fallback)
2443
+ if (!this.computedRowBackgrounds.has(rowId)) {
2444
+ try {
2445
+ const background = this.rowsConfig.backgroundApplyFunction(row);
2446
+ this.computedRowBackgrounds.set(rowId, background);
2447
+ return background;
2448
+ }
2449
+ catch (error) {
2450
+ console.warn('Error computing row background:', error);
2451
+ return null;
2452
+ }
2453
+ }
2454
+ return this.computedRowBackgrounds.get(rowId) || null;
1505
2455
  }
1506
2456
  drop(event) {
1507
2457
  // Ignore if the item was dropped at the same index
@@ -1521,20 +2471,10 @@ class TisSmartTableViewerComponent {
1521
2471
  this.listDataSequenceChange.emit(currentData);
1522
2472
  }
1523
2473
  handleButtonClick(config) {
1524
- if (config?.btnClick) {
1525
- config.btnClick();
1526
- }
1527
- else if (config?.btnUrl) {
1528
- this.goToUrl(config.btnUrl);
1529
- }
2474
+ UrlHelper.handleButtonClick(this.router, config);
1530
2475
  }
1531
2476
  handleSecondButtonClick(config) {
1532
- if (config?.secondBtnClick) {
1533
- config.secondBtnClick();
1534
- }
1535
- else if (config?.secondBtnUrl) {
1536
- this.goToUrl(config.secondBtnUrl);
1537
- }
2477
+ UrlHelper.handleSecondaryButtonClick(this.router, config);
1538
2478
  }
1539
2479
  setSelectedRows() {
1540
2480
  this.selection.clear();
@@ -1554,29 +2494,40 @@ class TisSmartTableViewerComponent {
1554
2494
  }
1555
2495
  /** Toggles the expanded state of an element. */
1556
2496
  toggleExpand(element) {
1557
- if (this.isExpansion) {
1558
- if (!element?.expanded) {
1559
- element.expanded = true;
1560
- }
1561
- else {
1562
- element.expanded = false;
1563
- }
2497
+ if (!this.isExpansion || !element) {
2498
+ return;
2499
+ }
2500
+ const rowId = this.getRowIdentifier(element);
2501
+ if (this.expandedRowIds.has(rowId)) {
2502
+ this.expandedRowIds.delete(rowId);
2503
+ }
2504
+ else {
2505
+ this.expandedRowIds.add(rowId);
1564
2506
  }
1565
2507
  }
1566
2508
  expandAllRow() {
1567
- if (this.isExpansion) {
1568
- this.isAllExpanded = !this.isAllExpanded;
2509
+ if (!this.isExpansion || !this.dataSource?.apiSubject?.value) {
2510
+ return;
2511
+ }
2512
+ this.isAllExpanded = !this.isAllExpanded;
2513
+ if (this.isAllExpanded) {
2514
+ // Add all row IDs to expanded set
1569
2515
  this.dataSource.apiSubject.value.forEach(row => {
1570
- row.expanded = this.isAllExpanded;
2516
+ const rowId = this.getRowIdentifier(row);
2517
+ this.expandedRowIds.add(rowId);
1571
2518
  });
1572
2519
  }
2520
+ else {
2521
+ // Clear all expanded rows
2522
+ this.expandedRowIds.clear();
2523
+ }
1573
2524
  }
1574
2525
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.7", ngImport: i0, type: TisSmartTableViewerComponent, deps: [{ token: i1$1.MatDialog }, { token: ApiService }, { token: i3$1.ActivatedRoute }, { token: i3$1.Router }, { token: i4.Location }, { token: i5.BreakpointObserver }], target: i0.ɵɵFactoryTarget.Component });
1575
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.7", type: TisSmartTableViewerComponent, isStandalone: false, selector: "tis-smart-table-viewer", inputs: { columnCustomizationUrlConfig: "columnCustomizationUrlConfig", t: "t", componentName: "componentName", mainTitle: "mainTitle", searchPlaceholder: "searchPlaceholder", breadcrumbs: "breadcrumbs", hideHeader: "hideHeader", hideTableHeader: "hideTableHeader", hidePaginator: "hidePaginator", keepFilterInUrl: "keepFilterInUrl", disableBorderedView: "disableBorderedView", displayColumnsSelectionButton: "displayColumnsSelectionButton", loadDataApiBaseUrl: "loadDataApiBaseUrl", startStickyColumnCount: "startStickyColumnCount", endStickyColumnCount: "endStickyColumnCount", loaderPosition: "loaderPosition", dataNotFoundConfig: "dataNotFoundConfig", showFilterButtonSection: "showFilterButtonSection", columnsCodeMapping: "columnsCodeMapping", defaultDisplayedColumns: "defaultDisplayedColumns", defaultSortObj: "defaultSortObj", loadingSpinnerDiameter: "loadingSpinnerDiameter", pageSizeOptions: "pageSizeOptions", pageSize: "pageSize", useGlobalPageSize: "useGlobalPageSize", pageIndex: "pageIndex", filterFormGroup: "filterFormGroup", rowsConfig: "rowsConfig", enableRowsSelection: "enableRowsSelection", enableAllRowsSelection: "enableAllRowsSelection", onlySingleSelection: "onlySingleSelection", selectedRowIds: "selectedRowIds", selectedRowKey: "selectedRowKey", selectedRows: "selectedRows", enableDragNDrop: "enableDragNDrop", isExpansion: "isExpansion", isExpandedRow: "isExpandedRow", expandedTemplate: "expandedTemplate" }, outputs: { displayedColumnsChange: "displayedColumnsChange", sortObjChange: "sortObjChange", pageSizeChange: "pageSizeChange", pageIndexChange: "pageIndexChange", onDataLoaded: "onDataLoaded", onSetExtraData: "onSetExtraData", onSetTotal: "onSetTotal", selectedRowsChange: "selectedRowsChange", allRowsSelectedChange: "allRowsSelectedChange", listDataSequenceChange: "listDataSequenceChange" }, providers: [CdkColumnDef], viewQueries: [{ propertyName: "sort", first: true, predicate: MatSort, descendants: true }, { propertyName: "paginator", first: true, predicate: MatPaginator, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<section [class.tis-page]=\"!hideHeader\">\n <div class=\"tis-page-header\" *ngIf=\"!hideHeader\">\n <nav aria-label=\"tis-breadcrumb\">\n <ol class=\"tis-breadcrumb\">\n <li class=\"tis-breadcrumb-item\"><a href=\"javascript:;\" [routerLink]=\"homeUrl\">{{t?.home}}</a></li>\n @for(breadcrumb of breadcrumbs; track breadcrumb) {\n <li class=\"tis-breadcrumb-item\" *ngIf=\"breadcrumb?.url\">\n <a href=\"javascript:;\" (click)=\"goToUrl(breadcrumb.url)\">{{breadcrumb?.name}}</a>\n </li>\n }\n <li class=\"tis-breadcrumb-item active\">\n {{mainTitle}}\n </li>\n </ol>\n </nav>\n <ng-content select=\"[slot='top-buttons-section']\"></ng-content>\n </div>\n <h1 class=\"tis-page-title\" *ngIf=\"!hideHeader\">{{mainTitle}}</h1>\n <div class=\"tis-page-body\">\n <div class=\"tis-page-body-content\">\n\n @if(initialLoading){\n <div class=\"tis-d-flex tis-justify-content-center pb-2 pt-7\">\n <mat-progress-spinner color=\"primary\" mode=\"indeterminate\" [diameter]=\"60\"></mat-progress-spinner>\n </div>\n } @else {\n\n @if ((dataSource?.totalDataLength$ | async) || (dataSource?.loading$ | async) || search ||\n filterHasNonEmptyValue || showFilterButtonSection || displayAfterFilterRemoved) {\n <div class=\"tis-table-container\">\n @if(!hideTableHeader){\n <div class=\"tis-table-container-header\">\n <ul class=\"tis-inline-group\">\n <li class=\"tis-inline-group-item\">\n <tis-columns-btn [columnCustomizationUrlConfig]=\"columnCustomizationUrlConfig\" [t]=\"t\"\n [componentName]=\"componentName\" [defaultColumns]=\"defaultColumns\" [columns]=\"columns\"\n (displayedColumnsChange)=\"onChangeDisplayColumns($event)\"\n (fromStartColumnNumberChange)=\"onChangeFromStartColumnNumber($event)\"\n (fromEndColumnNumberChange)=\"onChangeFromEndColumnNumber($event)\"></tis-columns-btn>\n </li>\n <ng-content select=\"[slot='filter-button-section']\"></ng-content>\n </ul>\n <div class=\"flex items-center\">\n <ul class=\"tis-inline-group\">\n <ng-content select=\"[slot='filter-right-button-section']\"></ng-content>\n </ul>\n @if(!isMobile && searchPlaceholder && searchPlaceholder != ''){\n <mat-form-field\n class=\"custom-mat-form-field-mb-0 search-mat-form-field ml-3 tis-table-search-field\"\n appearance=\"outline\">\n <span class=\"material-icons\" matPrefix>search</span>\n <input matInput [formControl]=\"searchCtrl\" [placeholder]=\"searchPlaceholder\">\n <span class=\"material-icons mr-2 tis-curser-pointer\" matSuffix\n (click)=\"searchCtrl.setValue('')\"\n *ngIf=\"searchCtrl.value && searchCtrl.value != ''\">close</span>\n </mat-form-field>\n }\n </div>\n </div>\n }\n\n @if (filterFormGroup) {\n\n <ng-content select=\"[slot='filter-form-section']\"></ng-content>\n\n @if(finalSelectedFilterValuesToDisplay.length && filterApplied) {\n <div class=\"flex gap-3 mb-3 filter-applied-section md-hide-scrollbar\">\n @for(v of finalSelectedFilterValuesToDisplay; track v) {\n @if (v) {\n <span class=\"tis-filter-badge\" style=\"white-space: nowrap;\">\n @if(v.labelKey && v.labelKey != '' && (v.valueKey || v.value)) {\n <span class=\"font-semibold\"> {{v.labelKey }} </span>\n }\n @if(v.valueKey) {\n {{v.valueKey }}\n } @else {\n {{v.value }}\n }\n <span class=\"material-icons tis-curser-pointer\"\n (click)=\"removeParticularFilter(v)\">cancel</span>\n </span>\n }\n }\n </div>\n }\n }\n\n @if(isMobile && searchPlaceholder && searchPlaceholder != ''){\n <mat-form-field\n class=\"custom-mat-form-field-mb-0 search-mat-form-field mb-3 tis-table-search-field\"\n appearance=\"outline\">\n <span class=\"material-icons\" matPrefix>search</span>\n <input matInput [formControl]=\"searchCtrl\" [placeholder]=\"searchPlaceholder\">\n <span class=\"material-icons mr-2 tis-curser-pointer\" matSuffix\n (click)=\"searchCtrl.setValue('')\"\n *ngIf=\"searchCtrl.value && searchCtrl.value != ''\">close</span>\n </mat-form-field>\n }\n\n \n @if(loaderPosition == 'top'){\n @if(dataSource?.loading$ | async){\n <div class=\"tis-d-flex tis-justify-content-center py-2\">\n <mat-progress-spinner color=\"primary\" mode=\"indeterminate\" [diameter]=\"loadingSpinnerDiameter\"></mat-progress-spinner>\n </div>\n }\n }\n <div class=\"tis-table-container-body\">\n <div class=\"tis-table-wrapper\" [appScrolling]=\"true\">\n\n <!--Table Here-->\n <table mat-table matSort [dataSource]=\"dataSource\" class=\"tis-table\" [class.tis-table-bordered]=\"disableBorderedView == false\" cdkDropList (cdkDropListDropped)=\"drop($event)\" [cdkDropListLockAxis]=\"'y'\" multiTemplateDataRows>\n\n @if (enableRowsSelection) {\n <ng-container matColumnDef=\"Select\">\n <th mat-header-cell *matHeaderCellDef>\n @if (enableAllRowsSelection) {\n <mat-checkbox color=\"primary\" (change)=\"$event ? toggleAllRows() : null\"\n [checked]=\"isAllRowsSelected\"\n [indeterminate]=\"selection.hasValue() && !isAllRowsSelected\">\n </mat-checkbox>\n }\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-checkbox color=\"primary\" (click)=\"stopPropagation($event)\" (change)=\"$event ? toggleSelection($event, row) : null\" [checked]=\"isChecked(row)\"></mat-checkbox>\n </td>\n </ng-container>\n }\n\n @for(column of autoRenderColumns; track column.serverKeyCode; let i = $index; let l = $last){\n <!-- [sticky]=\"i < startStickyColumnCount\" [stickyEnd]=\"i > (autoRenderColumns?.length - endStickyColumnCount)\" -->\n <ng-container [matColumnDef]=\"column?.columnDef || column.name\" [sticky]=\"isStickyStart(column?.columnDef || column.name)\" [stickyEnd]=\"isStickyEnd(column?.columnDef || column.name)\">\n @if(column.type == 'expand') {\n <th mat-header-cell *matHeaderCellDef [ngClass]=\"getColumnClasses(column)\">\n <div style=\"display: flex; align-items: center; gap: 5px;\">\n <span>{{ column?.columnName ? column?.columnName : t[column.name] }}</span>\n <mat-icon *ngIf=\"!isAllExpanded\">expand_more</mat-icon>\n <mat-icon *ngIf=\"isAllExpanded\">expand_less</mat-icon>\n </div>\n </th>\n }\n @else if(column.sort) {\n <th mat-header-cell mat-sort-header *matHeaderCellDef [ngClass]=\"getColumnClasses(column)\">\n {{ column?.columnName ? column?.columnName : t[column.name] }}\n </th>\n }\n @else {\n <th mat-header-cell *matHeaderCellDef [ngClass]=\"getColumnClasses(column)\">\n {{ column?.columnName ? column?.columnName : t[column.name] }}\n </th>\n }\n \n\n @if(column.type == 'date'){\n <td mat-cell *matCellDef=\"let element\" class=\"1al-{{column.align}} 1ty-{{column.type}}\" >\n <p [class.tis-a]=\"column.clickFn\" (click)=\"column?.clickFn?.(element, $event)\">\n {{ column.valueKey ? (getNestedValue(element, column.valueKey) | tisDate) : ''}}\n </p>\n </td>\n } @else if(column.type == 'date-time'){\n <td mat-cell *matCellDef=\"let element\" class=\"2al-{{column.align}} 2ty-{{column.type}}\">\n <p [class.tis-a]=\"column.clickFn\" (click)=\"column?.clickFn?.(element, $event)\">\n {{ column.valueKey ? (getNestedValue(element, column.valueKey) | tisDateTime) : ''}}\n </p>\n </td>\n } @else if(column.type == 'date-time-with-seconds'){\n <td mat-cell *matCellDef=\"let element\" class=\"2al-{{column.align}} 2ty-{{column.type}}\">\n <p [class.tis-a]=\"column.clickFn\" (click)=\"column?.clickFn?.(element, $event)\">\n {{ column.valueKey ? (getNestedValue(element, column.valueKey) | tisDateTimeWithSeconds) : ''}}\n </p>\n </td>\n } @else {\n <td mat-cell *matCellDef=\"let element\" class=\"3al-{{column.align}} 3ty-{{column.type}}\" [ngClass]=\"getColumnClasses(column)\">\n <p [class.tis-a]=\"column.clickFn\" (click)=\"column?.clickFn?.(element, $event)\">\n @if (column.type == 'quantity') {\n {{ column.valueKey ? (getNestedValue(element, column.valueKey) | number : '1.4-4') : '-' }}\n } @else if (column.type == 'money') {\n {{ column.valueKey && (getNestedValue(element, column.valueKey))?.toFixed(2) }}\n } @else {\n {{ column.valueKey && getNestedValue(element, column.valueKey) }}\n }\n </p>\n </td>\n }\n </ng-container>\n\n }\n\n\n @for(column of templateRenderColumns; track column.serverKeyCode; let i = $index; let l = $last){\n <!-- [sticky]=\"i < startStickyColumnCount\" [stickyEnd]=\"l\" -->\n <ng-container [matColumnDef]=\"column?.columnDef || column.name\" [sticky]=\"isStickyStart(column?.columnDef || column.name)\" [stickyEnd]=\"isStickyEnd(column?.columnDef || column.name)\">\n @if(column.type == 'expand') {\n <th mat-header-cell *matHeaderCellDef [ngClass]=\"getColumnClasses(column)\">\n <div style=\"display: flex; align-items: center; gap: 5px; cursor: pointer;\" (click)=\"expandAllRow()\">\n <span>{{ column?.columnName ? column?.columnName : t[column.name] }}</span>\n <mat-icon *ngIf=\"!isAllExpanded\">expand_more</mat-icon>\n <mat-icon *ngIf=\"isAllExpanded\">expand_less</mat-icon>\n </div>\n </th>\n }\n @else if(column.sort) {\n <th mat-header-cell *matHeaderCellDef mat-sort-header [ngClass]=\"getColumnClasses(column)\">\n {{ column?.columnName ? column?.columnName : t[column.name] }}\n </th>\n }\n @else {\n <th mat-header-cell *matHeaderCellDef [ngClass]=\"getColumnClasses(column)\">\n {{ column?.columnName ? column?.columnName : t[column.name] }}\n </th>\n }\n <td mat-cell *matCellDef=\"let element\" class=\"4al-{{column.align}} 4ty-{{column.type}}\" [ngClass]=\"getColumnClasses(column)\">\n <ng-container *ngIf=\"column.template as template\">\n <ng-container *ngTemplateOutlet=\"template; context: { colDef: column, colData: element }\"></ng-container>\n </ng-container>\n </td>\n </ng-container>\n }\n\n <!--Drag Column Def Start-->\n <ng-container [matColumnDef]=\"'drag'\" >\n <th mat-header-cell *matHeaderCellDef>\n --\n </th>\n <td mat-cell *matCellDef=\"let element\" class=\"5al-drag 5ty-drag\">\n <mat-icon cdkDragHandle class=\"tis-curser-pointer\" style=\"color: rgba(0, 0, 0, 0.54); font-size: 19px; width: 19px; height: 19px;\">drag_indicator</mat-icon>\n </td>\n </ng-container>\n <!--Drag Column Def End-->\n\n <!-- Expanded Content Column - The detail row is made up of this one column that spans across all columns -->\n <ng-container matColumnDef=\"expandedDetail\">\n <td mat-cell *matCellDef=\"let element\" [attr.colspan]=\"displayedColumns.length\" [style.border-bottom-width]=\"element.expanded ? '1px' : '0px'\" style=\"padding: 0px !important;\">\n <div class=\"tis-element-detail-wrapper\" [class.tis-element-detail-wrapper-expanded]=\"element.expanded\">\n <ng-container *ngIf=\"expandedTemplate as template\">\n <ng-container *ngTemplateOutlet=\"template; context: { colData: element }\"></ng-container>\n </ng-container>\n </div>\n </td>\n </ng-container>\n\n\n <tr class=\"mat-row\" *matNoDataRow>\n <td class=\"mat-cell\" [attr.colspan]=\"displayedColumns.length\">\n <div class=\"tis-data-not-found\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"130\" height=\"126.89\" viewBox=\"0 0 647.63626 632.17383\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" role=\"img\" artist=\"Katerina Limpitsouni\" source=\"https://undraw.co/\">\n <path d=\"M687.3279,276.08691H512.81813a15.01828,15.01828,0,0,0-15,15v387.85l-2,.61005-42.81006,13.11a8.00676,8.00676,0,0,1-9.98974-5.31L315.678,271.39691a8.00313,8.00313,0,0,1,5.31006-9.99l65.97022-20.2,191.25-58.54,65.96972-20.2a7.98927,7.98927,0,0,1,9.99024,5.3l32.5498,106.32Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"#f2f2f2\"/>\n <path d=\"M725.408,274.08691l-39.23-128.14a16.99368,16.99368,0,0,0-21.23-11.28l-92.75,28.39L380.95827,221.60693l-92.75,28.4a17.0152,17.0152,0,0,0-11.28028,21.23l134.08008,437.93a17.02661,17.02661,0,0,0,16.26026,12.03,16.78926,16.78926,0,0,0,4.96972-.75l63.58008-19.46,2-.62v-2.09l-2,.61-64.16992,19.65a15.01489,15.01489,0,0,1-18.73-9.95l-134.06983-437.94a14.97935,14.97935,0,0,1,9.94971-18.73l92.75-28.4,191.24024-58.54,92.75-28.4a15.15551,15.15551,0,0,1,4.40966-.66,15.01461,15.01461,0,0,1,14.32032,10.61l39.0498,127.56.62012,2h2.08008Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"#3f3d56\"/>\n <path d=\"M398.86279,261.73389a9.0157,9.0157,0,0,1-8.61133-6.3667l-12.88037-42.07178a8.99884,8.99884,0,0,1,5.9712-11.24023l175.939-53.86377a9.00867,9.00867,0,0,1,11.24072,5.9707l12.88037,42.07227a9.01029,9.01029,0,0,1-5.9707,11.24072L401.49219,261.33887A8.976,8.976,0,0,1,398.86279,261.73389Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"var(--tis-primary, var(--mat-sys-primary, #3838a2))\"/>\n <circle cx=\"190.15351\" cy=\"24.95465\" r=\"20\" fill=\"var(--tis-primary, var(--mat-sys-primary, #3838a2))\"/>\n <circle cx=\"190.15351\" cy=\"24.95465\" r=\"12.66462\" fill=\"#fff\"/>\n <path d=\"M878.81836,716.08691h-338a8.50981,8.50981,0,0,1-8.5-8.5v-405a8.50951,8.50951,0,0,1,8.5-8.5h338a8.50982,8.50982,0,0,1,8.5,8.5v405A8.51013,8.51013,0,0,1,878.81836,716.08691Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"#e6e6e6\"/>\n <path d=\"M723.31813,274.08691h-210.5a17.02411,17.02411,0,0,0-17,17v407.8l2-.61v-407.19a15.01828,15.01828,0,0,1,15-15H723.93825Zm183.5,0h-394a17.02411,17.02411,0,0,0-17,17v458a17.0241,17.0241,0,0,0,17,17h394a17.0241,17.0241,0,0,0,17-17v-458A17.02411,17.02411,0,0,0,906.81813,274.08691Zm15,475a15.01828,15.01828,0,0,1-15,15h-394a15.01828,15.01828,0,0,1-15-15v-458a15.01828,15.01828,0,0,1,15-15h394a15.01828,15.01828,0,0,1,15,15Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"#3f3d56\"/>\n <path d=\"M801.81836,318.08691h-184a9.01015,9.01015,0,0,1-9-9v-44a9.01016,9.01016,0,0,1,9-9h184a9.01016,9.01016,0,0,1,9,9v44A9.01015,9.01015,0,0,1,801.81836,318.08691Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"var(--tis-primary, var(--mat-sys-primary, #3838a2))\"/>\n <circle cx=\"433.63626\" cy=\"105.17383\" r=\"20\" fill=\"var(--tis-primary, var(--mat-sys-primary, #3838a2))\"/>\n <circle cx=\"433.63626\" cy=\"105.17383\" r=\"12.18187\" fill=\"#fff\"/>\n </svg>\n <h5 class=\"tis-h5\">{{dataNotFoundConfig.title}}</h5>\n </div>\n </td>\n </tr>\n\n <!-- Apply Drag and Drop to tbody -->\n @if(enableDragNDrop) {\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns\" [ngStyle]=\"{'background-color': getRowBackground(row) || 'inherit'}\" [class.tis-curser-pointer]=\"isExpandedRow\" (click)=\"(isExpansion && isExpandedRow) ? toggleExpand(row) : null\" cdkDrag></tr>\n }\n\n @if(!enableDragNDrop) {\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns\" [ngStyle]=\"{'background-color': getRowBackground(row) || 'inherit'}\" [class.tis-curser-pointer]=\"isExpandedRow\" (click)=\"(isExpansion && isExpandedRow) ? toggleExpand(row) : null\"></tr>\n } \n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: ['expandedDetail']\" class=\"tis-detail-row\"></tr>\n </table>\n <!--Table End-->\n\n </div>\n @if(loaderPosition == 'bottom'){\n @if(dataSource?.loading$ | async){\n <div class=\"tis-d-flex tis-justify-content-center py-2\">\n <mat-progress-spinner color=\"primary\" mode=\"indeterminate\" [diameter]=\"loadingSpinnerDiameter\"></mat-progress-spinner>\n </div>\n }\n }\n @if (!hidePaginator) {\n <div class=\"tis-table-paginator\">\n <mat-paginator [length]=\"dataSource?.totalDataLength?.value\" [pageSize]=\"pageSize\"\n [pageSizeOptions]=\"pageSizeOptions\" showFirstLastButtons></mat-paginator>\n </div>\n }\n </div>\n </div>\n } @else {\n\n @if(dataNotFoundConfig) {\n <div class=\"tis-data-not-found\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"130\" height=\"126.89\" viewBox=\"0 0 647.63626 632.17383\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" role=\"img\" artist=\"Katerina Limpitsouni\" source=\"https://undraw.co/\">\n <path d=\"M687.3279,276.08691H512.81813a15.01828,15.01828,0,0,0-15,15v387.85l-2,.61005-42.81006,13.11a8.00676,8.00676,0,0,1-9.98974-5.31L315.678,271.39691a8.00313,8.00313,0,0,1,5.31006-9.99l65.97022-20.2,191.25-58.54,65.96972-20.2a7.98927,7.98927,0,0,1,9.99024,5.3l32.5498,106.32Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"#f2f2f2\"/>\n <path d=\"M725.408,274.08691l-39.23-128.14a16.99368,16.99368,0,0,0-21.23-11.28l-92.75,28.39L380.95827,221.60693l-92.75,28.4a17.0152,17.0152,0,0,0-11.28028,21.23l134.08008,437.93a17.02661,17.02661,0,0,0,16.26026,12.03,16.78926,16.78926,0,0,0,4.96972-.75l63.58008-19.46,2-.62v-2.09l-2,.61-64.16992,19.65a15.01489,15.01489,0,0,1-18.73-9.95l-134.06983-437.94a14.97935,14.97935,0,0,1,9.94971-18.73l92.75-28.4,191.24024-58.54,92.75-28.4a15.15551,15.15551,0,0,1,4.40966-.66,15.01461,15.01461,0,0,1,14.32032,10.61l39.0498,127.56.62012,2h2.08008Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"#3f3d56\"/>\n <path d=\"M398.86279,261.73389a9.0157,9.0157,0,0,1-8.61133-6.3667l-12.88037-42.07178a8.99884,8.99884,0,0,1,5.9712-11.24023l175.939-53.86377a9.00867,9.00867,0,0,1,11.24072,5.9707l12.88037,42.07227a9.01029,9.01029,0,0,1-5.9707,11.24072L401.49219,261.33887A8.976,8.976,0,0,1,398.86279,261.73389Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"var(--tis-primary, var(--mat-sys-primary, #3838a2))\"/>\n <circle cx=\"190.15351\" cy=\"24.95465\" r=\"20\" fill=\"var(--tis-primary, var(--mat-sys-primary, #3838a2))\"/>\n <circle cx=\"190.15351\" cy=\"24.95465\" r=\"12.66462\" fill=\"#fff\"/>\n <path d=\"M878.81836,716.08691h-338a8.50981,8.50981,0,0,1-8.5-8.5v-405a8.50951,8.50951,0,0,1,8.5-8.5h338a8.50982,8.50982,0,0,1,8.5,8.5v405A8.51013,8.51013,0,0,1,878.81836,716.08691Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"#e6e6e6\"/>\n <path d=\"M723.31813,274.08691h-210.5a17.02411,17.02411,0,0,0-17,17v407.8l2-.61v-407.19a15.01828,15.01828,0,0,1,15-15H723.93825Zm183.5,0h-394a17.02411,17.02411,0,0,0-17,17v458a17.0241,17.0241,0,0,0,17,17h394a17.0241,17.0241,0,0,0,17-17v-458A17.02411,17.02411,0,0,0,906.81813,274.08691Zm15,475a15.01828,15.01828,0,0,1-15,15h-394a15.01828,15.01828,0,0,1-15-15v-458a15.01828,15.01828,0,0,1,15-15h394a15.01828,15.01828,0,0,1,15,15Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"#3f3d56\"/>\n <path d=\"M801.81836,318.08691h-184a9.01015,9.01015,0,0,1-9-9v-44a9.01016,9.01016,0,0,1,9-9h184a9.01016,9.01016,0,0,1,9,9v44A9.01015,9.01015,0,0,1,801.81836,318.08691Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"var(--tis-primary, var(--mat-sys-primary, #3838a2))\"/>\n <circle cx=\"433.63626\" cy=\"105.17383\" r=\"20\" fill=\"var(--tis-primary, var(--mat-sys-primary, #3838a2))\"/>\n <circle cx=\"433.63626\" cy=\"105.17383\" r=\"12.18187\" fill=\"#fff\"/>\n </svg>\n <h5 class=\"tis-h5\">{{dataNotFoundConfig.title}}</h5>\n <p class=\"tis-p\">{{dataNotFoundConfig.desc}}</p>\n @if((dataNotFoundConfig.btnUrl || dataNotFoundConfig?.btnClick) && dataNotFoundConfig.btnText) {\n <button mat-flat-button color=\"primary\" class=\"tis-text-upper\"\n (click)=\"handleButtonClick(dataNotFoundConfig)\">\n <mat-icon>add</mat-icon>\n {{dataNotFoundConfig.btnText}}\n </button>\n }\n @if((dataNotFoundConfig.secondBtnUrl || dataNotFoundConfig?.secondBtnClick) && dataNotFoundConfig.secondBtnText) {\n <button mat-stroked-button color=\"primary\" class=\"tis-text-upper\"\n (click)=\"handleSecondButtonClick(dataNotFoundConfig)\">\n <mat-icon>add</mat-icon>\n {{dataNotFoundConfig.secondBtnText}}\n </button>\n }\n </div>\n }\n\n }\n\n }\n\n </div>\n </div>\n</section>", styles: ["::ng-deep .sub-main-content{border:0px solid #f00;margin-top:56px;height:calc(100% - 56px);padding:15px;overflow:auto}.header-title{margin-top:8px;padding:7px 10px;color:#969a9c}.header-title h3{font-size:20px!important;font-weight:700}.header-menu{border:0px solid red;background:#fff;margin-top:1px;margin-bottom:0}.w-100{width:100%}.mat-mdc-table-sticky-border-elem-right{border-left:1px solid #e0e0e087}.mat-mdc-table-sticky-border-elem-left{border-right:1px solid #e0e0e087}.search-mat-form-field{width:100%}.filter-applied-section{overflow:auto}.tis-detail-row{height:0!important}.tis-element-detail-wrapper{overflow:hidden;max-height:0;transition:max-height 225ms ease}.tis-element-detail-wrapper-expanded{max-height:500px}.tis-table-bordered{border-collapse:collapse;width:100%}.tis-table-bordered th,.tis-table-bordered td{border-left:1px solid #e0e0e0}.tis-table-bordered th:first-child,.tis-table-bordered td:first-child{border-left:0px solid #e0e0e0}.tis-table-bordered .bg-unset{background-color:unset!important}@media (max-width: 575.98px){.search-mat-form-field{width:100%!important}}@media (min-width: 576px) and (max-width: 767.98px){.search-mat-form-field{width:100%!important}}\n"], dependencies: [{ kind: "directive", type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i4.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i6.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i6.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i6.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i3$1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i8.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i8.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i8.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "directive", type: i10.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i10$1.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: i4$1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i12$1.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "component", type: i13$1.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i13$1.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i13$1.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i13$1.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i13$1.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i13$1.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i13$1.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i13$1.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i13$1.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i13$1.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: i13$1.MatNoDataRow, selector: "ng-template[matNoDataRow]" }, { kind: "component", type: i12.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "directive", type: i15.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i15.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "directive", type: i13.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i13.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i13.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "directive", type: ScrollingDirective, selector: "[appScrolling]", inputs: ["appScrolling"] }, { kind: "component", type: TisColumnsBtnComponent, selector: "tis-columns-btn", inputs: ["columnCustomizationUrlConfig", "t", "componentName", "defaultColumns", "columns", "skipTranslation", "customColumns"], outputs: ["displayedColumnsChange", "fromStartColumnNumberChange", "fromEndColumnNumberChange"] }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.DecimalPipe, name: "number" }, { kind: "pipe", type: TisDatePipe, name: "tisDate" }, { kind: "pipe", type: TisDateTimePipe, name: "tisDateTime" }, { kind: "pipe", type: TisDateTimeWithSecondsPipe, name: "tisDateTimeWithSeconds" }] });
2526
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.7", type: TisSmartTableViewerComponent, isStandalone: false, selector: "tis-smart-table-viewer", inputs: { columnCustomizationUrlConfig: "columnCustomizationUrlConfig", t: "t", componentName: "componentName", mainTitle: "mainTitle", searchPlaceholder: "searchPlaceholder", breadcrumbs: "breadcrumbs", hideHeader: "hideHeader", hideTableHeader: "hideTableHeader", hidePaginator: "hidePaginator", keepFilterInUrl: "keepFilterInUrl", disableBorderedView: "disableBorderedView", displayColumnsSelectionButton: "displayColumnsSelectionButton", loadDataApiBaseUrl: "loadDataApiBaseUrl", startStickyColumnCount: "startStickyColumnCount", endStickyColumnCount: "endStickyColumnCount", loaderPosition: "loaderPosition", dataNotFoundConfig: "dataNotFoundConfig", showFilterButtonSection: "showFilterButtonSection", columnsCodeMapping: "columnsCodeMapping", defaultDisplayedColumns: "defaultDisplayedColumns", defaultSortObj: "defaultSortObj", loadingSpinnerDiameter: "loadingSpinnerDiameter", pageSizeOptions: "pageSizeOptions", pageSize: "pageSize", useGlobalPageSize: "useGlobalPageSize", pageIndex: "pageIndex", filterFormGroup: "filterFormGroup", rowsConfig: "rowsConfig", enableRowsSelection: "enableRowsSelection", enableAllRowsSelection: "enableAllRowsSelection", onlySingleSelection: "onlySingleSelection", selectedRowIds: "selectedRowIds", selectedRowKey: "selectedRowKey", selectedRows: "selectedRows", enableDragNDrop: "enableDragNDrop", isExpansion: "isExpansion", isExpandedRow: "isExpandedRow", expandedTemplate: "expandedTemplate" }, outputs: { displayedColumnsChange: "displayedColumnsChange", sortObjChange: "sortObjChange", pageSizeChange: "pageSizeChange", pageIndexChange: "pageIndexChange", onDataLoaded: "onDataLoaded", onSetExtraData: "onSetExtraData", onSetTotal: "onSetTotal", selectedRowsChange: "selectedRowsChange", allRowsSelectedChange: "allRowsSelectedChange", listDataSequenceChange: "listDataSequenceChange" }, providers: [CdkColumnDef], viewQueries: [{ propertyName: "sort", first: true, predicate: MatSort, descendants: true }, { propertyName: "paginator", first: true, predicate: MatPaginator, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<section [class.tis-page]=\"!hideHeader\">\n <div class=\"tis-page-header\" *ngIf=\"!hideHeader\">\n <nav aria-label=\"tis-breadcrumb\">\n <ol class=\"tis-breadcrumb\">\n <li class=\"tis-breadcrumb-item\"><a href=\"javascript:;\" [routerLink]=\"homeUrl\">{{t?.home}}</a></li>\n @for(breadcrumb of breadcrumbs; track trackByBreadcrumb($index, breadcrumb)) {\n <li class=\"tis-breadcrumb-item\" *ngIf=\"breadcrumb?.url\">\n <a href=\"javascript:;\" (click)=\"goToUrl(breadcrumb.url)\">{{breadcrumb?.name}}</a>\n </li>\n }\n <li class=\"tis-breadcrumb-item active\">\n {{mainTitle}}\n </li>\n </ol>\n </nav>\n <ng-content select=\"[slot='top-buttons-section']\"></ng-content>\n </div>\n <h1 class=\"tis-page-title\" *ngIf=\"!hideHeader\">{{mainTitle}}</h1>\n <div class=\"tis-page-body\">\n <div class=\"tis-page-body-content\">\n\n @if(initialLoading){\n <div class=\"tis-d-flex tis-justify-content-center pb-2 pt-7\">\n <mat-progress-spinner color=\"primary\" mode=\"indeterminate\" [diameter]=\"60\"></mat-progress-spinner>\n </div>\n } @else {\n\n @if ((dataSource?.totalDataLength$ | async) || (dataSource?.loading$ | async) || search ||\n filterHasNonEmptyValue || showFilterButtonSection || displayAfterFilterRemoved) {\n <div class=\"tis-table-container\">\n @if(!hideTableHeader){\n <div class=\"tis-table-container-header\">\n <ul class=\"tis-inline-group\">\n <li class=\"tis-inline-group-item\">\n <tis-columns-btn [columnCustomizationUrlConfig]=\"columnCustomizationUrlConfig\" [t]=\"t\"\n [componentName]=\"componentName\" [defaultColumns]=\"defaultColumns\" [columns]=\"columns\"\n (displayedColumnsChange)=\"onChangeDisplayColumns($event)\"\n (fromStartColumnNumberChange)=\"onChangeFromStartColumnNumber($event)\"\n (fromEndColumnNumberChange)=\"onChangeFromEndColumnNumber($event)\"></tis-columns-btn>\n </li>\n <ng-content select=\"[slot='filter-button-section']\"></ng-content>\n </ul>\n <div class=\"flex items-center\">\n <ul class=\"tis-inline-group\">\n <ng-content select=\"[slot='filter-right-button-section']\"></ng-content>\n </ul>\n @if(!isMobile && searchPlaceholder && searchPlaceholder != ''){\n <mat-form-field\n class=\"custom-mat-form-field-mb-0 search-mat-form-field ml-3 tis-table-search-field\"\n appearance=\"outline\">\n <span class=\"material-icons\" matPrefix>search</span>\n <input matInput [formControl]=\"searchCtrl\" [placeholder]=\"searchPlaceholder\">\n <span class=\"material-icons mr-2 tis-curser-pointer\" matSuffix\n (click)=\"searchCtrl.setValue('')\"\n *ngIf=\"searchCtrl.value && searchCtrl.value != ''\">close</span>\n </mat-form-field>\n }\n </div>\n </div>\n }\n\n @if (filterFormGroup) {\n\n <ng-content select=\"[slot='filter-form-section']\"></ng-content>\n\n @if(finalSelectedFilterValuesToDisplay.length && filterApplied) {\n <div class=\"flex gap-3 mb-3 filter-applied-section md-hide-scrollbar\">\n @for(v of finalSelectedFilterValuesToDisplay; track trackByFilterValue($index, v)) {\n @if (v) {\n <span class=\"tis-filter-badge\" style=\"white-space: nowrap;\">\n @if(v.labelKey && v.labelKey != '' && (v.valueKey || v.value)) {\n <span class=\"font-semibold\"> {{v.labelKey }} </span>\n }\n @if(v.valueKey) {\n {{v.valueKey }}\n } @else {\n {{v.value }}\n }\n <span class=\"material-icons tis-curser-pointer\"\n (click)=\"removeParticularFilter(v)\">cancel</span>\n </span>\n }\n }\n </div>\n }\n }\n\n @if(isMobile && searchPlaceholder && searchPlaceholder != ''){\n <mat-form-field\n class=\"custom-mat-form-field-mb-0 search-mat-form-field mb-3 tis-table-search-field\"\n appearance=\"outline\">\n <span class=\"material-icons\" matPrefix>search</span>\n <input matInput [formControl]=\"searchCtrl\" [placeholder]=\"searchPlaceholder\">\n <span class=\"material-icons mr-2 tis-curser-pointer\" matSuffix\n (click)=\"searchCtrl.setValue('')\"\n *ngIf=\"searchCtrl.value && searchCtrl.value != ''\">close</span>\n </mat-form-field>\n }\n\n \n @if(loaderPosition == 'top'){\n @if(dataSource?.loading$ | async){\n <div class=\"tis-d-flex tis-justify-content-center py-2\">\n <mat-progress-spinner color=\"primary\" mode=\"indeterminate\" [diameter]=\"loadingSpinnerDiameter\"></mat-progress-spinner>\n </div>\n }\n }\n <div class=\"tis-table-container-body\">\n <div class=\"tis-table-wrapper\" [appScrolling]=\"true\">\n\n <!--Table Here-->\n <table mat-table matSort [dataSource]=\"dataSource\" class=\"tis-table\" [class.tis-table-bordered]=\"disableBorderedView == false\" cdkDropList (cdkDropListDropped)=\"drop($event)\" [cdkDropListLockAxis]=\"'y'\" multiTemplateDataRows>\n\n @if (enableRowsSelection) {\n <ng-container matColumnDef=\"Select\">\n <th mat-header-cell *matHeaderCellDef>\n @if (enableAllRowsSelection) {\n <mat-checkbox color=\"primary\" (change)=\"$event ? toggleAllRows() : null\"\n [checked]=\"isAllRowsSelected\"\n [indeterminate]=\"selection.hasValue() && !isAllRowsSelected\">\n </mat-checkbox>\n }\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-checkbox color=\"primary\" (click)=\"stopPropagation($event)\" (change)=\"$event ? toggleSelection($event, row) : null\" [checked]=\"isChecked(row)\"></mat-checkbox>\n </td>\n </ng-container>\n }\n\n @for(column of autoRenderColumns; track trackByAutoColumn($index, column); let i = $index; let l = $last){\n <!-- [sticky]=\"i < startStickyColumnCount\" [stickyEnd]=\"i > (autoRenderColumns?.length - endStickyColumnCount)\" -->\n <ng-container [matColumnDef]=\"column?.columnDef || column.name\" [sticky]=\"isStickyStart(column?.columnDef || column.name)\" [stickyEnd]=\"isStickyEnd(column?.columnDef || column.name)\">\n @if(column.type == 'expand') {\n <th mat-header-cell *matHeaderCellDef [ngClass]=\"getColumnClasses(column)\">\n <div style=\"display: flex; align-items: center; gap: 5px;\">\n <span>{{ column?.columnName ? column?.columnName : t[column.name] }}</span>\n <mat-icon *ngIf=\"!isAllExpanded\">expand_more</mat-icon>\n <mat-icon *ngIf=\"isAllExpanded\">expand_less</mat-icon>\n </div>\n </th>\n }\n @else if(column.sort) {\n <th mat-header-cell mat-sort-header *matHeaderCellDef [ngClass]=\"getColumnClasses(column)\">\n {{ column?.columnName ? column?.columnName : t[column.name] }}\n </th>\n }\n @else {\n <th mat-header-cell *matHeaderCellDef [ngClass]=\"getColumnClasses(column)\">\n {{ column?.columnName ? column?.columnName : t[column.name] }}\n </th>\n }\n \n\n @if(column.type == 'date'){\n <td mat-cell *matCellDef=\"let element\" class=\"1al-{{column.align}} 1ty-{{column.type}}\" >\n <p [class.tis-a]=\"column.clickFn\" (click)=\"column?.clickFn?.(element, $event)\">\n {{ column.valueKey ? (getNestedValue(element, column.valueKey) | tisDate) : ''}}\n </p>\n </td>\n } @else if(column.type == 'date-time'){\n <td mat-cell *matCellDef=\"let element\" class=\"2al-{{column.align}} 2ty-{{column.type}}\">\n <p [class.tis-a]=\"column.clickFn\" (click)=\"column?.clickFn?.(element, $event)\">\n {{ column.valueKey ? (getNestedValue(element, column.valueKey) | tisDateTime) : ''}}\n </p>\n </td>\n } @else if(column.type == 'date-time-with-seconds'){\n <td mat-cell *matCellDef=\"let element\" class=\"2al-{{column.align}} 2ty-{{column.type}}\">\n <p [class.tis-a]=\"column.clickFn\" (click)=\"column?.clickFn?.(element, $event)\">\n {{ column.valueKey ? (getNestedValue(element, column.valueKey) | tisDateTimeWithSeconds) : ''}}\n </p>\n </td>\n } @else {\n <td mat-cell *matCellDef=\"let element\" class=\"3al-{{column.align}} 3ty-{{column.type}}\" [ngClass]=\"getColumnClasses(column)\">\n <p [class.tis-a]=\"column.clickFn\" (click)=\"column?.clickFn?.(element, $event)\">\n @if (column.type == 'quantity') {\n {{ column.valueKey ? (getNestedValue(element, column.valueKey) | number : '1.4-4') : '-' }}\n } @else if (column.type == 'money') {\n {{ column.valueKey && (getNestedValue(element, column.valueKey))?.toFixed(2) }}\n } @else {\n {{ column.valueKey && getNestedValue(element, column.valueKey) }}\n }\n </p>\n </td>\n }\n </ng-container>\n\n }\n\n\n @for(column of templateRenderColumns; track trackByTemplateColumn($index, column); let i = $index; let l = $last){\n <!-- [sticky]=\"i < startStickyColumnCount\" [stickyEnd]=\"l\" -->\n <ng-container [matColumnDef]=\"column?.columnDef || column.name\" [sticky]=\"isStickyStart(column?.columnDef || column.name)\" [stickyEnd]=\"isStickyEnd(column?.columnDef || column.name)\">\n @if(column.type == 'expand') {\n <th mat-header-cell *matHeaderCellDef [ngClass]=\"getColumnClasses(column)\">\n <div style=\"display: flex; align-items: center; gap: 5px; cursor: pointer;\" (click)=\"expandAllRow()\">\n <span>{{ column?.columnName ? column?.columnName : t[column.name] }}</span>\n <mat-icon *ngIf=\"!isAllExpanded\">expand_more</mat-icon>\n <mat-icon *ngIf=\"isAllExpanded\">expand_less</mat-icon>\n </div>\n </th>\n }\n @else if(column.sort) {\n <th mat-header-cell *matHeaderCellDef mat-sort-header [ngClass]=\"getColumnClasses(column)\">\n {{ column?.columnName ? column?.columnName : t[column.name] }}\n </th>\n }\n @else {\n <th mat-header-cell *matHeaderCellDef [ngClass]=\"getColumnClasses(column)\">\n {{ column?.columnName ? column?.columnName : t[column.name] }}\n </th>\n }\n <td mat-cell *matCellDef=\"let element\" class=\"4al-{{column.align}} 4ty-{{column.type}}\" [ngClass]=\"getColumnClasses(column)\">\n <ng-container *ngIf=\"column.template as template\">\n <ng-container *ngTemplateOutlet=\"template; context: { colDef: column, colData: element }\"></ng-container>\n </ng-container>\n </td>\n </ng-container>\n }\n\n <!--Drag Column Def Start-->\n <ng-container [matColumnDef]=\"'drag'\" >\n <th mat-header-cell *matHeaderCellDef>\n --\n </th>\n <td mat-cell *matCellDef=\"let element\" class=\"5al-drag 5ty-drag\">\n <mat-icon cdkDragHandle class=\"tis-curser-pointer\" style=\"color: rgba(0, 0, 0, 0.54); font-size: 19px; width: 19px; height: 19px;\">drag_indicator</mat-icon>\n </td>\n </ng-container>\n <!--Drag Column Def End-->\n\n <!-- Expanded Content Column - The detail row is made up of this one column that spans across all columns -->\n <ng-container matColumnDef=\"expandedDetail\">\n <td mat-cell *matCellDef=\"let element\" [attr.colspan]=\"displayedColumns.length\" [style.border-bottom-width]=\"element.expanded ? '1px' : '0px'\" style=\"padding: 0px !important;\">\n <div class=\"tis-element-detail-wrapper\" [class.tis-element-detail-wrapper-expanded]=\"element.expanded\">\n <ng-container *ngIf=\"expandedTemplate as template\">\n <ng-container *ngTemplateOutlet=\"template; context: { colData: element }\"></ng-container>\n </ng-container>\n </div>\n </td>\n </ng-container>\n\n\n <tr class=\"mat-row\" *matNoDataRow>\n <td class=\"mat-cell\" [attr.colspan]=\"displayedColumns.length\">\n <div class=\"tis-data-not-found\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"130\" height=\"126.89\" viewBox=\"0 0 647.63626 632.17383\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" role=\"img\" artist=\"Katerina Limpitsouni\" source=\"https://undraw.co/\">\n <path d=\"M687.3279,276.08691H512.81813a15.01828,15.01828,0,0,0-15,15v387.85l-2,.61005-42.81006,13.11a8.00676,8.00676,0,0,1-9.98974-5.31L315.678,271.39691a8.00313,8.00313,0,0,1,5.31006-9.99l65.97022-20.2,191.25-58.54,65.96972-20.2a7.98927,7.98927,0,0,1,9.99024,5.3l32.5498,106.32Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"#f2f2f2\"/>\n <path d=\"M725.408,274.08691l-39.23-128.14a16.99368,16.99368,0,0,0-21.23-11.28l-92.75,28.39L380.95827,221.60693l-92.75,28.4a17.0152,17.0152,0,0,0-11.28028,21.23l134.08008,437.93a17.02661,17.02661,0,0,0,16.26026,12.03,16.78926,16.78926,0,0,0,4.96972-.75l63.58008-19.46,2-.62v-2.09l-2,.61-64.16992,19.65a15.01489,15.01489,0,0,1-18.73-9.95l-134.06983-437.94a14.97935,14.97935,0,0,1,9.94971-18.73l92.75-28.4,191.24024-58.54,92.75-28.4a15.15551,15.15551,0,0,1,4.40966-.66,15.01461,15.01461,0,0,1,14.32032,10.61l39.0498,127.56.62012,2h2.08008Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"#3f3d56\"/>\n <path d=\"M398.86279,261.73389a9.0157,9.0157,0,0,1-8.61133-6.3667l-12.88037-42.07178a8.99884,8.99884,0,0,1,5.9712-11.24023l175.939-53.86377a9.00867,9.00867,0,0,1,11.24072,5.9707l12.88037,42.07227a9.01029,9.01029,0,0,1-5.9707,11.24072L401.49219,261.33887A8.976,8.976,0,0,1,398.86279,261.73389Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"var(--tis-primary, var(--mat-sys-primary, #3838a2))\"/>\n <circle cx=\"190.15351\" cy=\"24.95465\" r=\"20\" fill=\"var(--tis-primary, var(--mat-sys-primary, #3838a2))\"/>\n <circle cx=\"190.15351\" cy=\"24.95465\" r=\"12.66462\" fill=\"#fff\"/>\n <path d=\"M878.81836,716.08691h-338a8.50981,8.50981,0,0,1-8.5-8.5v-405a8.50951,8.50951,0,0,1,8.5-8.5h338a8.50982,8.50982,0,0,1,8.5,8.5v405A8.51013,8.51013,0,0,1,878.81836,716.08691Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"#e6e6e6\"/>\n <path d=\"M723.31813,274.08691h-210.5a17.02411,17.02411,0,0,0-17,17v407.8l2-.61v-407.19a15.01828,15.01828,0,0,1,15-15H723.93825Zm183.5,0h-394a17.02411,17.02411,0,0,0-17,17v458a17.0241,17.0241,0,0,0,17,17h394a17.0241,17.0241,0,0,0,17-17v-458A17.02411,17.02411,0,0,0,906.81813,274.08691Zm15,475a15.01828,15.01828,0,0,1-15,15h-394a15.01828,15.01828,0,0,1-15-15v-458a15.01828,15.01828,0,0,1,15-15h394a15.01828,15.01828,0,0,1,15,15Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"#3f3d56\"/>\n <path d=\"M801.81836,318.08691h-184a9.01015,9.01015,0,0,1-9-9v-44a9.01016,9.01016,0,0,1,9-9h184a9.01016,9.01016,0,0,1,9,9v44A9.01015,9.01015,0,0,1,801.81836,318.08691Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"var(--tis-primary, var(--mat-sys-primary, #3838a2))\"/>\n <circle cx=\"433.63626\" cy=\"105.17383\" r=\"20\" fill=\"var(--tis-primary, var(--mat-sys-primary, #3838a2))\"/>\n <circle cx=\"433.63626\" cy=\"105.17383\" r=\"12.18187\" fill=\"#fff\"/>\n </svg>\n <h5 class=\"tis-h5\">{{dataNotFoundConfig.title}}</h5>\n </div>\n </td>\n </tr>\n\n <!-- Apply Drag and Drop to tbody -->\n @if(enableDragNDrop) {\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns\" [ngStyle]=\"{'background-color': getRowBackground(row) || 'inherit'}\" [class.tis-curser-pointer]=\"isExpandedRow\" (click)=\"(isExpansion && isExpandedRow) ? toggleExpand(row) : null\" cdkDrag></tr>\n }\n\n @if(!enableDragNDrop) {\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns\" [ngStyle]=\"{'background-color': getRowBackground(row) || 'inherit'}\" [class.tis-curser-pointer]=\"isExpandedRow\" (click)=\"(isExpansion && isExpandedRow) ? toggleExpand(row) : null\"></tr>\n } \n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: ['expandedDetail']\" class=\"tis-detail-row\"></tr>\n </table>\n <!--Table End-->\n\n </div>\n @if(loaderPosition == 'bottom'){\n @if(dataSource?.loading$ | async){\n <div class=\"tis-d-flex tis-justify-content-center py-2\">\n <mat-progress-spinner color=\"primary\" mode=\"indeterminate\" [diameter]=\"loadingSpinnerDiameter\"></mat-progress-spinner>\n </div>\n }\n }\n @if (!hidePaginator) {\n <div class=\"tis-table-paginator\">\n <mat-paginator [length]=\"dataSource?.totalDataLength?.value\" [pageSize]=\"pageSize\"\n [pageSizeOptions]=\"pageSizeOptions\" showFirstLastButtons></mat-paginator>\n </div>\n }\n </div>\n </div>\n } @else {\n\n @if(dataNotFoundConfig) {\n <div class=\"tis-data-not-found\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"130\" height=\"126.89\" viewBox=\"0 0 647.63626 632.17383\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" role=\"img\" artist=\"Katerina Limpitsouni\" source=\"https://undraw.co/\">\n <path d=\"M687.3279,276.08691H512.81813a15.01828,15.01828,0,0,0-15,15v387.85l-2,.61005-42.81006,13.11a8.00676,8.00676,0,0,1-9.98974-5.31L315.678,271.39691a8.00313,8.00313,0,0,1,5.31006-9.99l65.97022-20.2,191.25-58.54,65.96972-20.2a7.98927,7.98927,0,0,1,9.99024,5.3l32.5498,106.32Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"#f2f2f2\"/>\n <path d=\"M725.408,274.08691l-39.23-128.14a16.99368,16.99368,0,0,0-21.23-11.28l-92.75,28.39L380.95827,221.60693l-92.75,28.4a17.0152,17.0152,0,0,0-11.28028,21.23l134.08008,437.93a17.02661,17.02661,0,0,0,16.26026,12.03,16.78926,16.78926,0,0,0,4.96972-.75l63.58008-19.46,2-.62v-2.09l-2,.61-64.16992,19.65a15.01489,15.01489,0,0,1-18.73-9.95l-134.06983-437.94a14.97935,14.97935,0,0,1,9.94971-18.73l92.75-28.4,191.24024-58.54,92.75-28.4a15.15551,15.15551,0,0,1,4.40966-.66,15.01461,15.01461,0,0,1,14.32032,10.61l39.0498,127.56.62012,2h2.08008Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"#3f3d56\"/>\n <path d=\"M398.86279,261.73389a9.0157,9.0157,0,0,1-8.61133-6.3667l-12.88037-42.07178a8.99884,8.99884,0,0,1,5.9712-11.24023l175.939-53.86377a9.00867,9.00867,0,0,1,11.24072,5.9707l12.88037,42.07227a9.01029,9.01029,0,0,1-5.9707,11.24072L401.49219,261.33887A8.976,8.976,0,0,1,398.86279,261.73389Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"var(--tis-primary, var(--mat-sys-primary, #3838a2))\"/>\n <circle cx=\"190.15351\" cy=\"24.95465\" r=\"20\" fill=\"var(--tis-primary, var(--mat-sys-primary, #3838a2))\"/>\n <circle cx=\"190.15351\" cy=\"24.95465\" r=\"12.66462\" fill=\"#fff\"/>\n <path d=\"M878.81836,716.08691h-338a8.50981,8.50981,0,0,1-8.5-8.5v-405a8.50951,8.50951,0,0,1,8.5-8.5h338a8.50982,8.50982,0,0,1,8.5,8.5v405A8.51013,8.51013,0,0,1,878.81836,716.08691Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"#e6e6e6\"/>\n <path d=\"M723.31813,274.08691h-210.5a17.02411,17.02411,0,0,0-17,17v407.8l2-.61v-407.19a15.01828,15.01828,0,0,1,15-15H723.93825Zm183.5,0h-394a17.02411,17.02411,0,0,0-17,17v458a17.0241,17.0241,0,0,0,17,17h394a17.0241,17.0241,0,0,0,17-17v-458A17.02411,17.02411,0,0,0,906.81813,274.08691Zm15,475a15.01828,15.01828,0,0,1-15,15h-394a15.01828,15.01828,0,0,1-15-15v-458a15.01828,15.01828,0,0,1,15-15h394a15.01828,15.01828,0,0,1,15,15Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"#3f3d56\"/>\n <path d=\"M801.81836,318.08691h-184a9.01015,9.01015,0,0,1-9-9v-44a9.01016,9.01016,0,0,1,9-9h184a9.01016,9.01016,0,0,1,9,9v44A9.01015,9.01015,0,0,1,801.81836,318.08691Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"var(--tis-primary, var(--mat-sys-primary, #3838a2))\"/>\n <circle cx=\"433.63626\" cy=\"105.17383\" r=\"20\" fill=\"var(--tis-primary, var(--mat-sys-primary, #3838a2))\"/>\n <circle cx=\"433.63626\" cy=\"105.17383\" r=\"12.18187\" fill=\"#fff\"/>\n </svg>\n <h5 class=\"tis-h5\">{{dataNotFoundConfig.title}}</h5>\n <p class=\"tis-p\">{{dataNotFoundConfig.desc}}</p>\n @if((dataNotFoundConfig.btnUrl || dataNotFoundConfig?.btnClick) && dataNotFoundConfig.btnText) {\n <button mat-flat-button color=\"primary\" class=\"tis-text-upper\"\n (click)=\"handleButtonClick(dataNotFoundConfig)\">\n <mat-icon>add</mat-icon>\n {{dataNotFoundConfig.btnText}}\n </button>\n }\n @if((dataNotFoundConfig.secondBtnUrl || dataNotFoundConfig?.secondBtnClick) && dataNotFoundConfig.secondBtnText) {\n <button mat-stroked-button color=\"primary\" class=\"tis-text-upper\"\n (click)=\"handleSecondButtonClick(dataNotFoundConfig)\">\n <mat-icon>add</mat-icon>\n {{dataNotFoundConfig.secondBtnText}}\n </button>\n }\n </div>\n }\n\n }\n\n }\n\n </div>\n </div>\n</section>", styles: ["::ng-deep .sub-main-content{border:0px solid #f00;margin-top:56px;height:calc(100% - 56px);padding:15px;overflow:auto}.header-title{margin-top:8px;padding:7px 10px;color:#969a9c}.header-title h3{font-size:20px!important;font-weight:700}.header-menu{border:0px solid red;background:#fff;margin-top:1px;margin-bottom:0}.w-100{width:100%}.mat-mdc-table-sticky-border-elem-right{border-left:1px solid #e0e0e087}.mat-mdc-table-sticky-border-elem-left{border-right:1px solid #e0e0e087}.search-mat-form-field{width:100%}.filter-applied-section{overflow:auto}.tis-detail-row{height:0!important}.tis-element-detail-wrapper{overflow:hidden;max-height:0;transition:max-height 225ms ease}.tis-element-detail-wrapper-expanded{max-height:500px}.tis-table-bordered{border-collapse:collapse;width:100%}.tis-table-bordered th,.tis-table-bordered td{border-left:1px solid #e0e0e0}.tis-table-bordered th:first-child,.tis-table-bordered td:first-child{border-left:0px solid #e0e0e0}.tis-table-bordered .bg-unset{background-color:unset!important}@media (max-width: 575.98px){.search-mat-form-field{width:100%!important}}@media (min-width: 576px) and (max-width: 767.98px){.search-mat-form-field{width:100%!important}}\n"], dependencies: [{ kind: "directive", type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i4.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i6.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i6.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i6.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i3$1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i8.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i8.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i8.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "directive", type: i10.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i10$1.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: i4$1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i12$1.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "component", type: i13$1.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i13$1.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i13$1.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i13$1.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i13$1.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i13$1.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i13$1.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i13$1.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i13$1.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i13$1.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: i13$1.MatNoDataRow, selector: "ng-template[matNoDataRow]" }, { kind: "component", type: i12.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "directive", type: i15.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i15.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "directive", type: i13.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i13.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i13.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "directive", type: ScrollingDirective, selector: "[appScrolling]", inputs: ["appScrolling"] }, { kind: "component", type: TisColumnsBtnComponent, selector: "tis-columns-btn", inputs: ["columnCustomizationUrlConfig", "t", "componentName", "defaultColumns", "columns", "skipTranslation", "customColumns"], outputs: ["displayedColumnsChange", "fromStartColumnNumberChange", "fromEndColumnNumberChange"] }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.DecimalPipe, name: "number" }, { kind: "pipe", type: TisDatePipe, name: "tisDate" }, { kind: "pipe", type: TisDateTimePipe, name: "tisDateTime" }, { kind: "pipe", type: TisDateTimeWithSecondsPipe, name: "tisDateTimeWithSeconds" }] });
1576
2527
  }
1577
2528
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.7", ngImport: i0, type: TisSmartTableViewerComponent, decorators: [{
1578
2529
  type: Component,
1579
- args: [{ selector: 'tis-smart-table-viewer', standalone: false, providers: [CdkColumnDef], template: "<section [class.tis-page]=\"!hideHeader\">\n <div class=\"tis-page-header\" *ngIf=\"!hideHeader\">\n <nav aria-label=\"tis-breadcrumb\">\n <ol class=\"tis-breadcrumb\">\n <li class=\"tis-breadcrumb-item\"><a href=\"javascript:;\" [routerLink]=\"homeUrl\">{{t?.home}}</a></li>\n @for(breadcrumb of breadcrumbs; track breadcrumb) {\n <li class=\"tis-breadcrumb-item\" *ngIf=\"breadcrumb?.url\">\n <a href=\"javascript:;\" (click)=\"goToUrl(breadcrumb.url)\">{{breadcrumb?.name}}</a>\n </li>\n }\n <li class=\"tis-breadcrumb-item active\">\n {{mainTitle}}\n </li>\n </ol>\n </nav>\n <ng-content select=\"[slot='top-buttons-section']\"></ng-content>\n </div>\n <h1 class=\"tis-page-title\" *ngIf=\"!hideHeader\">{{mainTitle}}</h1>\n <div class=\"tis-page-body\">\n <div class=\"tis-page-body-content\">\n\n @if(initialLoading){\n <div class=\"tis-d-flex tis-justify-content-center pb-2 pt-7\">\n <mat-progress-spinner color=\"primary\" mode=\"indeterminate\" [diameter]=\"60\"></mat-progress-spinner>\n </div>\n } @else {\n\n @if ((dataSource?.totalDataLength$ | async) || (dataSource?.loading$ | async) || search ||\n filterHasNonEmptyValue || showFilterButtonSection || displayAfterFilterRemoved) {\n <div class=\"tis-table-container\">\n @if(!hideTableHeader){\n <div class=\"tis-table-container-header\">\n <ul class=\"tis-inline-group\">\n <li class=\"tis-inline-group-item\">\n <tis-columns-btn [columnCustomizationUrlConfig]=\"columnCustomizationUrlConfig\" [t]=\"t\"\n [componentName]=\"componentName\" [defaultColumns]=\"defaultColumns\" [columns]=\"columns\"\n (displayedColumnsChange)=\"onChangeDisplayColumns($event)\"\n (fromStartColumnNumberChange)=\"onChangeFromStartColumnNumber($event)\"\n (fromEndColumnNumberChange)=\"onChangeFromEndColumnNumber($event)\"></tis-columns-btn>\n </li>\n <ng-content select=\"[slot='filter-button-section']\"></ng-content>\n </ul>\n <div class=\"flex items-center\">\n <ul class=\"tis-inline-group\">\n <ng-content select=\"[slot='filter-right-button-section']\"></ng-content>\n </ul>\n @if(!isMobile && searchPlaceholder && searchPlaceholder != ''){\n <mat-form-field\n class=\"custom-mat-form-field-mb-0 search-mat-form-field ml-3 tis-table-search-field\"\n appearance=\"outline\">\n <span class=\"material-icons\" matPrefix>search</span>\n <input matInput [formControl]=\"searchCtrl\" [placeholder]=\"searchPlaceholder\">\n <span class=\"material-icons mr-2 tis-curser-pointer\" matSuffix\n (click)=\"searchCtrl.setValue('')\"\n *ngIf=\"searchCtrl.value && searchCtrl.value != ''\">close</span>\n </mat-form-field>\n }\n </div>\n </div>\n }\n\n @if (filterFormGroup) {\n\n <ng-content select=\"[slot='filter-form-section']\"></ng-content>\n\n @if(finalSelectedFilterValuesToDisplay.length && filterApplied) {\n <div class=\"flex gap-3 mb-3 filter-applied-section md-hide-scrollbar\">\n @for(v of finalSelectedFilterValuesToDisplay; track v) {\n @if (v) {\n <span class=\"tis-filter-badge\" style=\"white-space: nowrap;\">\n @if(v.labelKey && v.labelKey != '' && (v.valueKey || v.value)) {\n <span class=\"font-semibold\"> {{v.labelKey }} </span>\n }\n @if(v.valueKey) {\n {{v.valueKey }}\n } @else {\n {{v.value }}\n }\n <span class=\"material-icons tis-curser-pointer\"\n (click)=\"removeParticularFilter(v)\">cancel</span>\n </span>\n }\n }\n </div>\n }\n }\n\n @if(isMobile && searchPlaceholder && searchPlaceholder != ''){\n <mat-form-field\n class=\"custom-mat-form-field-mb-0 search-mat-form-field mb-3 tis-table-search-field\"\n appearance=\"outline\">\n <span class=\"material-icons\" matPrefix>search</span>\n <input matInput [formControl]=\"searchCtrl\" [placeholder]=\"searchPlaceholder\">\n <span class=\"material-icons mr-2 tis-curser-pointer\" matSuffix\n (click)=\"searchCtrl.setValue('')\"\n *ngIf=\"searchCtrl.value && searchCtrl.value != ''\">close</span>\n </mat-form-field>\n }\n\n \n @if(loaderPosition == 'top'){\n @if(dataSource?.loading$ | async){\n <div class=\"tis-d-flex tis-justify-content-center py-2\">\n <mat-progress-spinner color=\"primary\" mode=\"indeterminate\" [diameter]=\"loadingSpinnerDiameter\"></mat-progress-spinner>\n </div>\n }\n }\n <div class=\"tis-table-container-body\">\n <div class=\"tis-table-wrapper\" [appScrolling]=\"true\">\n\n <!--Table Here-->\n <table mat-table matSort [dataSource]=\"dataSource\" class=\"tis-table\" [class.tis-table-bordered]=\"disableBorderedView == false\" cdkDropList (cdkDropListDropped)=\"drop($event)\" [cdkDropListLockAxis]=\"'y'\" multiTemplateDataRows>\n\n @if (enableRowsSelection) {\n <ng-container matColumnDef=\"Select\">\n <th mat-header-cell *matHeaderCellDef>\n @if (enableAllRowsSelection) {\n <mat-checkbox color=\"primary\" (change)=\"$event ? toggleAllRows() : null\"\n [checked]=\"isAllRowsSelected\"\n [indeterminate]=\"selection.hasValue() && !isAllRowsSelected\">\n </mat-checkbox>\n }\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-checkbox color=\"primary\" (click)=\"stopPropagation($event)\" (change)=\"$event ? toggleSelection($event, row) : null\" [checked]=\"isChecked(row)\"></mat-checkbox>\n </td>\n </ng-container>\n }\n\n @for(column of autoRenderColumns; track column.serverKeyCode; let i = $index; let l = $last){\n <!-- [sticky]=\"i < startStickyColumnCount\" [stickyEnd]=\"i > (autoRenderColumns?.length - endStickyColumnCount)\" -->\n <ng-container [matColumnDef]=\"column?.columnDef || column.name\" [sticky]=\"isStickyStart(column?.columnDef || column.name)\" [stickyEnd]=\"isStickyEnd(column?.columnDef || column.name)\">\n @if(column.type == 'expand') {\n <th mat-header-cell *matHeaderCellDef [ngClass]=\"getColumnClasses(column)\">\n <div style=\"display: flex; align-items: center; gap: 5px;\">\n <span>{{ column?.columnName ? column?.columnName : t[column.name] }}</span>\n <mat-icon *ngIf=\"!isAllExpanded\">expand_more</mat-icon>\n <mat-icon *ngIf=\"isAllExpanded\">expand_less</mat-icon>\n </div>\n </th>\n }\n @else if(column.sort) {\n <th mat-header-cell mat-sort-header *matHeaderCellDef [ngClass]=\"getColumnClasses(column)\">\n {{ column?.columnName ? column?.columnName : t[column.name] }}\n </th>\n }\n @else {\n <th mat-header-cell *matHeaderCellDef [ngClass]=\"getColumnClasses(column)\">\n {{ column?.columnName ? column?.columnName : t[column.name] }}\n </th>\n }\n \n\n @if(column.type == 'date'){\n <td mat-cell *matCellDef=\"let element\" class=\"1al-{{column.align}} 1ty-{{column.type}}\" >\n <p [class.tis-a]=\"column.clickFn\" (click)=\"column?.clickFn?.(element, $event)\">\n {{ column.valueKey ? (getNestedValue(element, column.valueKey) | tisDate) : ''}}\n </p>\n </td>\n } @else if(column.type == 'date-time'){\n <td mat-cell *matCellDef=\"let element\" class=\"2al-{{column.align}} 2ty-{{column.type}}\">\n <p [class.tis-a]=\"column.clickFn\" (click)=\"column?.clickFn?.(element, $event)\">\n {{ column.valueKey ? (getNestedValue(element, column.valueKey) | tisDateTime) : ''}}\n </p>\n </td>\n } @else if(column.type == 'date-time-with-seconds'){\n <td mat-cell *matCellDef=\"let element\" class=\"2al-{{column.align}} 2ty-{{column.type}}\">\n <p [class.tis-a]=\"column.clickFn\" (click)=\"column?.clickFn?.(element, $event)\">\n {{ column.valueKey ? (getNestedValue(element, column.valueKey) | tisDateTimeWithSeconds) : ''}}\n </p>\n </td>\n } @else {\n <td mat-cell *matCellDef=\"let element\" class=\"3al-{{column.align}} 3ty-{{column.type}}\" [ngClass]=\"getColumnClasses(column)\">\n <p [class.tis-a]=\"column.clickFn\" (click)=\"column?.clickFn?.(element, $event)\">\n @if (column.type == 'quantity') {\n {{ column.valueKey ? (getNestedValue(element, column.valueKey) | number : '1.4-4') : '-' }}\n } @else if (column.type == 'money') {\n {{ column.valueKey && (getNestedValue(element, column.valueKey))?.toFixed(2) }}\n } @else {\n {{ column.valueKey && getNestedValue(element, column.valueKey) }}\n }\n </p>\n </td>\n }\n </ng-container>\n\n }\n\n\n @for(column of templateRenderColumns; track column.serverKeyCode; let i = $index; let l = $last){\n <!-- [sticky]=\"i < startStickyColumnCount\" [stickyEnd]=\"l\" -->\n <ng-container [matColumnDef]=\"column?.columnDef || column.name\" [sticky]=\"isStickyStart(column?.columnDef || column.name)\" [stickyEnd]=\"isStickyEnd(column?.columnDef || column.name)\">\n @if(column.type == 'expand') {\n <th mat-header-cell *matHeaderCellDef [ngClass]=\"getColumnClasses(column)\">\n <div style=\"display: flex; align-items: center; gap: 5px; cursor: pointer;\" (click)=\"expandAllRow()\">\n <span>{{ column?.columnName ? column?.columnName : t[column.name] }}</span>\n <mat-icon *ngIf=\"!isAllExpanded\">expand_more</mat-icon>\n <mat-icon *ngIf=\"isAllExpanded\">expand_less</mat-icon>\n </div>\n </th>\n }\n @else if(column.sort) {\n <th mat-header-cell *matHeaderCellDef mat-sort-header [ngClass]=\"getColumnClasses(column)\">\n {{ column?.columnName ? column?.columnName : t[column.name] }}\n </th>\n }\n @else {\n <th mat-header-cell *matHeaderCellDef [ngClass]=\"getColumnClasses(column)\">\n {{ column?.columnName ? column?.columnName : t[column.name] }}\n </th>\n }\n <td mat-cell *matCellDef=\"let element\" class=\"4al-{{column.align}} 4ty-{{column.type}}\" [ngClass]=\"getColumnClasses(column)\">\n <ng-container *ngIf=\"column.template as template\">\n <ng-container *ngTemplateOutlet=\"template; context: { colDef: column, colData: element }\"></ng-container>\n </ng-container>\n </td>\n </ng-container>\n }\n\n <!--Drag Column Def Start-->\n <ng-container [matColumnDef]=\"'drag'\" >\n <th mat-header-cell *matHeaderCellDef>\n --\n </th>\n <td mat-cell *matCellDef=\"let element\" class=\"5al-drag 5ty-drag\">\n <mat-icon cdkDragHandle class=\"tis-curser-pointer\" style=\"color: rgba(0, 0, 0, 0.54); font-size: 19px; width: 19px; height: 19px;\">drag_indicator</mat-icon>\n </td>\n </ng-container>\n <!--Drag Column Def End-->\n\n <!-- Expanded Content Column - The detail row is made up of this one column that spans across all columns -->\n <ng-container matColumnDef=\"expandedDetail\">\n <td mat-cell *matCellDef=\"let element\" [attr.colspan]=\"displayedColumns.length\" [style.border-bottom-width]=\"element.expanded ? '1px' : '0px'\" style=\"padding: 0px !important;\">\n <div class=\"tis-element-detail-wrapper\" [class.tis-element-detail-wrapper-expanded]=\"element.expanded\">\n <ng-container *ngIf=\"expandedTemplate as template\">\n <ng-container *ngTemplateOutlet=\"template; context: { colData: element }\"></ng-container>\n </ng-container>\n </div>\n </td>\n </ng-container>\n\n\n <tr class=\"mat-row\" *matNoDataRow>\n <td class=\"mat-cell\" [attr.colspan]=\"displayedColumns.length\">\n <div class=\"tis-data-not-found\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"130\" height=\"126.89\" viewBox=\"0 0 647.63626 632.17383\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" role=\"img\" artist=\"Katerina Limpitsouni\" source=\"https://undraw.co/\">\n <path d=\"M687.3279,276.08691H512.81813a15.01828,15.01828,0,0,0-15,15v387.85l-2,.61005-42.81006,13.11a8.00676,8.00676,0,0,1-9.98974-5.31L315.678,271.39691a8.00313,8.00313,0,0,1,5.31006-9.99l65.97022-20.2,191.25-58.54,65.96972-20.2a7.98927,7.98927,0,0,1,9.99024,5.3l32.5498,106.32Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"#f2f2f2\"/>\n <path d=\"M725.408,274.08691l-39.23-128.14a16.99368,16.99368,0,0,0-21.23-11.28l-92.75,28.39L380.95827,221.60693l-92.75,28.4a17.0152,17.0152,0,0,0-11.28028,21.23l134.08008,437.93a17.02661,17.02661,0,0,0,16.26026,12.03,16.78926,16.78926,0,0,0,4.96972-.75l63.58008-19.46,2-.62v-2.09l-2,.61-64.16992,19.65a15.01489,15.01489,0,0,1-18.73-9.95l-134.06983-437.94a14.97935,14.97935,0,0,1,9.94971-18.73l92.75-28.4,191.24024-58.54,92.75-28.4a15.15551,15.15551,0,0,1,4.40966-.66,15.01461,15.01461,0,0,1,14.32032,10.61l39.0498,127.56.62012,2h2.08008Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"#3f3d56\"/>\n <path d=\"M398.86279,261.73389a9.0157,9.0157,0,0,1-8.61133-6.3667l-12.88037-42.07178a8.99884,8.99884,0,0,1,5.9712-11.24023l175.939-53.86377a9.00867,9.00867,0,0,1,11.24072,5.9707l12.88037,42.07227a9.01029,9.01029,0,0,1-5.9707,11.24072L401.49219,261.33887A8.976,8.976,0,0,1,398.86279,261.73389Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"var(--tis-primary, var(--mat-sys-primary, #3838a2))\"/>\n <circle cx=\"190.15351\" cy=\"24.95465\" r=\"20\" fill=\"var(--tis-primary, var(--mat-sys-primary, #3838a2))\"/>\n <circle cx=\"190.15351\" cy=\"24.95465\" r=\"12.66462\" fill=\"#fff\"/>\n <path d=\"M878.81836,716.08691h-338a8.50981,8.50981,0,0,1-8.5-8.5v-405a8.50951,8.50951,0,0,1,8.5-8.5h338a8.50982,8.50982,0,0,1,8.5,8.5v405A8.51013,8.51013,0,0,1,878.81836,716.08691Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"#e6e6e6\"/>\n <path d=\"M723.31813,274.08691h-210.5a17.02411,17.02411,0,0,0-17,17v407.8l2-.61v-407.19a15.01828,15.01828,0,0,1,15-15H723.93825Zm183.5,0h-394a17.02411,17.02411,0,0,0-17,17v458a17.0241,17.0241,0,0,0,17,17h394a17.0241,17.0241,0,0,0,17-17v-458A17.02411,17.02411,0,0,0,906.81813,274.08691Zm15,475a15.01828,15.01828,0,0,1-15,15h-394a15.01828,15.01828,0,0,1-15-15v-458a15.01828,15.01828,0,0,1,15-15h394a15.01828,15.01828,0,0,1,15,15Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"#3f3d56\"/>\n <path d=\"M801.81836,318.08691h-184a9.01015,9.01015,0,0,1-9-9v-44a9.01016,9.01016,0,0,1,9-9h184a9.01016,9.01016,0,0,1,9,9v44A9.01015,9.01015,0,0,1,801.81836,318.08691Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"var(--tis-primary, var(--mat-sys-primary, #3838a2))\"/>\n <circle cx=\"433.63626\" cy=\"105.17383\" r=\"20\" fill=\"var(--tis-primary, var(--mat-sys-primary, #3838a2))\"/>\n <circle cx=\"433.63626\" cy=\"105.17383\" r=\"12.18187\" fill=\"#fff\"/>\n </svg>\n <h5 class=\"tis-h5\">{{dataNotFoundConfig.title}}</h5>\n </div>\n </td>\n </tr>\n\n <!-- Apply Drag and Drop to tbody -->\n @if(enableDragNDrop) {\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns\" [ngStyle]=\"{'background-color': getRowBackground(row) || 'inherit'}\" [class.tis-curser-pointer]=\"isExpandedRow\" (click)=\"(isExpansion && isExpandedRow) ? toggleExpand(row) : null\" cdkDrag></tr>\n }\n\n @if(!enableDragNDrop) {\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns\" [ngStyle]=\"{'background-color': getRowBackground(row) || 'inherit'}\" [class.tis-curser-pointer]=\"isExpandedRow\" (click)=\"(isExpansion && isExpandedRow) ? toggleExpand(row) : null\"></tr>\n } \n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: ['expandedDetail']\" class=\"tis-detail-row\"></tr>\n </table>\n <!--Table End-->\n\n </div>\n @if(loaderPosition == 'bottom'){\n @if(dataSource?.loading$ | async){\n <div class=\"tis-d-flex tis-justify-content-center py-2\">\n <mat-progress-spinner color=\"primary\" mode=\"indeterminate\" [diameter]=\"loadingSpinnerDiameter\"></mat-progress-spinner>\n </div>\n }\n }\n @if (!hidePaginator) {\n <div class=\"tis-table-paginator\">\n <mat-paginator [length]=\"dataSource?.totalDataLength?.value\" [pageSize]=\"pageSize\"\n [pageSizeOptions]=\"pageSizeOptions\" showFirstLastButtons></mat-paginator>\n </div>\n }\n </div>\n </div>\n } @else {\n\n @if(dataNotFoundConfig) {\n <div class=\"tis-data-not-found\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"130\" height=\"126.89\" viewBox=\"0 0 647.63626 632.17383\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" role=\"img\" artist=\"Katerina Limpitsouni\" source=\"https://undraw.co/\">\n <path d=\"M687.3279,276.08691H512.81813a15.01828,15.01828,0,0,0-15,15v387.85l-2,.61005-42.81006,13.11a8.00676,8.00676,0,0,1-9.98974-5.31L315.678,271.39691a8.00313,8.00313,0,0,1,5.31006-9.99l65.97022-20.2,191.25-58.54,65.96972-20.2a7.98927,7.98927,0,0,1,9.99024,5.3l32.5498,106.32Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"#f2f2f2\"/>\n <path d=\"M725.408,274.08691l-39.23-128.14a16.99368,16.99368,0,0,0-21.23-11.28l-92.75,28.39L380.95827,221.60693l-92.75,28.4a17.0152,17.0152,0,0,0-11.28028,21.23l134.08008,437.93a17.02661,17.02661,0,0,0,16.26026,12.03,16.78926,16.78926,0,0,0,4.96972-.75l63.58008-19.46,2-.62v-2.09l-2,.61-64.16992,19.65a15.01489,15.01489,0,0,1-18.73-9.95l-134.06983-437.94a14.97935,14.97935,0,0,1,9.94971-18.73l92.75-28.4,191.24024-58.54,92.75-28.4a15.15551,15.15551,0,0,1,4.40966-.66,15.01461,15.01461,0,0,1,14.32032,10.61l39.0498,127.56.62012,2h2.08008Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"#3f3d56\"/>\n <path d=\"M398.86279,261.73389a9.0157,9.0157,0,0,1-8.61133-6.3667l-12.88037-42.07178a8.99884,8.99884,0,0,1,5.9712-11.24023l175.939-53.86377a9.00867,9.00867,0,0,1,11.24072,5.9707l12.88037,42.07227a9.01029,9.01029,0,0,1-5.9707,11.24072L401.49219,261.33887A8.976,8.976,0,0,1,398.86279,261.73389Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"var(--tis-primary, var(--mat-sys-primary, #3838a2))\"/>\n <circle cx=\"190.15351\" cy=\"24.95465\" r=\"20\" fill=\"var(--tis-primary, var(--mat-sys-primary, #3838a2))\"/>\n <circle cx=\"190.15351\" cy=\"24.95465\" r=\"12.66462\" fill=\"#fff\"/>\n <path d=\"M878.81836,716.08691h-338a8.50981,8.50981,0,0,1-8.5-8.5v-405a8.50951,8.50951,0,0,1,8.5-8.5h338a8.50982,8.50982,0,0,1,8.5,8.5v405A8.51013,8.51013,0,0,1,878.81836,716.08691Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"#e6e6e6\"/>\n <path d=\"M723.31813,274.08691h-210.5a17.02411,17.02411,0,0,0-17,17v407.8l2-.61v-407.19a15.01828,15.01828,0,0,1,15-15H723.93825Zm183.5,0h-394a17.02411,17.02411,0,0,0-17,17v458a17.0241,17.0241,0,0,0,17,17h394a17.0241,17.0241,0,0,0,17-17v-458A17.02411,17.02411,0,0,0,906.81813,274.08691Zm15,475a15.01828,15.01828,0,0,1-15,15h-394a15.01828,15.01828,0,0,1-15-15v-458a15.01828,15.01828,0,0,1,15-15h394a15.01828,15.01828,0,0,1,15,15Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"#3f3d56\"/>\n <path d=\"M801.81836,318.08691h-184a9.01015,9.01015,0,0,1-9-9v-44a9.01016,9.01016,0,0,1,9-9h184a9.01016,9.01016,0,0,1,9,9v44A9.01015,9.01015,0,0,1,801.81836,318.08691Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"var(--tis-primary, var(--mat-sys-primary, #3838a2))\"/>\n <circle cx=\"433.63626\" cy=\"105.17383\" r=\"20\" fill=\"var(--tis-primary, var(--mat-sys-primary, #3838a2))\"/>\n <circle cx=\"433.63626\" cy=\"105.17383\" r=\"12.18187\" fill=\"#fff\"/>\n </svg>\n <h5 class=\"tis-h5\">{{dataNotFoundConfig.title}}</h5>\n <p class=\"tis-p\">{{dataNotFoundConfig.desc}}</p>\n @if((dataNotFoundConfig.btnUrl || dataNotFoundConfig?.btnClick) && dataNotFoundConfig.btnText) {\n <button mat-flat-button color=\"primary\" class=\"tis-text-upper\"\n (click)=\"handleButtonClick(dataNotFoundConfig)\">\n <mat-icon>add</mat-icon>\n {{dataNotFoundConfig.btnText}}\n </button>\n }\n @if((dataNotFoundConfig.secondBtnUrl || dataNotFoundConfig?.secondBtnClick) && dataNotFoundConfig.secondBtnText) {\n <button mat-stroked-button color=\"primary\" class=\"tis-text-upper\"\n (click)=\"handleSecondButtonClick(dataNotFoundConfig)\">\n <mat-icon>add</mat-icon>\n {{dataNotFoundConfig.secondBtnText}}\n </button>\n }\n </div>\n }\n\n }\n\n }\n\n </div>\n </div>\n</section>", styles: ["::ng-deep .sub-main-content{border:0px solid #f00;margin-top:56px;height:calc(100% - 56px);padding:15px;overflow:auto}.header-title{margin-top:8px;padding:7px 10px;color:#969a9c}.header-title h3{font-size:20px!important;font-weight:700}.header-menu{border:0px solid red;background:#fff;margin-top:1px;margin-bottom:0}.w-100{width:100%}.mat-mdc-table-sticky-border-elem-right{border-left:1px solid #e0e0e087}.mat-mdc-table-sticky-border-elem-left{border-right:1px solid #e0e0e087}.search-mat-form-field{width:100%}.filter-applied-section{overflow:auto}.tis-detail-row{height:0!important}.tis-element-detail-wrapper{overflow:hidden;max-height:0;transition:max-height 225ms ease}.tis-element-detail-wrapper-expanded{max-height:500px}.tis-table-bordered{border-collapse:collapse;width:100%}.tis-table-bordered th,.tis-table-bordered td{border-left:1px solid #e0e0e0}.tis-table-bordered th:first-child,.tis-table-bordered td:first-child{border-left:0px solid #e0e0e0}.tis-table-bordered .bg-unset{background-color:unset!important}@media (max-width: 575.98px){.search-mat-form-field{width:100%!important}}@media (min-width: 576px) and (max-width: 767.98px){.search-mat-form-field{width:100%!important}}\n"] }]
2530
+ args: [{ selector: 'tis-smart-table-viewer', standalone: false, providers: [CdkColumnDef], template: "<section [class.tis-page]=\"!hideHeader\">\n <div class=\"tis-page-header\" *ngIf=\"!hideHeader\">\n <nav aria-label=\"tis-breadcrumb\">\n <ol class=\"tis-breadcrumb\">\n <li class=\"tis-breadcrumb-item\"><a href=\"javascript:;\" [routerLink]=\"homeUrl\">{{t?.home}}</a></li>\n @for(breadcrumb of breadcrumbs; track trackByBreadcrumb($index, breadcrumb)) {\n <li class=\"tis-breadcrumb-item\" *ngIf=\"breadcrumb?.url\">\n <a href=\"javascript:;\" (click)=\"goToUrl(breadcrumb.url)\">{{breadcrumb?.name}}</a>\n </li>\n }\n <li class=\"tis-breadcrumb-item active\">\n {{mainTitle}}\n </li>\n </ol>\n </nav>\n <ng-content select=\"[slot='top-buttons-section']\"></ng-content>\n </div>\n <h1 class=\"tis-page-title\" *ngIf=\"!hideHeader\">{{mainTitle}}</h1>\n <div class=\"tis-page-body\">\n <div class=\"tis-page-body-content\">\n\n @if(initialLoading){\n <div class=\"tis-d-flex tis-justify-content-center pb-2 pt-7\">\n <mat-progress-spinner color=\"primary\" mode=\"indeterminate\" [diameter]=\"60\"></mat-progress-spinner>\n </div>\n } @else {\n\n @if ((dataSource?.totalDataLength$ | async) || (dataSource?.loading$ | async) || search ||\n filterHasNonEmptyValue || showFilterButtonSection || displayAfterFilterRemoved) {\n <div class=\"tis-table-container\">\n @if(!hideTableHeader){\n <div class=\"tis-table-container-header\">\n <ul class=\"tis-inline-group\">\n <li class=\"tis-inline-group-item\">\n <tis-columns-btn [columnCustomizationUrlConfig]=\"columnCustomizationUrlConfig\" [t]=\"t\"\n [componentName]=\"componentName\" [defaultColumns]=\"defaultColumns\" [columns]=\"columns\"\n (displayedColumnsChange)=\"onChangeDisplayColumns($event)\"\n (fromStartColumnNumberChange)=\"onChangeFromStartColumnNumber($event)\"\n (fromEndColumnNumberChange)=\"onChangeFromEndColumnNumber($event)\"></tis-columns-btn>\n </li>\n <ng-content select=\"[slot='filter-button-section']\"></ng-content>\n </ul>\n <div class=\"flex items-center\">\n <ul class=\"tis-inline-group\">\n <ng-content select=\"[slot='filter-right-button-section']\"></ng-content>\n </ul>\n @if(!isMobile && searchPlaceholder && searchPlaceholder != ''){\n <mat-form-field\n class=\"custom-mat-form-field-mb-0 search-mat-form-field ml-3 tis-table-search-field\"\n appearance=\"outline\">\n <span class=\"material-icons\" matPrefix>search</span>\n <input matInput [formControl]=\"searchCtrl\" [placeholder]=\"searchPlaceholder\">\n <span class=\"material-icons mr-2 tis-curser-pointer\" matSuffix\n (click)=\"searchCtrl.setValue('')\"\n *ngIf=\"searchCtrl.value && searchCtrl.value != ''\">close</span>\n </mat-form-field>\n }\n </div>\n </div>\n }\n\n @if (filterFormGroup) {\n\n <ng-content select=\"[slot='filter-form-section']\"></ng-content>\n\n @if(finalSelectedFilterValuesToDisplay.length && filterApplied) {\n <div class=\"flex gap-3 mb-3 filter-applied-section md-hide-scrollbar\">\n @for(v of finalSelectedFilterValuesToDisplay; track trackByFilterValue($index, v)) {\n @if (v) {\n <span class=\"tis-filter-badge\" style=\"white-space: nowrap;\">\n @if(v.labelKey && v.labelKey != '' && (v.valueKey || v.value)) {\n <span class=\"font-semibold\"> {{v.labelKey }} </span>\n }\n @if(v.valueKey) {\n {{v.valueKey }}\n } @else {\n {{v.value }}\n }\n <span class=\"material-icons tis-curser-pointer\"\n (click)=\"removeParticularFilter(v)\">cancel</span>\n </span>\n }\n }\n </div>\n }\n }\n\n @if(isMobile && searchPlaceholder && searchPlaceholder != ''){\n <mat-form-field\n class=\"custom-mat-form-field-mb-0 search-mat-form-field mb-3 tis-table-search-field\"\n appearance=\"outline\">\n <span class=\"material-icons\" matPrefix>search</span>\n <input matInput [formControl]=\"searchCtrl\" [placeholder]=\"searchPlaceholder\">\n <span class=\"material-icons mr-2 tis-curser-pointer\" matSuffix\n (click)=\"searchCtrl.setValue('')\"\n *ngIf=\"searchCtrl.value && searchCtrl.value != ''\">close</span>\n </mat-form-field>\n }\n\n \n @if(loaderPosition == 'top'){\n @if(dataSource?.loading$ | async){\n <div class=\"tis-d-flex tis-justify-content-center py-2\">\n <mat-progress-spinner color=\"primary\" mode=\"indeterminate\" [diameter]=\"loadingSpinnerDiameter\"></mat-progress-spinner>\n </div>\n }\n }\n <div class=\"tis-table-container-body\">\n <div class=\"tis-table-wrapper\" [appScrolling]=\"true\">\n\n <!--Table Here-->\n <table mat-table matSort [dataSource]=\"dataSource\" class=\"tis-table\" [class.tis-table-bordered]=\"disableBorderedView == false\" cdkDropList (cdkDropListDropped)=\"drop($event)\" [cdkDropListLockAxis]=\"'y'\" multiTemplateDataRows>\n\n @if (enableRowsSelection) {\n <ng-container matColumnDef=\"Select\">\n <th mat-header-cell *matHeaderCellDef>\n @if (enableAllRowsSelection) {\n <mat-checkbox color=\"primary\" (change)=\"$event ? toggleAllRows() : null\"\n [checked]=\"isAllRowsSelected\"\n [indeterminate]=\"selection.hasValue() && !isAllRowsSelected\">\n </mat-checkbox>\n }\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-checkbox color=\"primary\" (click)=\"stopPropagation($event)\" (change)=\"$event ? toggleSelection($event, row) : null\" [checked]=\"isChecked(row)\"></mat-checkbox>\n </td>\n </ng-container>\n }\n\n @for(column of autoRenderColumns; track trackByAutoColumn($index, column); let i = $index; let l = $last){\n <!-- [sticky]=\"i < startStickyColumnCount\" [stickyEnd]=\"i > (autoRenderColumns?.length - endStickyColumnCount)\" -->\n <ng-container [matColumnDef]=\"column?.columnDef || column.name\" [sticky]=\"isStickyStart(column?.columnDef || column.name)\" [stickyEnd]=\"isStickyEnd(column?.columnDef || column.name)\">\n @if(column.type == 'expand') {\n <th mat-header-cell *matHeaderCellDef [ngClass]=\"getColumnClasses(column)\">\n <div style=\"display: flex; align-items: center; gap: 5px;\">\n <span>{{ column?.columnName ? column?.columnName : t[column.name] }}</span>\n <mat-icon *ngIf=\"!isAllExpanded\">expand_more</mat-icon>\n <mat-icon *ngIf=\"isAllExpanded\">expand_less</mat-icon>\n </div>\n </th>\n }\n @else if(column.sort) {\n <th mat-header-cell mat-sort-header *matHeaderCellDef [ngClass]=\"getColumnClasses(column)\">\n {{ column?.columnName ? column?.columnName : t[column.name] }}\n </th>\n }\n @else {\n <th mat-header-cell *matHeaderCellDef [ngClass]=\"getColumnClasses(column)\">\n {{ column?.columnName ? column?.columnName : t[column.name] }}\n </th>\n }\n \n\n @if(column.type == 'date'){\n <td mat-cell *matCellDef=\"let element\" class=\"1al-{{column.align}} 1ty-{{column.type}}\" >\n <p [class.tis-a]=\"column.clickFn\" (click)=\"column?.clickFn?.(element, $event)\">\n {{ column.valueKey ? (getNestedValue(element, column.valueKey) | tisDate) : ''}}\n </p>\n </td>\n } @else if(column.type == 'date-time'){\n <td mat-cell *matCellDef=\"let element\" class=\"2al-{{column.align}} 2ty-{{column.type}}\">\n <p [class.tis-a]=\"column.clickFn\" (click)=\"column?.clickFn?.(element, $event)\">\n {{ column.valueKey ? (getNestedValue(element, column.valueKey) | tisDateTime) : ''}}\n </p>\n </td>\n } @else if(column.type == 'date-time-with-seconds'){\n <td mat-cell *matCellDef=\"let element\" class=\"2al-{{column.align}} 2ty-{{column.type}}\">\n <p [class.tis-a]=\"column.clickFn\" (click)=\"column?.clickFn?.(element, $event)\">\n {{ column.valueKey ? (getNestedValue(element, column.valueKey) | tisDateTimeWithSeconds) : ''}}\n </p>\n </td>\n } @else {\n <td mat-cell *matCellDef=\"let element\" class=\"3al-{{column.align}} 3ty-{{column.type}}\" [ngClass]=\"getColumnClasses(column)\">\n <p [class.tis-a]=\"column.clickFn\" (click)=\"column?.clickFn?.(element, $event)\">\n @if (column.type == 'quantity') {\n {{ column.valueKey ? (getNestedValue(element, column.valueKey) | number : '1.4-4') : '-' }}\n } @else if (column.type == 'money') {\n {{ column.valueKey && (getNestedValue(element, column.valueKey))?.toFixed(2) }}\n } @else {\n {{ column.valueKey && getNestedValue(element, column.valueKey) }}\n }\n </p>\n </td>\n }\n </ng-container>\n\n }\n\n\n @for(column of templateRenderColumns; track trackByTemplateColumn($index, column); let i = $index; let l = $last){\n <!-- [sticky]=\"i < startStickyColumnCount\" [stickyEnd]=\"l\" -->\n <ng-container [matColumnDef]=\"column?.columnDef || column.name\" [sticky]=\"isStickyStart(column?.columnDef || column.name)\" [stickyEnd]=\"isStickyEnd(column?.columnDef || column.name)\">\n @if(column.type == 'expand') {\n <th mat-header-cell *matHeaderCellDef [ngClass]=\"getColumnClasses(column)\">\n <div style=\"display: flex; align-items: center; gap: 5px; cursor: pointer;\" (click)=\"expandAllRow()\">\n <span>{{ column?.columnName ? column?.columnName : t[column.name] }}</span>\n <mat-icon *ngIf=\"!isAllExpanded\">expand_more</mat-icon>\n <mat-icon *ngIf=\"isAllExpanded\">expand_less</mat-icon>\n </div>\n </th>\n }\n @else if(column.sort) {\n <th mat-header-cell *matHeaderCellDef mat-sort-header [ngClass]=\"getColumnClasses(column)\">\n {{ column?.columnName ? column?.columnName : t[column.name] }}\n </th>\n }\n @else {\n <th mat-header-cell *matHeaderCellDef [ngClass]=\"getColumnClasses(column)\">\n {{ column?.columnName ? column?.columnName : t[column.name] }}\n </th>\n }\n <td mat-cell *matCellDef=\"let element\" class=\"4al-{{column.align}} 4ty-{{column.type}}\" [ngClass]=\"getColumnClasses(column)\">\n <ng-container *ngIf=\"column.template as template\">\n <ng-container *ngTemplateOutlet=\"template; context: { colDef: column, colData: element }\"></ng-container>\n </ng-container>\n </td>\n </ng-container>\n }\n\n <!--Drag Column Def Start-->\n <ng-container [matColumnDef]=\"'drag'\" >\n <th mat-header-cell *matHeaderCellDef>\n --\n </th>\n <td mat-cell *matCellDef=\"let element\" class=\"5al-drag 5ty-drag\">\n <mat-icon cdkDragHandle class=\"tis-curser-pointer\" style=\"color: rgba(0, 0, 0, 0.54); font-size: 19px; width: 19px; height: 19px;\">drag_indicator</mat-icon>\n </td>\n </ng-container>\n <!--Drag Column Def End-->\n\n <!-- Expanded Content Column - The detail row is made up of this one column that spans across all columns -->\n <ng-container matColumnDef=\"expandedDetail\">\n <td mat-cell *matCellDef=\"let element\" [attr.colspan]=\"displayedColumns.length\" [style.border-bottom-width]=\"element.expanded ? '1px' : '0px'\" style=\"padding: 0px !important;\">\n <div class=\"tis-element-detail-wrapper\" [class.tis-element-detail-wrapper-expanded]=\"element.expanded\">\n <ng-container *ngIf=\"expandedTemplate as template\">\n <ng-container *ngTemplateOutlet=\"template; context: { colData: element }\"></ng-container>\n </ng-container>\n </div>\n </td>\n </ng-container>\n\n\n <tr class=\"mat-row\" *matNoDataRow>\n <td class=\"mat-cell\" [attr.colspan]=\"displayedColumns.length\">\n <div class=\"tis-data-not-found\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"130\" height=\"126.89\" viewBox=\"0 0 647.63626 632.17383\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" role=\"img\" artist=\"Katerina Limpitsouni\" source=\"https://undraw.co/\">\n <path d=\"M687.3279,276.08691H512.81813a15.01828,15.01828,0,0,0-15,15v387.85l-2,.61005-42.81006,13.11a8.00676,8.00676,0,0,1-9.98974-5.31L315.678,271.39691a8.00313,8.00313,0,0,1,5.31006-9.99l65.97022-20.2,191.25-58.54,65.96972-20.2a7.98927,7.98927,0,0,1,9.99024,5.3l32.5498,106.32Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"#f2f2f2\"/>\n <path d=\"M725.408,274.08691l-39.23-128.14a16.99368,16.99368,0,0,0-21.23-11.28l-92.75,28.39L380.95827,221.60693l-92.75,28.4a17.0152,17.0152,0,0,0-11.28028,21.23l134.08008,437.93a17.02661,17.02661,0,0,0,16.26026,12.03,16.78926,16.78926,0,0,0,4.96972-.75l63.58008-19.46,2-.62v-2.09l-2,.61-64.16992,19.65a15.01489,15.01489,0,0,1-18.73-9.95l-134.06983-437.94a14.97935,14.97935,0,0,1,9.94971-18.73l92.75-28.4,191.24024-58.54,92.75-28.4a15.15551,15.15551,0,0,1,4.40966-.66,15.01461,15.01461,0,0,1,14.32032,10.61l39.0498,127.56.62012,2h2.08008Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"#3f3d56\"/>\n <path d=\"M398.86279,261.73389a9.0157,9.0157,0,0,1-8.61133-6.3667l-12.88037-42.07178a8.99884,8.99884,0,0,1,5.9712-11.24023l175.939-53.86377a9.00867,9.00867,0,0,1,11.24072,5.9707l12.88037,42.07227a9.01029,9.01029,0,0,1-5.9707,11.24072L401.49219,261.33887A8.976,8.976,0,0,1,398.86279,261.73389Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"var(--tis-primary, var(--mat-sys-primary, #3838a2))\"/>\n <circle cx=\"190.15351\" cy=\"24.95465\" r=\"20\" fill=\"var(--tis-primary, var(--mat-sys-primary, #3838a2))\"/>\n <circle cx=\"190.15351\" cy=\"24.95465\" r=\"12.66462\" fill=\"#fff\"/>\n <path d=\"M878.81836,716.08691h-338a8.50981,8.50981,0,0,1-8.5-8.5v-405a8.50951,8.50951,0,0,1,8.5-8.5h338a8.50982,8.50982,0,0,1,8.5,8.5v405A8.51013,8.51013,0,0,1,878.81836,716.08691Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"#e6e6e6\"/>\n <path d=\"M723.31813,274.08691h-210.5a17.02411,17.02411,0,0,0-17,17v407.8l2-.61v-407.19a15.01828,15.01828,0,0,1,15-15H723.93825Zm183.5,0h-394a17.02411,17.02411,0,0,0-17,17v458a17.0241,17.0241,0,0,0,17,17h394a17.0241,17.0241,0,0,0,17-17v-458A17.02411,17.02411,0,0,0,906.81813,274.08691Zm15,475a15.01828,15.01828,0,0,1-15,15h-394a15.01828,15.01828,0,0,1-15-15v-458a15.01828,15.01828,0,0,1,15-15h394a15.01828,15.01828,0,0,1,15,15Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"#3f3d56\"/>\n <path d=\"M801.81836,318.08691h-184a9.01015,9.01015,0,0,1-9-9v-44a9.01016,9.01016,0,0,1,9-9h184a9.01016,9.01016,0,0,1,9,9v44A9.01015,9.01015,0,0,1,801.81836,318.08691Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"var(--tis-primary, var(--mat-sys-primary, #3838a2))\"/>\n <circle cx=\"433.63626\" cy=\"105.17383\" r=\"20\" fill=\"var(--tis-primary, var(--mat-sys-primary, #3838a2))\"/>\n <circle cx=\"433.63626\" cy=\"105.17383\" r=\"12.18187\" fill=\"#fff\"/>\n </svg>\n <h5 class=\"tis-h5\">{{dataNotFoundConfig.title}}</h5>\n </div>\n </td>\n </tr>\n\n <!-- Apply Drag and Drop to tbody -->\n @if(enableDragNDrop) {\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns\" [ngStyle]=\"{'background-color': getRowBackground(row) || 'inherit'}\" [class.tis-curser-pointer]=\"isExpandedRow\" (click)=\"(isExpansion && isExpandedRow) ? toggleExpand(row) : null\" cdkDrag></tr>\n }\n\n @if(!enableDragNDrop) {\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns\" [ngStyle]=\"{'background-color': getRowBackground(row) || 'inherit'}\" [class.tis-curser-pointer]=\"isExpandedRow\" (click)=\"(isExpansion && isExpandedRow) ? toggleExpand(row) : null\"></tr>\n } \n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: ['expandedDetail']\" class=\"tis-detail-row\"></tr>\n </table>\n <!--Table End-->\n\n </div>\n @if(loaderPosition == 'bottom'){\n @if(dataSource?.loading$ | async){\n <div class=\"tis-d-flex tis-justify-content-center py-2\">\n <mat-progress-spinner color=\"primary\" mode=\"indeterminate\" [diameter]=\"loadingSpinnerDiameter\"></mat-progress-spinner>\n </div>\n }\n }\n @if (!hidePaginator) {\n <div class=\"tis-table-paginator\">\n <mat-paginator [length]=\"dataSource?.totalDataLength?.value\" [pageSize]=\"pageSize\"\n [pageSizeOptions]=\"pageSizeOptions\" showFirstLastButtons></mat-paginator>\n </div>\n }\n </div>\n </div>\n } @else {\n\n @if(dataNotFoundConfig) {\n <div class=\"tis-data-not-found\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"130\" height=\"126.89\" viewBox=\"0 0 647.63626 632.17383\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" role=\"img\" artist=\"Katerina Limpitsouni\" source=\"https://undraw.co/\">\n <path d=\"M687.3279,276.08691H512.81813a15.01828,15.01828,0,0,0-15,15v387.85l-2,.61005-42.81006,13.11a8.00676,8.00676,0,0,1-9.98974-5.31L315.678,271.39691a8.00313,8.00313,0,0,1,5.31006-9.99l65.97022-20.2,191.25-58.54,65.96972-20.2a7.98927,7.98927,0,0,1,9.99024,5.3l32.5498,106.32Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"#f2f2f2\"/>\n <path d=\"M725.408,274.08691l-39.23-128.14a16.99368,16.99368,0,0,0-21.23-11.28l-92.75,28.39L380.95827,221.60693l-92.75,28.4a17.0152,17.0152,0,0,0-11.28028,21.23l134.08008,437.93a17.02661,17.02661,0,0,0,16.26026,12.03,16.78926,16.78926,0,0,0,4.96972-.75l63.58008-19.46,2-.62v-2.09l-2,.61-64.16992,19.65a15.01489,15.01489,0,0,1-18.73-9.95l-134.06983-437.94a14.97935,14.97935,0,0,1,9.94971-18.73l92.75-28.4,191.24024-58.54,92.75-28.4a15.15551,15.15551,0,0,1,4.40966-.66,15.01461,15.01461,0,0,1,14.32032,10.61l39.0498,127.56.62012,2h2.08008Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"#3f3d56\"/>\n <path d=\"M398.86279,261.73389a9.0157,9.0157,0,0,1-8.61133-6.3667l-12.88037-42.07178a8.99884,8.99884,0,0,1,5.9712-11.24023l175.939-53.86377a9.00867,9.00867,0,0,1,11.24072,5.9707l12.88037,42.07227a9.01029,9.01029,0,0,1-5.9707,11.24072L401.49219,261.33887A8.976,8.976,0,0,1,398.86279,261.73389Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"var(--tis-primary, var(--mat-sys-primary, #3838a2))\"/>\n <circle cx=\"190.15351\" cy=\"24.95465\" r=\"20\" fill=\"var(--tis-primary, var(--mat-sys-primary, #3838a2))\"/>\n <circle cx=\"190.15351\" cy=\"24.95465\" r=\"12.66462\" fill=\"#fff\"/>\n <path d=\"M878.81836,716.08691h-338a8.50981,8.50981,0,0,1-8.5-8.5v-405a8.50951,8.50951,0,0,1,8.5-8.5h338a8.50982,8.50982,0,0,1,8.5,8.5v405A8.51013,8.51013,0,0,1,878.81836,716.08691Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"#e6e6e6\"/>\n <path d=\"M723.31813,274.08691h-210.5a17.02411,17.02411,0,0,0-17,17v407.8l2-.61v-407.19a15.01828,15.01828,0,0,1,15-15H723.93825Zm183.5,0h-394a17.02411,17.02411,0,0,0-17,17v458a17.0241,17.0241,0,0,0,17,17h394a17.0241,17.0241,0,0,0,17-17v-458A17.02411,17.02411,0,0,0,906.81813,274.08691Zm15,475a15.01828,15.01828,0,0,1-15,15h-394a15.01828,15.01828,0,0,1-15-15v-458a15.01828,15.01828,0,0,1,15-15h394a15.01828,15.01828,0,0,1,15,15Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"#3f3d56\"/>\n <path d=\"M801.81836,318.08691h-184a9.01015,9.01015,0,0,1-9-9v-44a9.01016,9.01016,0,0,1,9-9h184a9.01016,9.01016,0,0,1,9,9v44A9.01015,9.01015,0,0,1,801.81836,318.08691Z\" transform=\"translate(-276.18187 -133.91309)\" fill=\"var(--tis-primary, var(--mat-sys-primary, #3838a2))\"/>\n <circle cx=\"433.63626\" cy=\"105.17383\" r=\"20\" fill=\"var(--tis-primary, var(--mat-sys-primary, #3838a2))\"/>\n <circle cx=\"433.63626\" cy=\"105.17383\" r=\"12.18187\" fill=\"#fff\"/>\n </svg>\n <h5 class=\"tis-h5\">{{dataNotFoundConfig.title}}</h5>\n <p class=\"tis-p\">{{dataNotFoundConfig.desc}}</p>\n @if((dataNotFoundConfig.btnUrl || dataNotFoundConfig?.btnClick) && dataNotFoundConfig.btnText) {\n <button mat-flat-button color=\"primary\" class=\"tis-text-upper\"\n (click)=\"handleButtonClick(dataNotFoundConfig)\">\n <mat-icon>add</mat-icon>\n {{dataNotFoundConfig.btnText}}\n </button>\n }\n @if((dataNotFoundConfig.secondBtnUrl || dataNotFoundConfig?.secondBtnClick) && dataNotFoundConfig.secondBtnText) {\n <button mat-stroked-button color=\"primary\" class=\"tis-text-upper\"\n (click)=\"handleSecondButtonClick(dataNotFoundConfig)\">\n <mat-icon>add</mat-icon>\n {{dataNotFoundConfig.secondBtnText}}\n </button>\n }\n </div>\n }\n\n }\n\n }\n\n </div>\n </div>\n</section>", styles: ["::ng-deep .sub-main-content{border:0px solid #f00;margin-top:56px;height:calc(100% - 56px);padding:15px;overflow:auto}.header-title{margin-top:8px;padding:7px 10px;color:#969a9c}.header-title h3{font-size:20px!important;font-weight:700}.header-menu{border:0px solid red;background:#fff;margin-top:1px;margin-bottom:0}.w-100{width:100%}.mat-mdc-table-sticky-border-elem-right{border-left:1px solid #e0e0e087}.mat-mdc-table-sticky-border-elem-left{border-right:1px solid #e0e0e087}.search-mat-form-field{width:100%}.filter-applied-section{overflow:auto}.tis-detail-row{height:0!important}.tis-element-detail-wrapper{overflow:hidden;max-height:0;transition:max-height 225ms ease}.tis-element-detail-wrapper-expanded{max-height:500px}.tis-table-bordered{border-collapse:collapse;width:100%}.tis-table-bordered th,.tis-table-bordered td{border-left:1px solid #e0e0e0}.tis-table-bordered th:first-child,.tis-table-bordered td:first-child{border-left:0px solid #e0e0e0}.tis-table-bordered .bg-unset{background-color:unset!important}@media (max-width: 575.98px){.search-mat-form-field{width:100%!important}}@media (min-width: 576px) and (max-width: 767.98px){.search-mat-form-field{width:100%!important}}\n"] }]
1580
2531
  }], ctorParameters: () => [{ type: i1$1.MatDialog }, { type: ApiService }, { type: i3$1.ActivatedRoute }, { type: i3$1.Router }, { type: i4.Location }, { type: i5.BreakpointObserver }], propDecorators: { columnCustomizationUrlConfig: [{
1581
2532
  type: Input,
1582
2533
  args: [{ required: true }]
@@ -1802,7 +2753,6 @@ class TisSmartTableViewerModule {
1802
2753
  Money, TisSmartTableViewerComponent,
1803
2754
  TisColumnsBtnComponent,
1804
2755
  CreateColumnsTemplateComponent,
1805
- TisSmartTableViewerComponent,
1806
2756
  TisSmartTableErrorDialogComponent,
1807
2757
  TisSmartTableConfirmationDialogComponent], imports: [CommonModule,
1808
2758
  FormsModule,
@@ -1837,7 +2787,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.7", ngImpor
1837
2787
  TisSmartTableViewerComponent,
1838
2788
  TisColumnsBtnComponent,
1839
2789
  CreateColumnsTemplateComponent,
1840
- TisSmartTableViewerComponent,
1841
2790
  TisSmartTableErrorDialogComponent,
1842
2791
  TisSmartTableConfirmationDialogComponent
1843
2792
  ],