@elite.framework/ng.ui.core 1.0.77 → 1.0.78

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.
@@ -313,7 +313,11 @@ class GenericReportComponent {
313
313
  .pipe(takeUntil(this.destroy$))
314
314
  .subscribe({
315
315
  next: (response) => {
316
- this.downloadFile(response, `${config.fileName}.${this.getFileExtension(config.exportType)}`);
316
+ this.loading = false;
317
+ if (config.exportType == ExportType.EXCEL) {
318
+ const blob = this.base64ToBlob(response, 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
319
+ this.downloadFile(blob, `${config.fileName}.${this.getFileExtension(config.exportType)}`);
320
+ }
317
321
  this.loading = false;
318
322
  },
319
323
  error: (error) => {
@@ -362,6 +366,11 @@ class GenericReportComponent {
362
366
  });
363
367
  return columns;
364
368
  }
369
+ base64ToBlob(base64, mime) {
370
+ const byteChars = atob(base64);
371
+ const byteNums = Array.from(byteChars, c => c.charCodeAt(0));
372
+ return new Blob([new Uint8Array(byteNums)], { type: mime });
373
+ }
365
374
  downloadFile(blob, fileName) {
366
375
  const url = window.URL.createObjectURL(blob);
367
376
  const link = document.createElement('a');
@@ -431,11 +440,11 @@ class GenericReportComponent {
431
440
  }
432
441
  }
433
442
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: GenericReportComponent, deps: [{ token: i1.DynamicDialogRef }, { token: i1.DynamicDialogConfig }], target: i0.ɵɵFactoryTarget.Component });
434
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.8", type: GenericReportComponent, isStandalone: true, selector: "app-report", inputs: { filterFields: "filterFields", enableQueryBuilder: "enableQueryBuilder", localExport: "localExport", queryString: "queryString", apiName: "apiName", model: "model" }, providers: [DialogService], viewQueries: [{ propertyName: "previewContainer", first: true, predicate: ["previewContainer"], descendants: true }], ngImport: i0, template: "\r\n <div class=\"flex flex-col h-full bg-white dark:bg-gray-900 rounded-lg max-w-6xl mx-auto\">\r\n <!-- Header -->\r\n <!-- <div class=\"flex items-center justify-between px-6 py-4 border-b border-gray-200 dark:border-gray-700\">\r\n <h2 class=\"text-lg font-semibold text-gray-900 dark:text-white\">\r\n {{ 'EXPORT_DATA' | translate }}\r\n </h2>\r\n <button\r\n (click)=\"ref?.close()\"\r\n class=\"p-1 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors\"\r\n aria-label=\"Close\">\r\n <i class=\"pi pi-times text-gray-500 dark:text-gray-400\"></i>\r\n </button>\r\n </div> -->\r\n\r\n <!-- Content -->\r\n <div class=\"flex-1 overflow-hidden\">\r\n <p-tabs [value]=\"activeTabIndex\">\r\n <!-- Configuration Tab -->\r\n <p-tablist>\r\n <p-tab value=\"0\">{{'CONFIGURATION' | translate}}</p-tab>\r\n <p-tab value=\"1\">{{'PREVIEW' | translate}}</p-tab>\r\n </p-tablist>\r\n <p-tabpanels>\r\n <p-tabpanel value=\"0\">\r\n <div class=\"grid grid-cols-1 lg:grid-cols-2 gap-6 p-4 max-h-[60vh] overflow-y-auto\">\r\n <!-- Left Column - Export Settings -->\r\n <div class=\"space-y-6\">\r\n <!-- File Name -->\r\n <div class=\"space-y-2\">\r\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300\">\r\n {{ 'FILE_NAME' | translate }}\r\n </label>\r\n <input\r\n type=\"text\"\r\n [(ngModel)]=\"fileName\"\r\n class=\"w-full p-3 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-500 focus:border-blue-500\"\r\n [placeholder]=\"'ENTER_FILE_NAME' | translate\">\r\n </div>\r\n\r\n <!-- Export Type -->\r\n <div class=\"space-y-3\">\r\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300\">\r\n {{ 'EXPORT_FORMAT' | translate }}\r\n </label>\r\n <div class=\"grid grid-cols-2 gap-3\">\r\n <div *ngFor=\"let type of exportTypes\" class=\"flex items-center\">\r\n <p-radioButton\r\n [name]=\"'exportType'\"\r\n [value]=\"type.value\"\r\n [(ngModel)]=\"exportType\"\r\n [inputId]=\"`${type.value}`\"\r\n (onClick)=\"onExportTypeChange(type.value)\"\r\n class=\"mr-3\">\r\n </p-radioButton>\r\n <label [for]=\"type.value\" class=\"flex items-center cursor-pointer text-sm text-gray-700 dark:text-gray-300\">\r\n <i [class]=\"type.icon + ' mr-2'\"></i>\r\n {{ type.label | translate }}\r\n </label>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Filters Section -->\r\n <div class=\"space-y-3\">\r\n <div class=\"flex items-center justify-between\">\r\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300\">\r\n {{ 'SEARCH_FILTERS' | translate }}\r\n </label>\r\n <button\r\n type=\"button\"\r\n (click)=\"showFilters = !showFilters\"\r\n class=\"text-sm text-blue-600 dark:text-blue-400 hover:underline\">\r\n {{ showFilters ? ('HIDE_FILTERS' | translate) : ('SHOW_FILTERS' | translate) }}\r\n </button>\r\n </div>\r\n\r\n <!-- <div *ngIf=\"showFilters\" class=\"space-y-4 p-4 border border-gray-200 dark:border-gray-700 rounded-lg bg-gray-50 dark:bg-gray-800\">\r\n <formly-form\r\n [form]=\"form\"\r\n [fields]=\"fields_\"\r\n [model]=\"model\">\r\n </formly-form>\r\n </div> -->\r\n </div>\r\n </div>\r\n\r\n <!-- Right Column - Column Selection -->\r\n <div class=\"space-y-4\">\r\n <div class=\"flex items-center justify-between\">\r\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300\">\r\n {{ 'SELECT_COLUMNS' | translate }}\r\n </label>\r\n <div class=\"flex gap-2\">\r\n <button\r\n type=\"button\"\r\n (click)=\"selectAllColumns()\"\r\n class=\"text-xs text-blue-600 dark:text-blue-400 hover:underline\">\r\n {{ 'SELECT_ALL' | translate }}\r\n </button>\r\n <button\r\n type=\"button\"\r\n (click)=\"deselectAllColumns()\"\r\n class=\"text-xs text-blue-600 dark:text-blue-400 hover:underline\">\r\n {{ 'DESELECT_ALL' | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"max-h-80 overflow-y-auto border border-gray-200 dark:border-gray-700 rounded-lg\">\r\n <div *ngFor=\"let column of availableColumns\" class=\"flex items-center p-3 border-b border-gray-100 dark:border-gray-600 last:border-b-0 hover:bg-gray-50 dark:hover:bg-gray-700\">\r\n <p-checkbox\r\n [binary]=\"true\"\r\n [(ngModel)]=\"column.selected\"\r\n [inputId]=\"column.key\"\r\n (onChange)=\"onColumnToggle(column)\"\r\n class=\"mr-3\">\r\n </p-checkbox>\r\n <label [for]=\"column.key\" class=\"flex-1 cursor-pointer text-sm text-gray-700 dark:text-gray-300\">\r\n {{ column.displayName }}\r\n </label>\r\n <div *ngIf=\"column.selected\" class=\"flex items-center gap-2\">\r\n <input\r\n type=\"text\"\r\n [(ngModel)]=\"column.customName\"\r\n (blur)=\"onCustomNameChange(column)\"\r\n [placeholder]=\"column.displayName\"\r\n class=\"text-xs p-1 border border-gray-300 dark:border-gray-600 rounded bg-white dark:bg-gray-800 text-gray-900 dark:text-white w-32\"\r\n [title]=\"'CUSTOM_COLUMN_NAME' | translate\">\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Selected Columns Summary -->\r\n <div *ngIf=\"selectedColumns.length > 0\" class=\"p-3 bg-blue-50 dark:bg-blue-900/20 rounded-lg\">\r\n <p class=\"text-sm text-blue-700 dark:text-blue-300\">\r\n {{ 'SELECTED_COLUMNS_COUNT' | translate: { count: selectedColumns.length } }}\r\n </p>\r\n </div>\r\n </div>\r\n </div>\r\n </p-tabpanel>\r\n\r\n <!-- Preview Tab -->\r\n <!-- [disabled]=\"selectedColumns.length === 0\" -->\r\n <p-tabpanel value=\"1\" >\r\n <div class=\"p-4 max-h-[60vh] overflow-y-auto\">\r\n <!-- Preview Actions -->\r\n <div class=\"flex justify-between items-center mb-4\">\r\n <h3 class=\"text-lg font-semibold text-gray-900 dark:text-white\">\r\n {{ 'REPORT_PREVIEW' | translate }}\r\n </h3>\r\n <div class=\"flex gap-2\">\r\n <button\r\n *ngIf=\"exportType === 1 || exportType === 4\"\r\n (click)=\"printPreview()\"\r\n class=\"flex items-center px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors\">\r\n <i class=\"pi pi-print mr-2\"></i>\r\n {{ 'PRINT' | translate }}\r\n </button>\r\n <button\r\n (click)=\"generatePreview()\"\r\n class=\"flex items-center px-4 py-2 text-sm font-medium text-white bg-blue-600 rounded-lg hover:bg-blue-700 transition-colors\">\r\n <i class=\"pi pi-refresh mr-2\"></i>\r\n {{ 'REFRESH_PREVIEW' | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- Preview Content -->\r\n <div #previewContainer class=\"bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg p-6\">\r\n <!-- Report Header -->\r\n <div class=\"text-center mb-6 border-b border-gray-200 dark:border-gray-700 pb-4\">\r\n <h1 class=\"text-2xl font-bold text-gray-900 dark:text-white\">{{ fileName }}</h1>\r\n <p class=\"text-gray-600 dark:text-gray-400 mt-2\">\r\n {{ 'GENERATED_ON' | translate }}: {{ currentDate | date:'medium' }}\r\n </p>\r\n </div>\r\n\r\n <!-- Report Table -->\r\n <div class=\"overflow-x-auto\">\r\n <table class=\"min-w-full divide-y divide-gray-200 dark:divide-gray-700\">\r\n <thead class=\"bg-gray-50 dark:bg-gray-700\">\r\n <tr>\r\n <th\r\n *ngFor=\"let column of selectedColumns\"\r\n class=\"px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider border border-gray-200 dark:border-gray-600\">\r\n {{ column.customName || column.displayName }}\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody class=\"bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700\">\r\n <tr *ngFor=\"let row of previewData; let i = index\"\r\n [class.bg-gray-50]=\"i % 2 === 0\"\r\n [class.dark:bg-gray-900]=\"i % 2 === 0\">\r\n <td\r\n *ngFor=\"let column of selectedColumns\"\r\n class=\"px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-white border border-gray-200 dark:border-gray-600\">\r\n {{ getPreviewValue(row, column.key) }}\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n\r\n <!-- Empty State -->\r\n <div *ngIf=\"previewData.length === 0\" class=\"text-center py-8\">\r\n <i class=\"pi pi-inbox text-4xl text-gray-400 dark:text-gray-500 mb-4\"></i>\r\n <p class=\"text-gray-500 dark:text-gray-400\">{{ 'NO_PREVIEW_DATA' | translate }}</p>\r\n <button\r\n (click)=\"generatePreview()\"\r\n class=\"mt-4 px-4 py-2 text-sm font-medium text-blue-600 dark:text-blue-400 hover:underline\">\r\n {{ 'GENERATE_PREVIEW' | translate }}\r\n </button>\r\n </div>\r\n\r\n <!-- Report Footer -->\r\n <div class=\"text-center mt-6 border-t border-gray-200 dark:border-gray-700 pt-4\">\r\n <p class=\"text-sm text-gray-500 dark:text-gray-400\">\r\n {{ 'PAGE' | translate }} 1 of 1\r\n </p>\r\n </div>\r\n </div>\r\n\r\n <!-- Preview Info -->\r\n <div class=\"mt-4 p-3 bg-green-50 dark:bg-green-900/20 rounded-lg\">\r\n <p class=\"text-sm text-green-700 dark:text-green-300\">\r\n <i class=\"pi pi-info-circle mr-2\"></i>\r\n {{ 'PREVIEW_INFO' | translate }}\r\n </p>\r\n </div>\r\n </div>\r\n </p-tabpanel>\r\n\r\n </p-tabpanels>\r\n </p-tabs>\r\n </div>\r\n\r\n <!-- Footer -->\r\n <div class=\"border-t border-gray-200 dark:border-gray-700 px-6 py-4 bg-gray-50 dark:bg-gray-800\">\r\n <div class=\"flex justify-between items-center\">\r\n <button\r\n type=\"button\"\r\n (click)=\"onReset()\"\r\n class=\"flex items-center px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg transition-colors\"\r\n [disabled]=\"loading\">\r\n <i class=\"pi pi-refresh ml-2\"></i>\r\n {{ 'RESET' | translate }}\r\n </button>\r\n\r\n <div class=\"flex gap-2\">\r\n <button\r\n type=\"button\"\r\n (click)=\"ref?.close()\"\r\n class=\"px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors\"\r\n [disabled]=\"loading\">\r\n {{ 'CANCEL' | translate }}\r\n </button>\r\n\r\n <button\r\n type=\"button\"\r\n (click)=\"onExport()\"\r\n [disabled]=\"loading || selectedColumns.length === 0\"\r\n class=\"flex items-center px-4 py-2 text-sm font-medium text-white bg-blue-600 rounded-lg hover:bg-blue-700 disabled:bg-gray-300 disabled:cursor-not-allowed transition-colors\">\r\n <i class=\"pi pi-download ml-2\" [class.animate-spin]=\"loading\"></i>\r\n {{ getExportButtonText() }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n @if(showFilters){\r\n<p-drawer\r\n [(visible)]=\"showFilters\"\r\n position=\"right\"\r\n [styleClass]=\"'!w-full md:!w-80 lg:!w-[40rem] !h-full' \"\r\n [modal]=\"true\"\r\n [dismissible]=\"true\"\r\n styleClass=\"p-4 w-full max-w-md max-h-[90vh] flex flex-col\"\r\n>\r\n <!-- Entire form wrapper -->\r\n <form [formGroup]=\"form\" (ngSubmit)=\"onSubmit(); showFilters=false\" class=\"flex flex-col flex-1\">\r\n <!-- Scrollable Form -->\r\n <div class=\"flex-1 overflow-auto\">\r\n <formly-form\r\n [form]=\"form\"\r\n [fields]=\"fields_\"\r\n [model]=\"model\"\r\n [options]=\"options\"\r\n >\r\n </formly-form>\r\n </div>\r\n\r\n </form>\r\n <!-- Action Buttons -->\r\n <ng-template pTemplate=\"footer\">\r\n <div class=\"flex justify-end mt-2 space-x-2 flex-none\">\r\n <button\r\n type=\"submit\"\r\n pButton size=\"small\"\r\n (click)=\" onSubmit(); showFilters=false\"\r\n label=\"{{ 'SEARCH' | translate }}\">\r\n </button>\r\n <button\r\n type=\"button\"\r\n pButton\r\n size=\"small\"\r\n class=\"p-button-text\"\r\n (click)=\"onReset(); showFilters=false\"\r\n >\r\n {{ 'CLEAR' | translate }}\r\n </button>\r\n </div>\r\n </ng-template>\r\n</p-drawer>\r\n\r\n }\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i3.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: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i4.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "loading", "severity", "raised", "rounded", "text", "outlined", "size", "plain", "fluid", "label", "icon", "buttonProps"] }, { kind: "directive", type: i5.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: DialogModule }, { kind: "ngmodule", type: SelectModule }, { kind: "ngmodule", type: MultiSelectModule }, { kind: "ngmodule", type: InputTextModule }, { kind: "ngmodule", type: RadioButtonModule }, { kind: "component", type: i6.RadioButton, selector: "p-radioButton, p-radiobutton, p-radio-button", inputs: ["value", "tabindex", "inputId", "ariaLabelledBy", "ariaLabel", "styleClass", "autofocus", "binary", "variant", "size"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: CheckboxModule }, { kind: "component", type: i7.Checkbox, selector: "p-checkbox, p-checkBox, p-check-box", inputs: ["value", "binary", "ariaLabelledBy", "ariaLabel", "tabindex", "inputId", "inputStyle", "styleClass", "inputClass", "indeterminate", "formControl", "checkboxIcon", "readonly", "autofocus", "trueValue", "falseValue", "variant", "size"], outputs: ["onChange", "onFocus", "onBlur"] }, { kind: "ngmodule", type: CardModule }, { kind: "ngmodule", type: DividerModule }, { kind: "ngmodule", type: TabsModule }, { kind: "component", type: i8.Tabs, selector: "p-tabs", inputs: ["value", "scrollable", "lazy", "selectOnFocus", "showNavigators", "tabindex"], outputs: ["valueChange"] }, { kind: "component", type: i8.TabPanels, selector: "p-tabpanels" }, { kind: "component", type: i8.TabPanel, selector: "p-tabpanel", inputs: ["value"], outputs: ["valueChange"] }, { kind: "component", type: i8.TabList, selector: "p-tablist" }, { kind: "component", type: i8.Tab, selector: "p-tab", inputs: ["value", "disabled"], outputs: ["valueChange"] }, { kind: "ngmodule", type: FormlyModule }, { kind: "component", type: i9.LegacyFormlyForm, selector: "formly-form" }, { kind: "ngmodule", type: DynamicDialogModule }, { kind: "ngmodule", type: DrawerModule }, { kind: "component", type: i10.Drawer, selector: "p-drawer", inputs: ["appendTo", "blockScroll", "style", "styleClass", "ariaCloseLabel", "autoZIndex", "baseZIndex", "modal", "closeButtonProps", "dismissible", "showCloseIcon", "closeOnEscape", "transitionOptions", "visible", "position", "fullScreen", "header", "maskStyle", "closable"], outputs: ["onShow", "onHide", "visibleChange"] }, { kind: "pipe", type: i2.DatePipe, name: "date" }, { kind: "pipe", type: i11.TranslatePipe, name: "translate" }] });
443
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.8", type: GenericReportComponent, isStandalone: true, selector: "app-generic-report", inputs: { filterFields: "filterFields", enableQueryBuilder: "enableQueryBuilder", localExport: "localExport", queryString: "queryString", apiName: "apiName", model: "model" }, providers: [DialogService], viewQueries: [{ propertyName: "previewContainer", first: true, predicate: ["previewContainer"], descendants: true }], ngImport: i0, template: "\r\n <div class=\"flex flex-col h-full bg-white dark:bg-gray-900 rounded-lg max-w-6xl mx-auto\">\r\n <!-- Header -->\r\n <!-- <div class=\"flex items-center justify-between px-6 py-4 border-b border-gray-200 dark:border-gray-700\">\r\n <h2 class=\"text-lg font-semibold text-gray-900 dark:text-white\">\r\n {{ 'EXPORT_DATA' | translate }}\r\n </h2>\r\n <button\r\n (click)=\"ref?.close()\"\r\n class=\"p-1 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors\"\r\n aria-label=\"Close\">\r\n <i class=\"pi pi-times text-gray-500 dark:text-gray-400\"></i>\r\n </button>\r\n </div> -->\r\n\r\n <!-- Content -->\r\n <div class=\"flex-1 overflow-hidden\">\r\n <p-tabs [value]=\"activeTabIndex\">\r\n <!-- Configuration Tab -->\r\n <p-tablist>\r\n <p-tab value=\"0\">{{'CONFIGURATION' | translate}}</p-tab>\r\n <p-tab value=\"1\">{{'PREVIEW' | translate}}</p-tab>\r\n </p-tablist>\r\n <p-tabpanels>\r\n <p-tabpanel value=\"0\">\r\n <div class=\"grid grid-cols-1 lg:grid-cols-2 gap-6 p-4 max-h-[60vh] overflow-y-auto\">\r\n <!-- Left Column - Export Settings -->\r\n <div class=\"space-y-6\">\r\n <!-- File Name -->\r\n <div class=\"space-y-2\">\r\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300\">\r\n {{ 'FILE_NAME' | translate }}\r\n </label>\r\n <input\r\n type=\"text\"\r\n [(ngModel)]=\"fileName\"\r\n class=\"w-full p-3 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-500 focus:border-blue-500\"\r\n [placeholder]=\"'ENTER_FILE_NAME' | translate\">\r\n </div>\r\n\r\n <!-- Export Type -->\r\n <div class=\"space-y-3\">\r\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300\">\r\n {{ 'EXPORT_FORMAT' | translate }}\r\n </label>\r\n <div class=\"grid grid-cols-2 gap-3\">\r\n <div *ngFor=\"let type of exportTypes\" class=\"flex items-center\">\r\n <p-radioButton\r\n [name]=\"'exportType'\"\r\n [value]=\"type.value\"\r\n [(ngModel)]=\"exportType\"\r\n [inputId]=\"`${type.value}`\"\r\n (onClick)=\"onExportTypeChange(type.value)\"\r\n class=\"mr-3\">\r\n </p-radioButton>\r\n <label [for]=\"type.value\" class=\"flex items-center cursor-pointer text-sm text-gray-700 dark:text-gray-300\">\r\n <i [class]=\"type.icon + ' mr-2'\"></i>\r\n {{ type.label | translate }}\r\n </label>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Filters Section -->\r\n <div class=\"space-y-3\">\r\n <div class=\"flex items-center justify-between\">\r\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300\">\r\n {{ 'SEARCH_FILTERS' | translate }}\r\n </label>\r\n <button\r\n type=\"button\"\r\n (click)=\"showFilters = !showFilters\"\r\n class=\"text-sm text-blue-600 dark:text-blue-400 hover:underline\">\r\n {{ showFilters ? ('HIDE_FILTERS' | translate) : ('SHOW_FILTERS' | translate) }}\r\n </button>\r\n </div>\r\n\r\n <!-- <div *ngIf=\"showFilters\" class=\"space-y-4 p-4 border border-gray-200 dark:border-gray-700 rounded-lg bg-gray-50 dark:bg-gray-800\">\r\n <formly-form\r\n [form]=\"form\"\r\n [fields]=\"fields_\"\r\n [model]=\"model\">\r\n </formly-form>\r\n </div> -->\r\n </div>\r\n </div>\r\n\r\n <!-- Right Column - Column Selection -->\r\n <div class=\"space-y-4\">\r\n <div class=\"flex items-center justify-between\">\r\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300\">\r\n {{ 'SELECT_COLUMNS' | translate }}\r\n </label>\r\n <div class=\"flex gap-2\">\r\n <button\r\n type=\"button\"\r\n (click)=\"selectAllColumns()\"\r\n class=\"text-xs text-blue-600 dark:text-blue-400 hover:underline\">\r\n {{ 'SELECT_ALL' | translate }}\r\n </button>\r\n <button\r\n type=\"button\"\r\n (click)=\"deselectAllColumns()\"\r\n class=\"text-xs text-blue-600 dark:text-blue-400 hover:underline\">\r\n {{ 'DESELECT_ALL' | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"max-h-80 overflow-y-auto border border-gray-200 dark:border-gray-700 rounded-lg\">\r\n <div *ngFor=\"let column of availableColumns\" class=\"flex items-center p-3 border-b border-gray-100 dark:border-gray-600 last:border-b-0 hover:bg-gray-50 dark:hover:bg-gray-700\">\r\n <p-checkbox\r\n [binary]=\"true\"\r\n [(ngModel)]=\"column.selected\"\r\n [inputId]=\"column.key\"\r\n (onChange)=\"onColumnToggle(column)\"\r\n class=\"mr-3\">\r\n </p-checkbox>\r\n <label [for]=\"column.key\" class=\"flex-1 cursor-pointer text-sm text-gray-700 dark:text-gray-300\">\r\n {{ column.displayName }}\r\n </label>\r\n <div *ngIf=\"column.selected\" class=\"flex items-center gap-2\">\r\n <input\r\n type=\"text\"\r\n [(ngModel)]=\"column.customName\"\r\n (blur)=\"onCustomNameChange(column)\"\r\n [placeholder]=\"column.displayName\"\r\n class=\"text-xs p-1 border border-gray-300 dark:border-gray-600 rounded bg-white dark:bg-gray-800 text-gray-900 dark:text-white w-32\"\r\n [title]=\"'CUSTOM_COLUMN_NAME' | translate\">\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Selected Columns Summary -->\r\n <div *ngIf=\"selectedColumns.length > 0\" class=\"p-3 bg-blue-50 dark:bg-blue-900/20 rounded-lg\">\r\n <p class=\"text-sm text-blue-700 dark:text-blue-300\">\r\n {{ 'SELECTED_COLUMNS_COUNT' | translate: { count: selectedColumns.length } }}\r\n </p>\r\n </div>\r\n </div>\r\n </div>\r\n </p-tabpanel>\r\n\r\n <!-- Preview Tab -->\r\n <!-- [disabled]=\"selectedColumns.length === 0\" -->\r\n <p-tabpanel value=\"1\" >\r\n <div class=\"p-4 max-h-[60vh] overflow-y-auto\">\r\n <!-- Preview Actions -->\r\n <div class=\"flex justify-between items-center mb-4\">\r\n <h3 class=\"text-lg font-semibold text-gray-900 dark:text-white\">\r\n {{ 'REPORT_PREVIEW' | translate }}\r\n </h3>\r\n <div class=\"flex gap-2\">\r\n <button\r\n *ngIf=\"exportType === 1 || exportType === 4\"\r\n (click)=\"printPreview()\"\r\n class=\"flex items-center px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors\">\r\n <i class=\"pi pi-print mr-2\"></i>\r\n {{ 'PRINT' | translate }}\r\n </button>\r\n <button\r\n (click)=\"generatePreview()\"\r\n class=\"flex items-center px-4 py-2 text-sm font-medium text-white bg-blue-600 rounded-lg hover:bg-blue-700 transition-colors\">\r\n <i class=\"pi pi-refresh mr-2\"></i>\r\n {{ 'REFRESH_PREVIEW' | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- Preview Content -->\r\n <div #previewContainer class=\"bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg p-6\">\r\n <!-- Report Header -->\r\n <div class=\"text-center mb-6 border-b border-gray-200 dark:border-gray-700 pb-4\">\r\n <h1 class=\"text-2xl font-bold text-gray-900 dark:text-white\">{{ fileName }}</h1>\r\n <p class=\"text-gray-600 dark:text-gray-400 mt-2\">\r\n {{ 'GENERATED_ON' | translate }}: {{ currentDate | date:'medium' }}\r\n </p>\r\n </div>\r\n\r\n <!-- Report Table -->\r\n <div class=\"overflow-x-auto\">\r\n <table class=\"min-w-full divide-y divide-gray-200 dark:divide-gray-700\">\r\n <thead class=\"bg-gray-50 dark:bg-gray-700\">\r\n <tr>\r\n <th\r\n *ngFor=\"let column of selectedColumns\"\r\n class=\"px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider border border-gray-200 dark:border-gray-600\">\r\n {{ column.customName || column.displayName }}\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody class=\"bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700\">\r\n <tr *ngFor=\"let row of previewData; let i = index\"\r\n [class.bg-gray-50]=\"i % 2 === 0\"\r\n [class.dark:bg-gray-900]=\"i % 2 === 0\">\r\n <td\r\n *ngFor=\"let column of selectedColumns\"\r\n class=\"px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-white border border-gray-200 dark:border-gray-600\">\r\n {{ getPreviewValue(row, column.key) }}\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n\r\n <!-- Empty State -->\r\n <div *ngIf=\"previewData.length === 0\" class=\"text-center py-8\">\r\n <i class=\"pi pi-inbox text-4xl text-gray-400 dark:text-gray-500 mb-4\"></i>\r\n <p class=\"text-gray-500 dark:text-gray-400\">{{ 'NO_PREVIEW_DATA' | translate }}</p>\r\n <button\r\n (click)=\"generatePreview()\"\r\n class=\"mt-4 px-4 py-2 text-sm font-medium text-blue-600 dark:text-blue-400 hover:underline\">\r\n {{ 'GENERATE_PREVIEW' | translate }}\r\n </button>\r\n </div>\r\n\r\n <!-- Report Footer -->\r\n <div class=\"text-center mt-6 border-t border-gray-200 dark:border-gray-700 pt-4\">\r\n <p class=\"text-sm text-gray-500 dark:text-gray-400\">\r\n {{ 'PAGE' | translate }} 1 of 1\r\n </p>\r\n </div>\r\n </div>\r\n\r\n <!-- Preview Info -->\r\n <div class=\"mt-4 p-3 bg-green-50 dark:bg-green-900/20 rounded-lg\">\r\n <p class=\"text-sm text-green-700 dark:text-green-300\">\r\n <i class=\"pi pi-info-circle mr-2\"></i>\r\n {{ 'PREVIEW_INFO' | translate }}\r\n </p>\r\n </div>\r\n </div>\r\n </p-tabpanel>\r\n\r\n </p-tabpanels>\r\n </p-tabs>\r\n </div>\r\n\r\n <!-- Footer -->\r\n <div class=\"border-t border-gray-200 dark:border-gray-700 px-6 py-4 bg-gray-50 dark:bg-gray-800\">\r\n <div class=\"flex justify-between items-center\">\r\n <button\r\n type=\"button\"\r\n (click)=\"onReset()\"\r\n class=\"flex items-center px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg transition-colors\"\r\n [disabled]=\"loading\">\r\n <i class=\"pi pi-refresh ml-2\"></i>\r\n {{ 'RESET' | translate }}\r\n </button>\r\n\r\n <div class=\"flex gap-2\">\r\n <button\r\n type=\"button\"\r\n (click)=\"ref?.close()\"\r\n class=\"px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors\"\r\n [disabled]=\"loading\">\r\n {{ 'CANCEL' | translate }}\r\n </button>\r\n\r\n <button\r\n type=\"button\"\r\n (click)=\"onExport()\"\r\n [disabled]=\"loading || selectedColumns.length === 0\"\r\n class=\"flex items-center px-4 py-2 text-sm font-medium text-white bg-blue-600 rounded-lg hover:bg-blue-700 disabled:bg-gray-300 disabled:cursor-not-allowed transition-colors\">\r\n <i class=\"pi pi-download ml-2\" [class.animate-spin]=\"loading\"></i>\r\n {{ getExportButtonText() }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n @if(showFilters){\r\n<p-drawer\r\n [(visible)]=\"showFilters\"\r\n position=\"right\"\r\n [styleClass]=\"'!w-full md:!w-80 lg:!w-[40rem] !h-full' \"\r\n [modal]=\"true\"\r\n [dismissible]=\"true\"\r\n styleClass=\"p-4 w-full max-w-md max-h-[90vh] flex flex-col\"\r\n>\r\n <!-- Entire form wrapper -->\r\n <form [formGroup]=\"form\" (ngSubmit)=\"onSubmit(); showFilters=false\" class=\"flex flex-col flex-1\">\r\n <!-- Scrollable Form -->\r\n <div class=\"flex-1 overflow-auto\">\r\n <formly-form\r\n [form]=\"form\"\r\n [fields]=\"fields_\"\r\n [model]=\"model\"\r\n [options]=\"options\"\r\n >\r\n </formly-form>\r\n </div>\r\n\r\n </form>\r\n <!-- Action Buttons -->\r\n <ng-template pTemplate=\"footer\">\r\n <div class=\"flex justify-end mt-2 space-x-2 flex-none\">\r\n <button\r\n type=\"submit\"\r\n pButton size=\"small\"\r\n (click)=\" onSubmit(); showFilters=false\"\r\n label=\"{{ 'SEARCH' | translate }}\">\r\n </button>\r\n <button\r\n type=\"button\"\r\n pButton\r\n size=\"small\"\r\n class=\"p-button-text\"\r\n (click)=\"onReset(); showFilters=false\"\r\n >\r\n {{ 'CLEAR' | translate }}\r\n </button>\r\n </div>\r\n </ng-template>\r\n</p-drawer>\r\n\r\n }\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i3.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: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i4.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "loading", "severity", "raised", "rounded", "text", "outlined", "size", "plain", "fluid", "label", "icon", "buttonProps"] }, { kind: "directive", type: i5.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: DialogModule }, { kind: "ngmodule", type: SelectModule }, { kind: "ngmodule", type: MultiSelectModule }, { kind: "ngmodule", type: InputTextModule }, { kind: "ngmodule", type: RadioButtonModule }, { kind: "component", type: i6.RadioButton, selector: "p-radioButton, p-radiobutton, p-radio-button", inputs: ["value", "tabindex", "inputId", "ariaLabelledBy", "ariaLabel", "styleClass", "autofocus", "binary", "variant", "size"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: CheckboxModule }, { kind: "component", type: i7.Checkbox, selector: "p-checkbox, p-checkBox, p-check-box", inputs: ["value", "binary", "ariaLabelledBy", "ariaLabel", "tabindex", "inputId", "inputStyle", "styleClass", "inputClass", "indeterminate", "formControl", "checkboxIcon", "readonly", "autofocus", "trueValue", "falseValue", "variant", "size"], outputs: ["onChange", "onFocus", "onBlur"] }, { kind: "ngmodule", type: CardModule }, { kind: "ngmodule", type: DividerModule }, { kind: "ngmodule", type: TabsModule }, { kind: "component", type: i8.Tabs, selector: "p-tabs", inputs: ["value", "scrollable", "lazy", "selectOnFocus", "showNavigators", "tabindex"], outputs: ["valueChange"] }, { kind: "component", type: i8.TabPanels, selector: "p-tabpanels" }, { kind: "component", type: i8.TabPanel, selector: "p-tabpanel", inputs: ["value"], outputs: ["valueChange"] }, { kind: "component", type: i8.TabList, selector: "p-tablist" }, { kind: "component", type: i8.Tab, selector: "p-tab", inputs: ["value", "disabled"], outputs: ["valueChange"] }, { kind: "ngmodule", type: FormlyModule }, { kind: "component", type: i9.LegacyFormlyForm, selector: "formly-form" }, { kind: "ngmodule", type: DynamicDialogModule }, { kind: "ngmodule", type: DrawerModule }, { kind: "component", type: i10.Drawer, selector: "p-drawer", inputs: ["appendTo", "blockScroll", "style", "styleClass", "ariaCloseLabel", "autoZIndex", "baseZIndex", "modal", "closeButtonProps", "dismissible", "showCloseIcon", "closeOnEscape", "transitionOptions", "visible", "position", "fullScreen", "header", "maskStyle", "closable"], outputs: ["onShow", "onHide", "visibleChange"] }, { kind: "pipe", type: i2.DatePipe, name: "date" }, { kind: "pipe", type: i11.TranslatePipe, name: "translate" }] });
435
444
  }
436
445
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: GenericReportComponent, decorators: [{
437
446
  type: Component,
438
- args: [{ selector: 'app-report', providers: [DialogService], imports: [
447
+ args: [{ selector: 'app-generic-report', providers: [DialogService], imports: [
439
448
  CommonModule,
440
449
  ReactiveFormsModule,
441
450
  FormsModule,