lib-portal-angular 0.0.87 → 0.0.89
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2022/lib/components/components.module.mjs +65 -40
- package/esm2022/lib/components/csv-importer/csv-importer.component.mjs +92 -0
- package/esm2022/lib/components/data-excel-exporter/IExcelExportConfig.mjs +2 -0
- package/esm2022/lib/components/data-excel-exporter/data-excel-exporter.component.mjs +126 -0
- package/esm2022/lib/components/data-excel-import/data-excel-importer.component.mjs +198 -0
- package/esm2022/lib/components/multi-select/multi-select.component.mjs +165 -115
- package/esm2022/lib/components/pdf-data-handler/argenta-pdf-data-handler.component.mjs +147 -0
- package/esm2022/lib/components/pdf-data-handler/function/formatToBrazilianNumber.mjs +7 -0
- package/esm2022/lib/components/pdf-data-handler/function/parseBrazilianNumber.mjs +9 -0
- package/esm2022/lib/components/pdf-data-handler/interface/DataRow.mjs +2 -0
- package/esm2022/lib/components/pdf-data-handler/interface/PdfExportConfig.mjs +2 -0
- package/esm2022/lib/components/pdf-data-handler/interface/PdfTableStyles.mjs +2 -0
- package/esm2022/lib/components/pdf-data-handler/interface/RowCalculation.mjs +2 -0
- package/esm2022/lib/components/pdf-data-handler/interface/TotalizerConfig.mjs +2 -0
- package/esm2022/lib/components/pdf-download/argenta-pdf-download.component.mjs +51 -0
- package/esm2022/public-api.mjs +36 -5
- package/fesm2022/lib-portal-angular.mjs +1095 -422
- package/fesm2022/lib-portal-angular.mjs.map +1 -1
- package/lib/components/components.module.d.ts +10 -5
- package/lib/components/csv-importer/csv-importer.component.d.ts +19 -0
- package/lib/components/data-excel-exporter/IExcelExportConfig.d.ts +21 -0
- package/lib/components/data-excel-exporter/data-excel-exporter.component.d.ts +9 -0
- package/lib/components/data-excel-import/data-excel-importer.component.d.ts +44 -0
- package/lib/components/multi-select/multi-select.component.d.ts +20 -9
- package/lib/components/pdf-data-handler/argenta-pdf-data-handler.component.d.ts +15 -0
- package/lib/components/pdf-data-handler/function/formatToBrazilianNumber.d.ts +1 -0
- package/lib/components/pdf-data-handler/function/parseBrazilianNumber.d.ts +1 -0
- package/lib/components/pdf-data-handler/interface/DataRow.d.ts +3 -0
- package/lib/components/pdf-data-handler/interface/PdfExportConfig.d.ts +12 -0
- package/lib/components/pdf-data-handler/interface/PdfTableStyles.d.ts +28 -0
- package/lib/components/pdf-data-handler/interface/RowCalculation.d.ts +4 -0
- package/lib/components/pdf-data-handler/interface/TotalizerConfig.d.ts +8 -0
- package/lib/components/pdf-download/argenta-pdf-download.component.d.ts +13 -0
- package/package.json +1 -1
- package/public-api.d.ts +34 -3
@@ -1,18 +1,20 @@
|
|
1
1
|
import * as i0 from '@angular/core';
|
2
|
-
import { Injectable, EventEmitter, Component, Input, Output, ChangeDetectionStrategy, HostListener, ViewChild, forwardRef, Directive, ViewContainerRef, NgModule, createComponent } from '@angular/core';
|
2
|
+
import { Injectable, EventEmitter, Component, Input, Output, ChangeDetectionStrategy, HostListener, ViewChild, forwardRef, Directive, ViewEncapsulation, ViewContainerRef, NgModule, createComponent } from '@angular/core';
|
3
3
|
import * as i1 from '@angular/common';
|
4
4
|
import { CommonModule } from '@angular/common';
|
5
5
|
import * as i2 from '@angular/forms';
|
6
6
|
import { NG_VALUE_ACCESSOR, FormsModule, ReactiveFormsModule } from '@angular/forms';
|
7
|
-
import * as
|
7
|
+
import * as i4 from 'lucide-angular';
|
8
8
|
import { LucideAngularModule, icons } from 'lucide-angular';
|
9
9
|
import hljs from 'highlight.js';
|
10
10
|
import * as i1$1 from '@ng-bootstrap/ng-bootstrap';
|
11
11
|
import { Subject, of, Subscription, Observable } from 'rxjs';
|
12
|
-
import { debounceTime,
|
13
|
-
import * as
|
12
|
+
import { debounceTime, distinctUntilChanged, switchMap, tap, map, catchError, takeUntil } from 'rxjs/operators';
|
13
|
+
import * as i1$2 from '@angular/common/http';
|
14
14
|
import { HttpParams } from '@angular/common/http';
|
15
|
-
import
|
15
|
+
import jsPDF from 'jspdf';
|
16
|
+
import 'jspdf-autotable';
|
17
|
+
import * as XLSX from 'xlsx';
|
16
18
|
import { NgSelectModule } from '@ng-select/ng-select';
|
17
19
|
import * as CryptoJS from 'crypto-js';
|
18
20
|
|
@@ -1151,7 +1153,7 @@ class CalendarArgentaComponent {
|
|
1151
1153
|
return this.locales[this.locale]?.daysOfWeek || this.locales['en'].daysOfWeek;
|
1152
1154
|
}
|
1153
1155
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CalendarArgentaComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
1154
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: CalendarArgentaComponent, selector: "argenta-calendar", inputs: { id: "id", placeholder: "placeholder", label: "label", minDate: "minDate", maxDate: "maxDate", locale: "locale", useTime: "useTime", initialDate: "initialDate", rangeMode: "rangeMode", startDate: "startDate", endDate: "endDate", closeButtonLabel: "closeButtonLabel" }, outputs: { rangeChange: "rangeChange" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"form-group\">\n <label [for]=\"id\" [ngClass]=\"'label-styles'\">{{ label }}</label>\n <div class=\"input-wrapper\">\n <input\n id=\"{{ id }}\"\n type=\"text\"\n class=\"custom-input\"\n [attr.placeholder]=\"rangeMode && useTime ? 'dd/MM/yyyy HH:mm - dd/MM/yyyy HH:mm' : \n rangeMode && !useTime ? 'dd/MM/yyyy - dd/MM/yyyy' :(!rangeMode && useTime ? 'dd/MM/yyyy HH:mm' : 'dd/MM/yyyy')\"\n [value]=\"inputDate\"\n (input)=\"onInputChange($event)\"\n (keypress)=\"handleKeyPress($event)\"\n (click)=\"toggleCalendar()\"\n />\n <lucide-icon name=\"calendar\" class=\"calendar-icon\"></lucide-icon>\n </div>\n\n <div *ngIf=\"invalidDate\" class=\"error-message\">\n {{ locales[locale].invalidDateMessage }}\n <span *ngIf=\"useTime\"> HH:mm.</span>\n </div>\n\n <div class=\"calendar-wrapper\">\n <div class=\"calendar-container\" [ngClass]=\"{ open: isCalendarVisible }\">\n <div class=\"calendar\">\n <div class=\"calendar-header\">\n <button (click)=\"prevMonth()\">‹</button>\n <span>{{ months[currentMonth] }} {{ currentYear }}</span>\n <button (click)=\"nextMonth()\">›</button>\n </div>\n\n <div class=\"calendar-body\">\n <div class=\"calendar-day-names\">\n <span *ngFor=\"let day of daysOfWeek\">{{ day }}</span>\n </div>\n\n <div class=\"calendar-days\">\n <span\n *ngFor=\"let day of daysInMonth; let i = index\"\n [class.today]=\"isToday(day)\"\n [class.selected]=\"isSelected(day)\"\n [class.in-range]=\"isInRange(day)\"\n [class.disabled]=\"isDateDisabled(day)\"\n (click)=\"day ? selectDate(day) : null\"\n >\n {{ day ? day : \"\" }}\n </span>\n </div>\n </div>\n\n <!-- Inputs para inser\u00E7\u00E3o das horas -->\n <div *ngIf=\"useTime\" class=\"time-inputs\">\n <!-- Campo de hora de in\u00EDcio -->\n <div *ngIf=\"rangeMode\" class=\"time-input\">\n <label>{{ locales[locale]?.startTimeLabel || 'Hora de In\u00EDcio' }}</label> <!-- Usando tradu\u00E7\u00E3o -->\n <input type=\"time\" [(ngModel)]=\"startTime\" (change)=\"onTimeChange('start')\" />\n </div>\n\n <!-- Campo de hora de fim -->\n <div *ngIf=\"rangeMode\" class=\"time-input\">\n <label>{{ locales[locale]?.endTimeLabel || 'Hora de Fim' }}</label> <!-- Usando tradu\u00E7\u00E3o -->\n <input type=\"time\" [(ngModel)]=\"endTime\" (change)=\"onTimeChange('end')\" />\n </div>\n\n <!-- Campo de hora \u00FAnica (se n\u00E3o for range) -->\n <div *ngIf=\"!rangeMode\" class=\"time-input\">\n <label>{{ locales[locale]?.startTimeLabel || 'Hora' }}</label> <!-- Usando o label de in\u00EDcio -->\n <input type=\"time\" [(ngModel)]=\"selectedTime\" (change)=\"onTimeChange('single')\" />\n </div>\n </div>\n\n <!-- Bot\u00E3o de fechar o calend\u00E1rio -->\n <button class=\"close-button\" (click)=\"closeCalendar()\">{{ closeButtonLabel }}</button>\n </div>\n </div>\n </div>\n</div>\n", styles: ["@charset \"UTF-8\";.calendar-container{overflow:hidden;max-height:0;transition:max-height .4s ease;position:absolute;top:100%;left:0;z-index:9999;background-color:#fff;box-shadow:0 4px 12px #0000001a;width:auto;max-width:none}.calendar-wrapper{position:relative}@media (max-width: 300px){.calendar-container{width:100vw;left:0}}.calendar-container.open{max-height:500px}.calendar{display:inline-block;border:1px solid #ccc;border-radius:8px;padding:10px;width:450px;font-family:var(--font-family);transition:max-height .4s ease;background-color:#fdfdfd}.calendar .calendar-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:10px;font-weight:700}.calendar .calendar-header button{background-color:var(--primary-color);color:var(--text-color);border:none;padding:8px 12px;cursor:pointer;border-radius:8px;font-size:1.2rem;transition:background-color .2s}.calendar .calendar-header button:hover{background-color:var(--secondary-color)}.calendar .calendar-header span{font-size:1.4rem;color:var(--primary-color);text-align:center;flex-grow:1}.calendar .calendar-body{display:grid;grid-template-columns:repeat(7,1fr);gap:7px}.calendar .calendar-body .calendar-day-names{display:contents}.calendar .calendar-body .calendar-day-names span{text-align:center;font-weight:700;margin-bottom:5px;font-size:.9rem}.calendar .calendar-body .calendar-day-names span:nth-child(1){color:#ff8080}.calendar .calendar-body .calendar-day-names span:nth-child(7){color:#555}.calendar .calendar-body .calendar-days{display:contents}.calendar .calendar-body .calendar-days span{display:flex;justify-content:center;align-items:center;margin:1px;padding:10px;height:45px;width:45px;cursor:pointer;border-radius:50%;transition:background-color .2s,color .2s ease}.calendar .calendar-body .calendar-days span.today{background-color:var(--secondary-color);color:var(--text-color)}.calendar .calendar-body .calendar-days span.selected{background-color:var(--primary-color);color:var(--text-color)}.calendar .calendar-body .calendar-days span.disabled{background-color:#e9ecef;color:#999;cursor:not-allowed}.calendar .calendar-body .calendar-days span:hover:not(.disabled){background-color:var(--secondary-color);color:var(--text-color)}.custom-input{font-family:var(--font-family);color:#333;font-size:.9rem;height:46px;padding:.5rem .75rem;border:1px solid #ccc;border-radius:4px;width:100%;box-sizing:border-box}.custom-input:focus{outline:none;border-color:#ccc}.custom-input::placeholder{font-size:14px;color:#d3d3d3}.label-styles{font-weight:400;font-family:var(--font-family);font-size:16px;line-height:19.36px;text-align:left;margin-top:1rem;margin-bottom:.5rem}.error-message{position:relative;background-color:#ff8080;color:#fff;padding:10px;border-radius:8px;font-size:.9rem;max-width:250px;margin-top:5px}.error-message:after{content:\"\";position:absolute;top:100%;left:20px;border-width:10px;border-style:solid;border-color:#ff8080 transparent transparent transparent}.input-wrapper{position:relative;display:inline-block;width:100%}.input-wrapper .custom-input{width:100%;padding-right:40px;box-sizing:border-box}.input-wrapper .calendar-icon{position:absolute;top:50%;right:10px;transform:translateY(-50%);pointer-events:none;color:#b8b8b8}.calendar-days{display:contents}.calendar-days span{display:flex;justify-content:center;align-items:center;margin:1px;padding:10px;height:45px;width:45px;cursor:pointer;border-radius:50%;transition:background-color .2s,color .2s ease}.calendar-days span.today{background-color:var(--secondary-color);color:var(--text-color);text-decoration:underline}.calendar-days span.selected{background-color:var(--primary-color);color:var(--text-color)}.calendar-days span.in-range{background-color:#fd9;color:#000}.calendar-days span.disabled{background-color:#e9ecef;color:#999;cursor:not-allowed}.calendar-days span:hover:not(.disabled){background-color:var(--secondary-color);color:var(--text-color)}.calendar-body{position:relative}.close-button{float:right;margin-top:10px;background-color:#fff3cd;color:#383838;border:none;padding:6px 12px;cursor:pointer;border-radius:20px;font-size:12px;font-weight:500;transition:all .2s ease}.close-button:hover{background-color:#e9ebec;box-shadow:0 2px 4px #eeebeb26}.close-button:active{transform:translateY(1px)}.time-inputs{display:flex;justify-content:space-between;margin-top:10px}.time-input{display:flex;flex-direction:column;width:45%}.time-input label{font-size:.9rem;margin-bottom:5px}.time-input input{padding:8px;font-size:.9rem;border:1px solid #ccc;border-radius:4px}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.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: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type:
|
1156
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: CalendarArgentaComponent, selector: "argenta-calendar", inputs: { id: "id", placeholder: "placeholder", label: "label", minDate: "minDate", maxDate: "maxDate", locale: "locale", useTime: "useTime", initialDate: "initialDate", rangeMode: "rangeMode", startDate: "startDate", endDate: "endDate", closeButtonLabel: "closeButtonLabel" }, outputs: { rangeChange: "rangeChange" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"form-group\">\n <label [for]=\"id\" [ngClass]=\"'label-styles'\">{{ label }}</label>\n <div class=\"input-wrapper\">\n <input\n id=\"{{ id }}\"\n type=\"text\"\n class=\"custom-input\"\n [attr.placeholder]=\"rangeMode && useTime ? 'dd/MM/yyyy HH:mm - dd/MM/yyyy HH:mm' : \n rangeMode && !useTime ? 'dd/MM/yyyy - dd/MM/yyyy' :(!rangeMode && useTime ? 'dd/MM/yyyy HH:mm' : 'dd/MM/yyyy')\"\n [value]=\"inputDate\"\n (input)=\"onInputChange($event)\"\n (keypress)=\"handleKeyPress($event)\"\n (click)=\"toggleCalendar()\"\n />\n <lucide-icon name=\"calendar\" class=\"calendar-icon\"></lucide-icon>\n </div>\n\n <div *ngIf=\"invalidDate\" class=\"error-message\">\n {{ locales[locale].invalidDateMessage }}\n <span *ngIf=\"useTime\"> HH:mm.</span>\n </div>\n\n <div class=\"calendar-wrapper\">\n <div class=\"calendar-container\" [ngClass]=\"{ open: isCalendarVisible }\">\n <div class=\"calendar\">\n <div class=\"calendar-header\">\n <button (click)=\"prevMonth()\">‹</button>\n <span>{{ months[currentMonth] }} {{ currentYear }}</span>\n <button (click)=\"nextMonth()\">›</button>\n </div>\n\n <div class=\"calendar-body\">\n <div class=\"calendar-day-names\">\n <span *ngFor=\"let day of daysOfWeek\">{{ day }}</span>\n </div>\n\n <div class=\"calendar-days\">\n <span\n *ngFor=\"let day of daysInMonth; let i = index\"\n [class.today]=\"isToday(day)\"\n [class.selected]=\"isSelected(day)\"\n [class.in-range]=\"isInRange(day)\"\n [class.disabled]=\"isDateDisabled(day)\"\n (click)=\"day ? selectDate(day) : null\"\n >\n {{ day ? day : \"\" }}\n </span>\n </div>\n </div>\n\n <!-- Inputs para inser\u00E7\u00E3o das horas -->\n <div *ngIf=\"useTime\" class=\"time-inputs\">\n <!-- Campo de hora de in\u00EDcio -->\n <div *ngIf=\"rangeMode\" class=\"time-input\">\n <label>{{ locales[locale]?.startTimeLabel || 'Hora de In\u00EDcio' }}</label> <!-- Usando tradu\u00E7\u00E3o -->\n <input type=\"time\" [(ngModel)]=\"startTime\" (change)=\"onTimeChange('start')\" />\n </div>\n\n <!-- Campo de hora de fim -->\n <div *ngIf=\"rangeMode\" class=\"time-input\">\n <label>{{ locales[locale]?.endTimeLabel || 'Hora de Fim' }}</label> <!-- Usando tradu\u00E7\u00E3o -->\n <input type=\"time\" [(ngModel)]=\"endTime\" (change)=\"onTimeChange('end')\" />\n </div>\n\n <!-- Campo de hora \u00FAnica (se n\u00E3o for range) -->\n <div *ngIf=\"!rangeMode\" class=\"time-input\">\n <label>{{ locales[locale]?.startTimeLabel || 'Hora' }}</label> <!-- Usando o label de in\u00EDcio -->\n <input type=\"time\" [(ngModel)]=\"selectedTime\" (change)=\"onTimeChange('single')\" />\n </div>\n </div>\n\n <!-- Bot\u00E3o de fechar o calend\u00E1rio -->\n <button class=\"close-button\" (click)=\"closeCalendar()\">{{ closeButtonLabel }}</button>\n </div>\n </div>\n </div>\n</div>\n", styles: ["@charset \"UTF-8\";.calendar-container{overflow:hidden;max-height:0;transition:max-height .4s ease;position:absolute;top:100%;left:0;z-index:9999;background-color:#fff;box-shadow:0 4px 12px #0000001a;width:auto;max-width:none}.calendar-wrapper{position:relative}@media (max-width: 300px){.calendar-container{width:100vw;left:0}}.calendar-container.open{max-height:500px}.calendar{display:inline-block;border:1px solid #ccc;border-radius:8px;padding:10px;width:450px;font-family:var(--font-family);transition:max-height .4s ease;background-color:#fdfdfd}.calendar .calendar-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:10px;font-weight:700}.calendar .calendar-header button{background-color:var(--primary-color);color:var(--text-color);border:none;padding:8px 12px;cursor:pointer;border-radius:8px;font-size:1.2rem;transition:background-color .2s}.calendar .calendar-header button:hover{background-color:var(--secondary-color)}.calendar .calendar-header span{font-size:1.4rem;color:var(--primary-color);text-align:center;flex-grow:1}.calendar .calendar-body{display:grid;grid-template-columns:repeat(7,1fr);gap:7px}.calendar .calendar-body .calendar-day-names{display:contents}.calendar .calendar-body .calendar-day-names span{text-align:center;font-weight:700;margin-bottom:5px;font-size:.9rem}.calendar .calendar-body .calendar-day-names span:nth-child(1){color:#ff8080}.calendar .calendar-body .calendar-day-names span:nth-child(7){color:#555}.calendar .calendar-body .calendar-days{display:contents}.calendar .calendar-body .calendar-days span{display:flex;justify-content:center;align-items:center;margin:1px;padding:10px;height:45px;width:45px;cursor:pointer;border-radius:50%;transition:background-color .2s,color .2s ease}.calendar .calendar-body .calendar-days span.today{background-color:var(--secondary-color);color:var(--text-color)}.calendar .calendar-body .calendar-days span.selected{background-color:var(--primary-color);color:var(--text-color)}.calendar .calendar-body .calendar-days span.disabled{background-color:#e9ecef;color:#999;cursor:not-allowed}.calendar .calendar-body .calendar-days span:hover:not(.disabled){background-color:var(--secondary-color);color:var(--text-color)}.custom-input{font-family:var(--font-family);color:#333;font-size:.9rem;height:46px;padding:.5rem .75rem;border:1px solid #ccc;border-radius:4px;width:100%;box-sizing:border-box}.custom-input:focus{outline:none;border-color:#ccc}.custom-input::placeholder{font-size:14px;color:#d3d3d3}.label-styles{font-weight:400;font-family:var(--font-family);font-size:16px;line-height:19.36px;text-align:left;margin-top:1rem;margin-bottom:.5rem}.error-message{position:relative;background-color:#ff8080;color:#fff;padding:10px;border-radius:8px;font-size:.9rem;max-width:250px;margin-top:5px}.error-message:after{content:\"\";position:absolute;top:100%;left:20px;border-width:10px;border-style:solid;border-color:#ff8080 transparent transparent transparent}.input-wrapper{position:relative;display:inline-block;width:100%}.input-wrapper .custom-input{width:100%;padding-right:40px;box-sizing:border-box}.input-wrapper .calendar-icon{position:absolute;top:50%;right:10px;transform:translateY(-50%);pointer-events:none;color:#b8b8b8}.calendar-days{display:contents}.calendar-days span{display:flex;justify-content:center;align-items:center;margin:1px;padding:10px;height:45px;width:45px;cursor:pointer;border-radius:50%;transition:background-color .2s,color .2s ease}.calendar-days span.today{background-color:var(--secondary-color);color:var(--text-color);text-decoration:underline}.calendar-days span.selected{background-color:var(--primary-color);color:var(--text-color)}.calendar-days span.in-range{background-color:#fd9;color:#000}.calendar-days span.disabled{background-color:#e9ecef;color:#999;cursor:not-allowed}.calendar-days span:hover:not(.disabled){background-color:var(--secondary-color);color:var(--text-color)}.calendar-body{position:relative}.close-button{float:right;margin-top:10px;background-color:#fff3cd;color:#383838;border:none;padding:6px 12px;cursor:pointer;border-radius:20px;font-size:12px;font-weight:500;transition:all .2s ease}.close-button:hover{background-color:#e9ebec;box-shadow:0 2px 4px #eeebeb26}.close-button:active{transform:translateY(1px)}.time-inputs{display:flex;justify-content:space-between;margin-top:10px}.time-input{display:flex;flex-direction:column;width:45%}.time-input label{font-size:.9rem;margin-bottom:5px}.time-input input{padding:8px;font-size:.9rem;border:1px solid #ccc;border-radius:4px}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.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: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i4.LucideAngularComponent, selector: "lucide-angular, lucide-icon, i-lucide, span-lucide", inputs: ["class", "name", "img", "color", "absoluteStrokeWidth", "size", "strokeWidth"] }] }); }
|
1155
1157
|
}
|
1156
1158
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CalendarArgentaComponent, decorators: [{
|
1157
1159
|
type: Component,
|
@@ -1525,192 +1527,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
1525
1527
|
type: Output
|
1526
1528
|
}] } });
|
1527
1529
|
|
1528
|
-
class DragDropListComponent {
|
1529
|
-
constructor() {
|
1530
|
-
this.nonSelectedList = [];
|
1531
|
-
this.nonSelectedButtonClick = new EventEmitter();
|
1532
|
-
this.nonSelectedInputChanged = new EventEmitter();
|
1533
|
-
this.selectedList = [];
|
1534
|
-
this.selectedButtonClick = new EventEmitter();
|
1535
|
-
this.selectedInputChanged = new EventEmitter();
|
1536
|
-
this.nonSelectedListInputSubject = new Subject();
|
1537
|
-
this.selectedListInputSubject = new Subject();
|
1538
|
-
this.ButtonClasses = ButtonClasses; // Adicione a enumeração ao componente
|
1539
|
-
this.draggedItem = null;
|
1540
|
-
this.nonSelectedListInputSubject.pipe(debounceTime(2000)).subscribe((value) => {
|
1541
|
-
this.nonSelectedInputChanged.emit(value);
|
1542
|
-
});
|
1543
|
-
this.selectedListInputSubject.pipe(debounceTime(2000)).subscribe((value) => {
|
1544
|
-
this.selectedInputChanged.emit(value);
|
1545
|
-
});
|
1546
|
-
}
|
1547
|
-
onDragStart(item) {
|
1548
|
-
this.draggedItem = item;
|
1549
|
-
}
|
1550
|
-
onDragOver(event) {
|
1551
|
-
event.preventDefault();
|
1552
|
-
}
|
1553
|
-
onDrop(list, event) {
|
1554
|
-
event.preventDefault();
|
1555
|
-
if (this.draggedItem) {
|
1556
|
-
const index = list.indexOf(this.draggedItem);
|
1557
|
-
if (index === -1) {
|
1558
|
-
this.removeItem(this.draggedItem);
|
1559
|
-
list.push(this.draggedItem);
|
1560
|
-
}
|
1561
|
-
this.draggedItem = null;
|
1562
|
-
}
|
1563
|
-
}
|
1564
|
-
removeItem(item) {
|
1565
|
-
[this.nonSelectedList, this.selectedList].forEach((list) => {
|
1566
|
-
const index = list.indexOf(item);
|
1567
|
-
if (index !== -1) {
|
1568
|
-
list.splice(index, 1);
|
1569
|
-
}
|
1570
|
-
});
|
1571
|
-
}
|
1572
|
-
nonSelectedListInputChange(event) {
|
1573
|
-
this.nonSelectedListInputSubject.next(event.target.value);
|
1574
|
-
}
|
1575
|
-
selectedListInputChange(event) {
|
1576
|
-
this.selectedListInputSubject.next(event.target.value);
|
1577
|
-
}
|
1578
|
-
selButtonClick() {
|
1579
|
-
this.selectedButtonClick.emit();
|
1580
|
-
}
|
1581
|
-
nonSelButtonClick() {
|
1582
|
-
this.nonSelectedButtonClick.emit();
|
1583
|
-
}
|
1584
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DragDropListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
1585
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: DragDropListComponent, selector: "argenta-drag-drop-list", inputs: { nonSelectedTitle: "nonSelectedTitle", nonSelectedList: "nonSelectedList", nonSelectedButtonLabel: "nonSelectedButtonLabel", selectedTitle: "selectedTitle", selectedList: "selectedList", selectedButtonLabel: "selectedButtonLabel" }, outputs: { nonSelectedButtonClick: "nonSelectedButtonClick", nonSelectedInputChanged: "nonSelectedInputChanged", selectedButtonClick: "selectedButtonClick", selectedInputChanged: "selectedInputChanged" }, ngImport: i0, template: "<!-- Cont\u00EAiner externo para dar a apar\u00EAncia de grupo -->\n<div class=\"group-container\">\n <div class=\"container\">\n <!-- Lista 1 com input -->\n <div\n class=\"list\"\n (dragover)=\"onDragOver($event)\"\n (drop)=\"onDrop(nonSelectedList, $event)\"\n >\n <div class=\"row\">\n <h6 class=\"col-md-8\">{{ nonSelectedTitle }}</h6>\n <div *ngIf=\"nonSelectedButtonLabel\" class=\"col-md-4 align-end\">\n <argenta-custom-button\n label=\"{{ nonSelectedButtonLabel }}\"\n (onButtonClick)=\"nonSelButtonClick()\"\n class=\"align-end\"\n [btnClass]=\"ButtonClasses.Primary\"\n >\n </argenta-custom-button>\n </div>\n </div>\n <input\n type=\"text\"\n class=\"list-input\"\n (input)=\"nonSelectedListInputChange($event)\"\n />\n <div\n *ngFor=\"let item of nonSelectedList\"\n class=\"item-card\"\n draggable=\"true\"\n (dragstart)=\"onDragStart(item)\"\n >\n {{ item.descricao }}\n </div>\n </div>\n\n <!-- Lista 2 com input -->\n <div\n class=\"list\"\n (dragover)=\"onDragOver($event)\"\n (drop)=\"onDrop(selectedList, $event)\"\n >\n <div class=\"row\">\n <h6 class=\"col-md-8\">{{ selectedTitle }}</h6>\n <div *ngIf=\"selectedButtonLabel\" class=\"col-md-4 align-end\">\n <argenta-custom-button\n label=\"{{ selectedButtonLabel }}\"\n (onButtonClick)=\"selButtonClick()\"\n class=\"align-end\"\n [btnClass]=\"ButtonClasses.Primary\"\n >\n </argenta-custom-button>\n </div>\n </div>\n <input\n type=\"text\"\n class=\"list-input\"\n (input)=\"selectedListInputChange($event)\"\n />\n <div\n *ngFor=\"let item of selectedList\"\n class=\"item-card\"\n draggable=\"true\"\n (dragstart)=\"onDragStart(item)\"\n >\n {{ item.descricao }}\n </div>\n </div>\n </div>\n</div>\n", styles: ["@charset \"UTF-8\";.group-container{display:flex;justify-content:center;padding:20px;background-color:#fff;border-radius:12px;box-shadow:0 4px 8px #0000001a;width:80%;margin:auto}.container{display:flex;gap:20px;width:100%}.list{flex:1;padding:10px;background-color:#f0f0f0;border-radius:8px;display:flex;flex-direction:column;align-items:flex-start;gap:10px}.list-input{width:100%;height:40px;margin-bottom:15px;border-radius:4px;border:1px solid #ccc;outline:none;font-size:1rem;resize:none}.item-card{width:100%;padding:15px;background-color:#fff;border-radius:8px;box-shadow:0 2px 5px #0003;cursor:move;display:flex;align-items:center;justify-content:center;text-align:center;font-family:var(--font-family);font-weight:500;font-size:1.1rem;color:#333}.row{display:flex;justify-content:space-between;align-items:center;width:100%;max-height:50px;height:50px}.align-end{display:flex;justify-content:flex-end}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: ButtonComponent, selector: "argenta-custom-button", inputs: ["type", "label", "btnClass", "fontSize", "disabled", "autofocus", "form", "formaction", "formenctype", "formmethod", "formnovalidate", "formtarget", "name", "value", "permissions"], outputs: ["onButtonClick"] }] }); }
|
1586
|
-
}
|
1587
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DragDropListComponent, decorators: [{
|
1588
|
-
type: Component,
|
1589
|
-
args: [{ selector: "argenta-drag-drop-list", template: "<!-- Cont\u00EAiner externo para dar a apar\u00EAncia de grupo -->\n<div class=\"group-container\">\n <div class=\"container\">\n <!-- Lista 1 com input -->\n <div\n class=\"list\"\n (dragover)=\"onDragOver($event)\"\n (drop)=\"onDrop(nonSelectedList, $event)\"\n >\n <div class=\"row\">\n <h6 class=\"col-md-8\">{{ nonSelectedTitle }}</h6>\n <div *ngIf=\"nonSelectedButtonLabel\" class=\"col-md-4 align-end\">\n <argenta-custom-button\n label=\"{{ nonSelectedButtonLabel }}\"\n (onButtonClick)=\"nonSelButtonClick()\"\n class=\"align-end\"\n [btnClass]=\"ButtonClasses.Primary\"\n >\n </argenta-custom-button>\n </div>\n </div>\n <input\n type=\"text\"\n class=\"list-input\"\n (input)=\"nonSelectedListInputChange($event)\"\n />\n <div\n *ngFor=\"let item of nonSelectedList\"\n class=\"item-card\"\n draggable=\"true\"\n (dragstart)=\"onDragStart(item)\"\n >\n {{ item.descricao }}\n </div>\n </div>\n\n <!-- Lista 2 com input -->\n <div\n class=\"list\"\n (dragover)=\"onDragOver($event)\"\n (drop)=\"onDrop(selectedList, $event)\"\n >\n <div class=\"row\">\n <h6 class=\"col-md-8\">{{ selectedTitle }}</h6>\n <div *ngIf=\"selectedButtonLabel\" class=\"col-md-4 align-end\">\n <argenta-custom-button\n label=\"{{ selectedButtonLabel }}\"\n (onButtonClick)=\"selButtonClick()\"\n class=\"align-end\"\n [btnClass]=\"ButtonClasses.Primary\"\n >\n </argenta-custom-button>\n </div>\n </div>\n <input\n type=\"text\"\n class=\"list-input\"\n (input)=\"selectedListInputChange($event)\"\n />\n <div\n *ngFor=\"let item of selectedList\"\n class=\"item-card\"\n draggable=\"true\"\n (dragstart)=\"onDragStart(item)\"\n >\n {{ item.descricao }}\n </div>\n </div>\n </div>\n</div>\n", styles: ["@charset \"UTF-8\";.group-container{display:flex;justify-content:center;padding:20px;background-color:#fff;border-radius:12px;box-shadow:0 4px 8px #0000001a;width:80%;margin:auto}.container{display:flex;gap:20px;width:100%}.list{flex:1;padding:10px;background-color:#f0f0f0;border-radius:8px;display:flex;flex-direction:column;align-items:flex-start;gap:10px}.list-input{width:100%;height:40px;margin-bottom:15px;border-radius:4px;border:1px solid #ccc;outline:none;font-size:1rem;resize:none}.item-card{width:100%;padding:15px;background-color:#fff;border-radius:8px;box-shadow:0 2px 5px #0003;cursor:move;display:flex;align-items:center;justify-content:center;text-align:center;font-family:var(--font-family);font-weight:500;font-size:1.1rem;color:#333}.row{display:flex;justify-content:space-between;align-items:center;width:100%;max-height:50px;height:50px}.align-end{display:flex;justify-content:flex-end}\n"] }]
|
1590
|
-
}], ctorParameters: function () { return []; }, propDecorators: { nonSelectedTitle: [{
|
1591
|
-
type: Input
|
1592
|
-
}], nonSelectedList: [{
|
1593
|
-
type: Input
|
1594
|
-
}], nonSelectedButtonLabel: [{
|
1595
|
-
type: Input
|
1596
|
-
}], nonSelectedButtonClick: [{
|
1597
|
-
type: Output
|
1598
|
-
}], nonSelectedInputChanged: [{
|
1599
|
-
type: Output
|
1600
|
-
}], selectedTitle: [{
|
1601
|
-
type: Input
|
1602
|
-
}], selectedList: [{
|
1603
|
-
type: Input
|
1604
|
-
}], selectedButtonLabel: [{
|
1605
|
-
type: Input
|
1606
|
-
}], selectedButtonClick: [{
|
1607
|
-
type: Output
|
1608
|
-
}], selectedInputChanged: [{
|
1609
|
-
type: Output
|
1610
|
-
}] } });
|
1611
|
-
|
1612
|
-
class DynamicModalComponent {
|
1613
|
-
constructor() {
|
1614
|
-
this.modalTitle = "Modal Title";
|
1615
|
-
this.modalSizeClass = "";
|
1616
|
-
this.modalId = "dynamicModal"; // ID único para cada modal
|
1617
|
-
}
|
1618
|
-
openModal() {
|
1619
|
-
const modalElement = document.getElementById(this.modalId);
|
1620
|
-
if (modalElement) {
|
1621
|
-
modalElement.classList.add("show");
|
1622
|
-
modalElement.setAttribute("aria-hidden", "false");
|
1623
|
-
modalElement.style.display = "block";
|
1624
|
-
document.body.classList.add("modal-open");
|
1625
|
-
// Adiciona o backdrop manualmente se não existir
|
1626
|
-
if (!document.querySelector(`.modal-backdrop[data-modal-id="${this.modalId}"]`)) {
|
1627
|
-
const backdrop = document.createElement("div");
|
1628
|
-
backdrop.className = "modal-backdrop fade show";
|
1629
|
-
backdrop.setAttribute("data-modal-id", this.modalId);
|
1630
|
-
document.body.appendChild(backdrop);
|
1631
|
-
}
|
1632
|
-
}
|
1633
|
-
}
|
1634
|
-
closeModal() {
|
1635
|
-
const modalElement = document.getElementById(this.modalId);
|
1636
|
-
if (modalElement) {
|
1637
|
-
modalElement.classList.remove("show");
|
1638
|
-
modalElement.setAttribute("aria-hidden", "true");
|
1639
|
-
modalElement.style.display = "none";
|
1640
|
-
document.body.classList.remove("modal-open");
|
1641
|
-
document
|
1642
|
-
.querySelector(`.modal-backdrop[data-modal-id="${this.modalId}"]`)
|
1643
|
-
?.remove();
|
1644
|
-
}
|
1645
|
-
}
|
1646
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DynamicModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
1647
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: DynamicModalComponent, selector: "argenta-dynamic-modal", inputs: { modalTitle: "modalTitle", modalSizeClass: "modalSizeClass", modalId: "modalId" }, ngImport: i0, template: "<div\n class=\"modal fade\"\n [id]=\"modalId\"\n tabindex=\"-1\"\n [attr.aria-labelledby]=\"modalId + 'Label'\"\n aria-hidden=\"true\"\n>\n <div class=\"modal-dialog\" [ngClass]=\"modalSizeClass\">\n <div class=\"modal-content\">\n <div class=\"modal-header custom-header\">\n <h5 class=\"modal-title custom-modal-title\" [id]=\"modalId + 'Label'\">\n {{ modalTitle }}\n </h5>\n <button\n type=\"button\"\n class=\"custom-close-button\"\n (click)=\"closeModal()\"\n aria-label=\"Close\"\n >\n ×\n </button>\n </div>\n <div class=\"modal-body custom-body\">\n <ng-content select=\"[modal-body]\"></ng-content>\n </div>\n <div class=\"modal-footer custom-footer\">\n <ng-content select=\"[modal-footer]\"></ng-content>\n </div>\n </div>\n </div>\n</div>\n", styles: [".custom-header{background-color:var(--primary-color)!important;color:var(--text-color)!important;font-size:1.25rem!important;font-family:var(--font-family)!important;padding:1rem;position:relative}.custom-header .custom-close-button{position:absolute;right:1rem;background:none;border:none;font-size:2.5rem;color:var(--text-color);cursor:pointer}.custom-header .custom-close-button:hover{color:var(--danger-color)}.custom-modal-title{color:var(--text-color)!important;font-size:1.8rem!important;font-family:var(--font-family)!important}.custom-body{background-color:#fff;padding:1rem}.custom-footer{background-color:#fff;padding:.75rem;display:flex;justify-content:flex-end;gap:.5rem}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] }); }
|
1648
|
-
}
|
1649
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DynamicModalComponent, decorators: [{
|
1650
|
-
type: Component,
|
1651
|
-
args: [{ selector: "argenta-dynamic-modal", template: "<div\n class=\"modal fade\"\n [id]=\"modalId\"\n tabindex=\"-1\"\n [attr.aria-labelledby]=\"modalId + 'Label'\"\n aria-hidden=\"true\"\n>\n <div class=\"modal-dialog\" [ngClass]=\"modalSizeClass\">\n <div class=\"modal-content\">\n <div class=\"modal-header custom-header\">\n <h5 class=\"modal-title custom-modal-title\" [id]=\"modalId + 'Label'\">\n {{ modalTitle }}\n </h5>\n <button\n type=\"button\"\n class=\"custom-close-button\"\n (click)=\"closeModal()\"\n aria-label=\"Close\"\n >\n ×\n </button>\n </div>\n <div class=\"modal-body custom-body\">\n <ng-content select=\"[modal-body]\"></ng-content>\n </div>\n <div class=\"modal-footer custom-footer\">\n <ng-content select=\"[modal-footer]\"></ng-content>\n </div>\n </div>\n </div>\n</div>\n", styles: [".custom-header{background-color:var(--primary-color)!important;color:var(--text-color)!important;font-size:1.25rem!important;font-family:var(--font-family)!important;padding:1rem;position:relative}.custom-header .custom-close-button{position:absolute;right:1rem;background:none;border:none;font-size:2.5rem;color:var(--text-color);cursor:pointer}.custom-header .custom-close-button:hover{color:var(--danger-color)}.custom-modal-title{color:var(--text-color)!important;font-size:1.8rem!important;font-family:var(--font-family)!important}.custom-body{background-color:#fff;padding:1rem}.custom-footer{background-color:#fff;padding:.75rem;display:flex;justify-content:flex-end;gap:.5rem}\n"] }]
|
1652
|
-
}], propDecorators: { modalTitle: [{
|
1653
|
-
type: Input
|
1654
|
-
}], modalSizeClass: [{
|
1655
|
-
type: Input
|
1656
|
-
}], modalId: [{
|
1657
|
-
type: Input
|
1658
|
-
}] } });
|
1659
|
-
|
1660
|
-
class DynamicTableComponent {
|
1661
|
-
constructor() {
|
1662
|
-
this.itemsPerPageOptions = [10, 20, 50];
|
1663
|
-
this.showPageInfo = true;
|
1664
|
-
this.currentPage = 1;
|
1665
|
-
this.itemsPerPage = 10;
|
1666
|
-
}
|
1667
|
-
get totalItems() {
|
1668
|
-
return this.config.totalItems ?? this.config.data.length;
|
1669
|
-
}
|
1670
|
-
get paginatedData() {
|
1671
|
-
if (!this.config.pagination) {
|
1672
|
-
// Retorna todos os dados se a paginação estiver desativada
|
1673
|
-
return this.config.data;
|
1674
|
-
}
|
1675
|
-
const itemsPerPage = this.config.itemsPerPage || this.itemsPerPage;
|
1676
|
-
const startIndex = (this.currentPage - 1) * itemsPerPage;
|
1677
|
-
return this.config.data.slice(startIndex, startIndex + itemsPerPage);
|
1678
|
-
}
|
1679
|
-
ngOnInit() {
|
1680
|
-
if (!this.config || !this.config.columns || !this.config.data) {
|
1681
|
-
throw new Error("DynamicTableComponent: Configuração inválida.");
|
1682
|
-
}
|
1683
|
-
// Define valores padrão se não especificados
|
1684
|
-
this.config.showHeader = this.config.showHeader ?? true; // Exibe o cabeçalho por padrão
|
1685
|
-
this.config.pagination = this.config.pagination ?? true; // Ativa paginação por padrão
|
1686
|
-
this.itemsPerPage = this.config.itemsPerPage || 10;
|
1687
|
-
}
|
1688
|
-
onPageChange(newPage) {
|
1689
|
-
this.currentPage = newPage;
|
1690
|
-
}
|
1691
|
-
onItemsPerPageChange(event) {
|
1692
|
-
const target = event.target;
|
1693
|
-
this.itemsPerPage = +target.value;
|
1694
|
-
this.currentPage = 1; // Reinicia a paginação ao alterar os itens por página
|
1695
|
-
}
|
1696
|
-
// Getter para garantir que totalItems nunca seja undefined
|
1697
|
-
get safeTotalItems() {
|
1698
|
-
return this.totalItems || 0;
|
1699
|
-
}
|
1700
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DynamicTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
1701
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: DynamicTableComponent, selector: "argenta-dynamic-table", inputs: { config: "config", itemsPerPageOptions: "itemsPerPageOptions", showPageInfo: "showPageInfo" }, ngImport: i0, template: "<table class=\"table\" [ngClass]=\"{ nested: config.isNested }\">\n <thead *ngIf=\"config.showHeader\">\n <tr>\n <th *ngFor=\"let column of config.columns\">{{ column.header }}</th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let row of paginatedData\">\n <td *ngFor=\"let column of config.columns\">\n <ng-container [ngSwitch]=\"column.type\">\n <span *ngSwitchCase=\"'text'\">{{ row[column.key] }}</span>\n <ng-container *ngSwitchCase=\"'template'\">\n <ng-container\n *ngTemplateOutlet=\"\n column.template || null;\n context: { $implicit: row }\n \"\n ></ng-container>\n </ng-container>\n </ng-container>\n </td>\n </tr>\n </tbody>\n</table>\n\n<div\n class=\"text-center pagination-controls\"\n [ngClass]=\"{ nested: config.isNested }\"\n *ngIf=\"config.pagination\"\n>\n <custom-pagination\n [totalItems]=\"safeTotalItems\"\n [itemsPerPage]=\"itemsPerPage\"\n [currentPage]=\"currentPage\"\n [showPageInfo]=\"showPageInfo\"\n (pageChange)=\"onPageChange($event)\"\n >\n </custom-pagination>\n</div>\n", styles: ["@charset \"UTF-8\";.table{width:100%;border-collapse:collapse;border-spacing:0}.table{width:100%;border-collapse:separate;border-spacing:0;overflow:hidden}.table thead th{background-color:var(--primary-color);color:var(--text-color);font-family:var(--font-family);font-size:14px;font-weight:600;padding:10px;border-bottom:.1rem solid #dcdcdc;text-align:center;line-height:2.5}.table thead th:first-child{border-top-left-radius:10px}.table thead th:last-child{border-top-right-radius:10px}.table.nested thead th{font-size:.7rem;padding:7px;line-height:.8}.table tbody td{font-family:var(--font-family);font-size:14px;color:#737b7b;padding:10px;border-bottom:.1rem solid #dcdcdc;text-align:center}.table tbody td:first-child{text-align:left;padding-left:1.4rem}.table.nested tbody td:first-child{padding-left:1rem}.table tbody tr:hover{background-color:#f5f5f5!important;transition:background-color .3s ease}.table.nested tbody tr:hover{background-color:#f0f0f0!important}.pagination-controls{display:flex;justify-content:center;align-items:center;margin-top:1rem}.pagination-controls.nested{font-size:.7rem;transform:scale(.7);margin-top:.5rem}.data-table-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:1rem}.left-section{display:flex;align-items:center}.items-per-page-label{font-family:var(--font-family);font-size:14px;color:#666;margin-right:.5rem}.custom-select{font-family:var(--font-family);font-size:14px;padding:.375rem 1.75rem .375rem .75rem;border:1px solid #ccc;border-radius:.25rem;appearance:none;background:#fff url('data:image/svg+xml;charset=US-ASCII,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 4 5\"><path fill=\"#666\" d=\"M2 0L0 2h4L2 0zM2 5l2-2H0l2 2z\"/></svg>') no-repeat right .75rem center/8px 10px}.custom-select:focus{border-color:#80bdff;outline:none;box-shadow:0 0 0 .2rem #007bff40}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "component", type: CustomPaginationComponent, selector: "custom-pagination", inputs: ["totalItems", "itemsPerPage", "currentPage", "showPageInfo"], outputs: ["pageChange"] }] }); }
|
1702
|
-
}
|
1703
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DynamicTableComponent, decorators: [{
|
1704
|
-
type: Component,
|
1705
|
-
args: [{ selector: "argenta-dynamic-table", template: "<table class=\"table\" [ngClass]=\"{ nested: config.isNested }\">\n <thead *ngIf=\"config.showHeader\">\n <tr>\n <th *ngFor=\"let column of config.columns\">{{ column.header }}</th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let row of paginatedData\">\n <td *ngFor=\"let column of config.columns\">\n <ng-container [ngSwitch]=\"column.type\">\n <span *ngSwitchCase=\"'text'\">{{ row[column.key] }}</span>\n <ng-container *ngSwitchCase=\"'template'\">\n <ng-container\n *ngTemplateOutlet=\"\n column.template || null;\n context: { $implicit: row }\n \"\n ></ng-container>\n </ng-container>\n </ng-container>\n </td>\n </tr>\n </tbody>\n</table>\n\n<div\n class=\"text-center pagination-controls\"\n [ngClass]=\"{ nested: config.isNested }\"\n *ngIf=\"config.pagination\"\n>\n <custom-pagination\n [totalItems]=\"safeTotalItems\"\n [itemsPerPage]=\"itemsPerPage\"\n [currentPage]=\"currentPage\"\n [showPageInfo]=\"showPageInfo\"\n (pageChange)=\"onPageChange($event)\"\n >\n </custom-pagination>\n</div>\n", styles: ["@charset \"UTF-8\";.table{width:100%;border-collapse:collapse;border-spacing:0}.table{width:100%;border-collapse:separate;border-spacing:0;overflow:hidden}.table thead th{background-color:var(--primary-color);color:var(--text-color);font-family:var(--font-family);font-size:14px;font-weight:600;padding:10px;border-bottom:.1rem solid #dcdcdc;text-align:center;line-height:2.5}.table thead th:first-child{border-top-left-radius:10px}.table thead th:last-child{border-top-right-radius:10px}.table.nested thead th{font-size:.7rem;padding:7px;line-height:.8}.table tbody td{font-family:var(--font-family);font-size:14px;color:#737b7b;padding:10px;border-bottom:.1rem solid #dcdcdc;text-align:center}.table tbody td:first-child{text-align:left;padding-left:1.4rem}.table.nested tbody td:first-child{padding-left:1rem}.table tbody tr:hover{background-color:#f5f5f5!important;transition:background-color .3s ease}.table.nested tbody tr:hover{background-color:#f0f0f0!important}.pagination-controls{display:flex;justify-content:center;align-items:center;margin-top:1rem}.pagination-controls.nested{font-size:.7rem;transform:scale(.7);margin-top:.5rem}.data-table-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:1rem}.left-section{display:flex;align-items:center}.items-per-page-label{font-family:var(--font-family);font-size:14px;color:#666;margin-right:.5rem}.custom-select{font-family:var(--font-family);font-size:14px;padding:.375rem 1.75rem .375rem .75rem;border:1px solid #ccc;border-radius:.25rem;appearance:none;background:#fff url('data:image/svg+xml;charset=US-ASCII,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 4 5\"><path fill=\"#666\" d=\"M2 0L0 2h4L2 0zM2 5l2-2H0l2 2z\"/></svg>') no-repeat right .75rem center/8px 10px}.custom-select:focus{border-color:#80bdff;outline:none;box-shadow:0 0 0 .2rem #007bff40}\n"] }]
|
1706
|
-
}], ctorParameters: function () { return []; }, propDecorators: { config: [{
|
1707
|
-
type: Input
|
1708
|
-
}], itemsPerPageOptions: [{
|
1709
|
-
type: Input
|
1710
|
-
}], showPageInfo: [{
|
1711
|
-
type: Input
|
1712
|
-
}] } });
|
1713
|
-
|
1714
1530
|
class FileUploadComponent {
|
1715
1531
|
constructor(authService) {
|
1716
1532
|
this.authService = authService;
|
@@ -2242,174 +2058,124 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
2242
2058
|
type: Output
|
2243
2059
|
}] } });
|
2244
2060
|
|
2245
|
-
class
|
2246
|
-
|
2247
|
-
|
2248
|
-
|
2249
|
-
|
2061
|
+
class MultiSelectComponent {
|
2062
|
+
onClickOutside(event) {
|
2063
|
+
const target = event.target;
|
2064
|
+
if (!target.closest(".custom-select-container")) {
|
2065
|
+
this.closeDropdown();
|
2066
|
+
}
|
2250
2067
|
}
|
2251
|
-
|
2252
|
-
this.
|
2253
|
-
this.
|
2068
|
+
constructor(authService, http, cdr) {
|
2069
|
+
this.authService = authService;
|
2070
|
+
this.http = http;
|
2071
|
+
this.cdr = cdr;
|
2072
|
+
this.label = "Multi Select";
|
2073
|
+
this.data = [];
|
2074
|
+
this.placeholder = "";
|
2075
|
+
this.id = "multiSelectId";
|
2076
|
+
this.bindLabel = "";
|
2077
|
+
this.bindValue = "";
|
2078
|
+
this.closeOnSelect = false;
|
2079
|
+
this.searchUrl = "";
|
2080
|
+
this.multiple = true;
|
2081
|
+
this.searchParams = {};
|
2082
|
+
this.keyupEvent = new EventEmitter();
|
2083
|
+
this.lastSearchTerm = "";
|
2084
|
+
this.backupData = [];
|
2085
|
+
this.allItems = [];
|
2086
|
+
this.items = of([]);
|
2087
|
+
this.filteredItems = of([]);
|
2088
|
+
this.searchTerms = new Subject();
|
2089
|
+
this.isOpen = false;
|
2090
|
+
this.onChangeCallback = () => { };
|
2091
|
+
this.onTouchedCallback = () => { };
|
2092
|
+
this.isCourseEntered = false;
|
2093
|
+
this.compareFn = (item1, item2) => {
|
2094
|
+
return item1 && item2
|
2095
|
+
? item1[this.bindValue] === item2[this.bindValue]
|
2096
|
+
: item1 === item2;
|
2097
|
+
};
|
2254
2098
|
}
|
2255
|
-
|
2256
|
-
|
2257
|
-
|
2099
|
+
ngOnInit() {
|
2100
|
+
this.filteredItems = this.searchTerms.pipe(debounceTime(700), // Reduz chamadas repetitivas
|
2101
|
+
distinctUntilChanged(), // Ignora termos repetidos consecutivos
|
2102
|
+
switchMap((term) => {
|
2103
|
+
// Sempre busca no back-end
|
2104
|
+
return this.search(term).pipe(tap((fetchedItems) => {
|
2105
|
+
this.updateData(fetchedItems);
|
2106
|
+
}), map((fetchedItems) => this.filterOutSelected(fetchedItems)));
|
2107
|
+
}));
|
2108
|
+
this.filteredItems.subscribe({
|
2109
|
+
next: (items) => { },
|
2110
|
+
error: (err) => console.error("Erro ao buscar no back-end:", err),
|
2111
|
+
});
|
2112
|
+
this.fetchInitialData().subscribe((data) => {
|
2113
|
+
this.updateData(data);
|
2114
|
+
});
|
2258
2115
|
}
|
2259
|
-
|
2260
|
-
|
2116
|
+
onInputChange(event) {
|
2117
|
+
const input = event.target.value.trim();
|
2118
|
+
this.searchTerms.next(input);
|
2119
|
+
if (input === "") {
|
2120
|
+
this.fetchInitialData().subscribe((data) => {
|
2121
|
+
this.allItems = data;
|
2122
|
+
this.filteredItems = of(this.filterOutSelected(this.allItems));
|
2123
|
+
});
|
2124
|
+
}
|
2261
2125
|
}
|
2262
|
-
|
2263
|
-
return
|
2126
|
+
search(term) {
|
2127
|
+
return this.http.get(`${this.searchUrl}`, { params: { term } }).pipe(map((response) => {
|
2128
|
+
const transformedItems = response.map((item) => ({
|
2129
|
+
[this.bindValue]: item[this.bindValue],
|
2130
|
+
[this.bindLabel]: item[this.bindLabel],
|
2131
|
+
}));
|
2132
|
+
this.allItems = transformedItems;
|
2133
|
+
this.filteredItems = of(this.filterOutSelected(this.allItems));
|
2134
|
+
this.cdr.markForCheck(); // Notifica o Angular sobre a alteração
|
2135
|
+
return transformedItems;
|
2136
|
+
}), catchError((error) => {
|
2137
|
+
console.error("Erro ao buscar no back-end:", error);
|
2138
|
+
this.filteredItems = of([]);
|
2139
|
+
return of([]);
|
2140
|
+
}));
|
2264
2141
|
}
|
2265
|
-
|
2266
|
-
return this.
|
2142
|
+
fetchInitialData() {
|
2143
|
+
return this.http.get(this.searchUrl).pipe(map((response) => {
|
2144
|
+
const transformedItems = response.map((item) => ({
|
2145
|
+
[this.bindValue]: item[this.bindValue],
|
2146
|
+
[this.bindLabel]: item[this.bindLabel],
|
2147
|
+
}));
|
2148
|
+
this.allItems = transformedItems;
|
2149
|
+
return this.allItems;
|
2150
|
+
}), catchError((error) => {
|
2151
|
+
console.error("Erro ao carregar dados iniciais:", error);
|
2152
|
+
return of([]);
|
2153
|
+
}));
|
2267
2154
|
}
|
2268
|
-
|
2269
|
-
|
2270
|
-
|
2271
|
-
|
2272
|
-
|
2273
|
-
|
2155
|
+
ngOnChanges(changes) {
|
2156
|
+
if (changes["selected"] && !changes["selected"].isFirstChange()) {
|
2157
|
+
this.addSelectedItemsToData();
|
2158
|
+
}
|
2159
|
+
}
|
2160
|
+
updateData(newData) {
|
2161
|
+
newData.forEach((item) => {
|
2162
|
+
const existsInList = this.allItems.some((listItem) => this.compareFn(listItem, item));
|
2163
|
+
if (!existsInList) {
|
2164
|
+
this.allItems = [...this.allItems, item]; // Cria uma nova referência
|
2165
|
+
}
|
2274
2166
|
});
|
2275
|
-
|
2276
|
-
|
2277
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: JsonViewerComponent, selector: "argenta-json-viewer", inputs: { jsonData: "jsonData", isRoot: "isRoot", copyLabel: "copyLabel", showLabel: "showLabel", hideLabel: "hideLabel" }, ngImport: i0, template: "<div class=\"json-viewer-box\">\n <div class=\"toolbar\">\n <button\n *ngIf=\"isRoot\"\n class=\"action-button copy-button\"\n (click)=\"copyJson()\"\n >\n {{ copyLabel }}\n </button>\n <button\n *ngIf=\"isRoot\"\n class=\"action-button toggle-button\"\n (click)=\"toggleAll()\"\n >\n {{ allExpanded ? \"\u25BC \" + hideLabel : \"\u25BA \" + showLabel }}\n </button>\n </div>\n\n <div class=\"json-content\">\n <div *ngIf=\"isObject(jsonData)\">\n <div class=\"json-pair\" *ngFor=\"let key of objectKeys(jsonData)\">\n <span class=\"key\">\n {{ key }}:\n <button class=\"minimal-toggle-button\" (click)=\"toggleExpand(key)\">\n {{ isExpanded(key) ? \"\u25BC\" : \"\u25BA\" }}\n </button>\n </span>\n\n <div class=\"nested-json\" *ngIf=\"isExpanded(key)\">\n <argenta-json-viewer\n [jsonData]=\"jsonData[key]\"\n [isRoot]=\"false\"\n ></argenta-json-viewer>\n </div>\n <span *ngIf=\"!isExpanded(key) && isObject(jsonData[key])\">[...]</span>\n </div>\n </div>\n <span *ngIf=\"!isObject(jsonData)\">\n {{ jsonData }}\n </span>\n </div>\n</div>\n", styles: [".json-viewer-box{border:1px solid #ccc;padding:10px;border-radius:8px;font-family:Arial,sans-serif;background-color:#f9f9f9}.json-viewer-box .toolbar{display:flex;justify-content:space-between;align-items:center;margin-bottom:10px;padding-bottom:5px;border-bottom:1px solid #ddd}.json-viewer-box .action-button{background-color:#4caf50;color:#fff;border:none;padding:8px 16px;font-size:14px;border-radius:4px;cursor:pointer;transition:background-color .3s ease}.json-viewer-box .action-button:hover{background-color:#45a049}.json-viewer-box .minimal-toggle-button{background:none;border:none;color:#007bff;cursor:pointer;font-size:12px;margin-left:5px;padding:0;line-height:1}.json-viewer-box .minimal-toggle-button:hover{color:#0056b3}.json-viewer-box .json-content{margin-top:10px}.json-viewer-box .json-content .json-pair{margin-bottom:5px}.json-viewer-box .json-content .json-pair .key{font-weight:700;margin-right:5px;display:flex;align-items:center}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: JsonViewerComponent, selector: "argenta-json-viewer", inputs: ["jsonData", "isRoot", "copyLabel", "showLabel", "hideLabel"] }] }); }
|
2278
|
-
}
|
2279
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: JsonViewerComponent, decorators: [{
|
2280
|
-
type: Component,
|
2281
|
-
args: [{ selector: 'argenta-json-viewer', template: "<div class=\"json-viewer-box\">\n <div class=\"toolbar\">\n <button\n *ngIf=\"isRoot\"\n class=\"action-button copy-button\"\n (click)=\"copyJson()\"\n >\n {{ copyLabel }}\n </button>\n <button\n *ngIf=\"isRoot\"\n class=\"action-button toggle-button\"\n (click)=\"toggleAll()\"\n >\n {{ allExpanded ? \"\u25BC \" + hideLabel : \"\u25BA \" + showLabel }}\n </button>\n </div>\n\n <div class=\"json-content\">\n <div *ngIf=\"isObject(jsonData)\">\n <div class=\"json-pair\" *ngFor=\"let key of objectKeys(jsonData)\">\n <span class=\"key\">\n {{ key }}:\n <button class=\"minimal-toggle-button\" (click)=\"toggleExpand(key)\">\n {{ isExpanded(key) ? \"\u25BC\" : \"\u25BA\" }}\n </button>\n </span>\n\n <div class=\"nested-json\" *ngIf=\"isExpanded(key)\">\n <argenta-json-viewer\n [jsonData]=\"jsonData[key]\"\n [isRoot]=\"false\"\n ></argenta-json-viewer>\n </div>\n <span *ngIf=\"!isExpanded(key) && isObject(jsonData[key])\">[...]</span>\n </div>\n </div>\n <span *ngIf=\"!isObject(jsonData)\">\n {{ jsonData }}\n </span>\n </div>\n</div>\n", styles: [".json-viewer-box{border:1px solid #ccc;padding:10px;border-radius:8px;font-family:Arial,sans-serif;background-color:#f9f9f9}.json-viewer-box .toolbar{display:flex;justify-content:space-between;align-items:center;margin-bottom:10px;padding-bottom:5px;border-bottom:1px solid #ddd}.json-viewer-box .action-button{background-color:#4caf50;color:#fff;border:none;padding:8px 16px;font-size:14px;border-radius:4px;cursor:pointer;transition:background-color .3s ease}.json-viewer-box .action-button:hover{background-color:#45a049}.json-viewer-box .minimal-toggle-button{background:none;border:none;color:#007bff;cursor:pointer;font-size:12px;margin-left:5px;padding:0;line-height:1}.json-viewer-box .minimal-toggle-button:hover{color:#0056b3}.json-viewer-box .json-content{margin-top:10px}.json-viewer-box .json-content .json-pair{margin-bottom:5px}.json-viewer-box .json-content .json-pair .key{font-weight:700;margin-right:5px;display:flex;align-items:center}\n"] }]
|
2282
|
-
}], propDecorators: { jsonData: [{
|
2283
|
-
type: Input
|
2284
|
-
}], isRoot: [{
|
2285
|
-
type: Input
|
2286
|
-
}], copyLabel: [{
|
2287
|
-
type: Input
|
2288
|
-
}], showLabel: [{
|
2289
|
-
type: Input
|
2290
|
-
}], hideLabel: [{
|
2291
|
-
type: Input
|
2292
|
-
}] } });
|
2293
|
-
|
2294
|
-
class ModalComponent {
|
2295
|
-
constructor(activeModal) {
|
2296
|
-
this.activeModal = activeModal;
|
2297
|
-
this.onButtonClick = new EventEmitter(); // Novo evento
|
2298
|
-
}
|
2299
|
-
ngOnInit() {
|
2300
|
-
const componentRef = this.dynamicComponent.createComponent(this.component);
|
2301
|
-
const instance = componentRef.instance;
|
2302
|
-
if (this.componentInputs) {
|
2303
|
-
Object.keys(this.componentInputs).forEach(inputName => {
|
2304
|
-
instance[inputName] = this.componentInputs[inputName];
|
2305
|
-
});
|
2306
|
-
}
|
2307
|
-
}
|
2308
|
-
closeModal() {
|
2309
|
-
this.activeModal.close();
|
2310
|
-
}
|
2311
|
-
buttonClicked() {
|
2312
|
-
this.onButtonClick.emit(); // Emitindo o evento
|
2313
|
-
}
|
2314
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ModalComponent, deps: [{ token: i1$1.NgbActiveModal }], target: i0.ɵɵFactoryTarget.Component }); }
|
2315
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: ModalComponent, selector: "argenta-modal", inputs: { title: "title", component: "component", componentInputs: "componentInputs", closeButtonLabel: "closeButtonLabel", buttonLabel: "buttonLabel" }, outputs: { onButtonClick: "onButtonClick" }, viewQueries: [{ propertyName: "dynamicComponent", first: true, predicate: ["dynamicComponent"], descendants: true, read: ViewContainerRef, static: true }], ngImport: i0, template: "<div class=\"modal-header custom-modal-header\">\n <h4 class=\"modal-title\">{{ title }}</h4>\n <p class=\"float-right close-modal\" (click)=\"closeModal()\">X</p>\n</div>\n<div class=\"modal-body\">\n <ng-container #dynamicComponent></ng-container>\n</div>\n<div class=\"modal-footer\">\n <button class=\"btn btn-secondary\" (click)=\"closeModal()\">\n {{ closeButtonLabel }}\n </button>\n <button *ngIf=\"buttonLabel\" class=\"btn btn-custom\" (click)=\"buttonClicked()\">\n {{ buttonLabel }}\n </button>\n</div>\n", styles: [".modal-content{border-radius:15px;overflow:hidden}.custom-modal-header{background-color:var(--primary-color);color:var(--text-color);border-bottom:none;font-family:var(--font-family);display:flex;justify-content:space-between;align-items:center;padding:1rem}.modal-title{color:var(--text-color);font-size:20px}.close-modal{margin:0;cursor:pointer;font-size:1.5rem;color:var(--text-color)}.close-modal:hover{color:#ccc}.modal-footer{border-top:none}.btn-custom{background-color:var(--primary-color);color:var(--text-color);border-bottom:none}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] }); }
|
2316
|
-
}
|
2317
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ModalComponent, decorators: [{
|
2318
|
-
type: Component,
|
2319
|
-
args: [{ selector: 'argenta-modal', template: "<div class=\"modal-header custom-modal-header\">\n <h4 class=\"modal-title\">{{ title }}</h4>\n <p class=\"float-right close-modal\" (click)=\"closeModal()\">X</p>\n</div>\n<div class=\"modal-body\">\n <ng-container #dynamicComponent></ng-container>\n</div>\n<div class=\"modal-footer\">\n <button class=\"btn btn-secondary\" (click)=\"closeModal()\">\n {{ closeButtonLabel }}\n </button>\n <button *ngIf=\"buttonLabel\" class=\"btn btn-custom\" (click)=\"buttonClicked()\">\n {{ buttonLabel }}\n </button>\n</div>\n", styles: [".modal-content{border-radius:15px;overflow:hidden}.custom-modal-header{background-color:var(--primary-color);color:var(--text-color);border-bottom:none;font-family:var(--font-family);display:flex;justify-content:space-between;align-items:center;padding:1rem}.modal-title{color:var(--text-color);font-size:20px}.close-modal{margin:0;cursor:pointer;font-size:1.5rem;color:var(--text-color)}.close-modal:hover{color:#ccc}.modal-footer{border-top:none}.btn-custom{background-color:var(--primary-color);color:var(--text-color);border-bottom:none}\n"] }]
|
2320
|
-
}], ctorParameters: function () { return [{ type: i1$1.NgbActiveModal }]; }, propDecorators: { title: [{
|
2321
|
-
type: Input
|
2322
|
-
}], component: [{
|
2323
|
-
type: Input
|
2324
|
-
}], componentInputs: [{
|
2325
|
-
type: Input
|
2326
|
-
}], closeButtonLabel: [{
|
2327
|
-
type: Input
|
2328
|
-
}], buttonLabel: [{
|
2329
|
-
type: Input
|
2330
|
-
}], onButtonClick: [{
|
2331
|
-
type: Output
|
2332
|
-
}], dynamicComponent: [{
|
2333
|
-
type: ViewChild,
|
2334
|
-
args: ['dynamicComponent', { read: ViewContainerRef, static: true }]
|
2335
|
-
}] } });
|
2336
|
-
|
2337
|
-
class MultiSelectComponent {
|
2338
|
-
constructor(authService, http) {
|
2339
|
-
this.authService = authService;
|
2340
|
-
this.http = http;
|
2341
|
-
this.label = 'Multi Select';
|
2342
|
-
this.data = []; // Accepts an array of generic objects
|
2343
|
-
this.placeholder = 'Select items';
|
2344
|
-
this.id = 'multiSelectId';
|
2345
|
-
this.bindLabel = ''; // Generic dynamic label
|
2346
|
-
this.bindValue = ''; // Generic dynamic value
|
2347
|
-
this.closeOnSelect = false; // New property to control dropdown close behavior
|
2348
|
-
this.searchUrl = ''; // URL for backend search
|
2349
|
-
this.multiple = true; // New property to control single or multiple selection
|
2350
|
-
this.searchParams = {}; // Parâmetros de busca dinâmicos
|
2351
|
-
this.keyupEvent = new EventEmitter();
|
2352
|
-
this.backupData = []; // Backup of the initial data
|
2353
|
-
this.allItems = []; // Store the combined list
|
2354
|
-
this.items = of([]); // Initialization of the property
|
2355
|
-
this.filteredItems = of([]); // Filtered items
|
2356
|
-
this.searchTerms = new Subject(); // For search debounce
|
2357
|
-
this.onChangeCallback = () => { };
|
2358
|
-
this.onTouchedCallback = () => { };
|
2359
|
-
this.isCourseEntered = false;
|
2360
|
-
this.compareFn = (item1, item2) => {
|
2361
|
-
return item1 && item2 ? item1[this.bindValue] === item2[this.bindValue] : item1 === item2;
|
2362
|
-
};
|
2363
|
-
}
|
2364
|
-
ngOnInit() {
|
2365
|
-
this.backupData = [...this.data]; // Backup initial data
|
2366
|
-
this.allItems = [...this.data]; // Initialize allItems with the initial data
|
2367
|
-
this.items = of(this.allItems);
|
2368
|
-
this.fetchInitialData().subscribe(data => {
|
2369
|
-
this.updateData(data);
|
2370
|
-
this.filteredItems = this.searchTerms.pipe(debounceTime(700), startWith(''), // Start with an empty search to load the original list
|
2371
|
-
switchMap(term => this.search(term)));
|
2372
|
-
// Adicionar itens selecionados à lista após buscar dados iniciais
|
2373
|
-
this.addSelectedItemsToData();
|
2374
|
-
});
|
2375
|
-
}
|
2376
|
-
ngOnChanges(changes) {
|
2377
|
-
if (changes['selected'] && !changes['selected'].isFirstChange()) {
|
2378
|
-
this.addSelectedItemsToData();
|
2379
|
-
}
|
2380
|
-
}
|
2381
|
-
fetchInitialData() {
|
2382
|
-
return this.http.get(this.searchUrl).pipe(map((response) => {
|
2383
|
-
if (response && response.length > 0) {
|
2384
|
-
return response.map((item) => ({
|
2385
|
-
[this.bindValue]: item[this.bindValue],
|
2386
|
-
[this.bindLabel]: item[this.bindLabel]
|
2387
|
-
}));
|
2388
|
-
}
|
2389
|
-
return [];
|
2390
|
-
}), catchError((error) => {
|
2391
|
-
console.error('Error fetching initial data from backend:', error);
|
2392
|
-
return of([]);
|
2393
|
-
}));
|
2394
|
-
}
|
2395
|
-
updateData(newData) {
|
2396
|
-
newData.forEach((item) => {
|
2397
|
-
const existsInList = this.allItems.some(listItem => this.compareFn(listItem, item));
|
2398
|
-
if (!existsInList) {
|
2399
|
-
this.allItems.push(item);
|
2400
|
-
}
|
2401
|
-
});
|
2402
|
-
this.items = of(this.allItems);
|
2167
|
+
this.filteredItems = of([...this.allItems]); // Garante nova referência
|
2168
|
+
this.cdr.markForCheck(); // Notifica o Angular sobre mudanças
|
2403
2169
|
}
|
2404
2170
|
addSelectedItemsToData() {
|
2405
2171
|
if (this.selected) {
|
2406
2172
|
const selectedItems = this.multiple ? this.selected : [this.selected];
|
2407
2173
|
selectedItems.forEach((item) => {
|
2408
|
-
const existsInList = this.allItems.some(listItem => this.compareFn(listItem, item));
|
2174
|
+
const existsInList = this.allItems.some((listItem) => this.compareFn(listItem, item));
|
2409
2175
|
if (!existsInList) {
|
2410
2176
|
const newItem = {
|
2411
2177
|
[this.bindValue]: item[this.bindValue] || item,
|
2412
|
-
[this.bindLabel]: item[this.bindLabel] || item
|
2178
|
+
[this.bindLabel]: item[this.bindLabel] || item,
|
2413
2179
|
};
|
2414
2180
|
this.data.push(newItem);
|
2415
2181
|
this.allItems.push(newItem);
|
@@ -2436,60 +2202,15 @@ class MultiSelectComponent {
|
|
2436
2202
|
this.selected = event ? event : null;
|
2437
2203
|
}
|
2438
2204
|
this.onChangeCallback(this.selected);
|
2439
|
-
|
2440
|
-
|
2441
|
-
|
2442
|
-
|
2443
|
-
|
2444
|
-
|
2445
|
-
this.data.push(item);
|
2446
|
-
this.allItems.push(item); // Adicionar de volta aos itens disponíveis
|
2205
|
+
if (previousSelected && Array.isArray(previousSelected)) {
|
2206
|
+
const removedItems = previousSelected.filter((item) => !event.includes(item));
|
2207
|
+
removedItems.forEach((item) => {
|
2208
|
+
const existsInAllItems = this.allItems.some((listItem) => this.compareFn(listItem, item));
|
2209
|
+
if (!existsInAllItems) {
|
2210
|
+
this.allItems.push(item);
|
2447
2211
|
}
|
2448
2212
|
});
|
2449
|
-
|
2450
|
-
}
|
2451
|
-
onInputChange(event) {
|
2452
|
-
const input = event.target.value;
|
2453
|
-
this.searchTerms.next(input);
|
2454
|
-
}
|
2455
|
-
search(term) {
|
2456
|
-
if (!term.trim()) {
|
2457
|
-
// Se o termo de busca estiver vazio, retorna a lista completa
|
2458
|
-
return of(this.allItems);
|
2459
|
-
}
|
2460
|
-
// Filtra os itens localmente
|
2461
|
-
const filtered = this.allItems.filter((item) => item[this.bindLabel].toLowerCase().includes(term.toLowerCase()));
|
2462
|
-
if (filtered.length > 0) {
|
2463
|
-
console.log('Items filtered locally.');
|
2464
|
-
return of(filtered);
|
2465
|
-
}
|
2466
|
-
else if (this.searchUrl) {
|
2467
|
-
// Construir os parâmetros de busca dinamicamente
|
2468
|
-
const params = new URLSearchParams(this.searchParams);
|
2469
|
-
params.append('term', term);
|
2470
|
-
return this.http.get(`${this.searchUrl}?${params.toString()}`).pipe(map((response) => {
|
2471
|
-
if (response && response.length > 0) {
|
2472
|
-
// Transforma os itens do backend para o formato esperado pelo componente
|
2473
|
-
const transformedItems = response.map((item) => ({
|
2474
|
-
[this.bindValue]: item[this.bindValue],
|
2475
|
-
[this.bindLabel]: item[this.bindLabel]
|
2476
|
-
}));
|
2477
|
-
// Atualiza os dados com os novos itens buscados
|
2478
|
-
this.updateData(transformedItems);
|
2479
|
-
return this.allItems;
|
2480
|
-
}
|
2481
|
-
else {
|
2482
|
-
console.log('No items found in the backend search.');
|
2483
|
-
return this.allItems;
|
2484
|
-
}
|
2485
|
-
}), catchError((error) => {
|
2486
|
-
console.error('Error fetching from backend:', error);
|
2487
|
-
return of(this.allItems);
|
2488
|
-
}));
|
2489
|
-
}
|
2490
|
-
else {
|
2491
|
-
console.log('No search URL provided and no items found locally.');
|
2492
|
-
return of(this.allItems);
|
2213
|
+
this.items = of(this.allItems);
|
2493
2214
|
}
|
2494
2215
|
}
|
2495
2216
|
writeValue(value) {
|
@@ -2500,6 +2221,7 @@ class MultiSelectComponent {
|
|
2500
2221
|
this.selected = value || null;
|
2501
2222
|
}
|
2502
2223
|
this.addSelectedItemsToData();
|
2224
|
+
this.cdr.detectChanges();
|
2503
2225
|
}
|
2504
2226
|
registerOnChange(fn) {
|
2505
2227
|
this.onChangeCallback = fn;
|
@@ -2507,9 +2229,7 @@ class MultiSelectComponent {
|
|
2507
2229
|
registerOnTouched(fn) {
|
2508
2230
|
this.onTouchedCallback = fn;
|
2509
2231
|
}
|
2510
|
-
setDisabledState(isDisabled) {
|
2511
|
-
// No implementation needed for this example
|
2512
|
-
}
|
2232
|
+
setDisabledState(isDisabled) { }
|
2513
2233
|
hasPermission() {
|
2514
2234
|
if (!this.permissions || this.permissions.length === 0) {
|
2515
2235
|
return true;
|
@@ -2519,33 +2239,88 @@ class MultiSelectComponent {
|
|
2519
2239
|
}
|
2520
2240
|
catch (error) {
|
2521
2241
|
if (error instanceof Error) {
|
2522
|
-
console.error(
|
2242
|
+
console.error("Permission error:", error.message);
|
2523
2243
|
}
|
2524
2244
|
else {
|
2525
|
-
console.error(
|
2245
|
+
console.error("Unknown error occurred during permission check");
|
2526
2246
|
}
|
2527
2247
|
return true;
|
2528
2248
|
}
|
2529
2249
|
}
|
2530
|
-
|
2531
|
-
|
2250
|
+
toggleDropdown() {
|
2251
|
+
this.isOpen = !this.isOpen;
|
2252
|
+
}
|
2253
|
+
closeDropdown() {
|
2254
|
+
this.isOpen = false;
|
2255
|
+
}
|
2256
|
+
isSelected(item) {
|
2257
|
+
if (this.multiple) {
|
2258
|
+
return this.selected?.some((selectedItem) => this.compareFn(selectedItem, item));
|
2259
|
+
}
|
2260
|
+
else {
|
2261
|
+
return this.compareFn(this.selected, item);
|
2262
|
+
}
|
2263
|
+
}
|
2264
|
+
selectItem(item, event) {
|
2265
|
+
event.stopPropagation();
|
2266
|
+
if (!this.isSelected(item)) {
|
2267
|
+
if (this.multiple) {
|
2268
|
+
this.selected.push(item);
|
2269
|
+
}
|
2270
|
+
else {
|
2271
|
+
this.selected = [item];
|
2272
|
+
}
|
2273
|
+
}
|
2274
|
+
if (this.multiple) {
|
2275
|
+
this.allItems = this.allItems.filter((listItem) => !this.compareFn(listItem, item));
|
2276
|
+
}
|
2277
|
+
this.filteredItems = of(this.filterOutSelected(this.allItems));
|
2278
|
+
this.onSelectedChange(this.selected);
|
2279
|
+
if (this.closeOnSelect) {
|
2280
|
+
this.closeDropdown();
|
2281
|
+
}
|
2282
|
+
}
|
2283
|
+
filterByTerm(term) {
|
2284
|
+
return this.allItems.filter((item) => item[this.bindLabel]?.toLowerCase().includes(term.toLowerCase()));
|
2285
|
+
}
|
2286
|
+
filterOutSelected(items) {
|
2287
|
+
if (!this.multiple) {
|
2288
|
+
return items;
|
2289
|
+
}
|
2290
|
+
return items.filter((item) => !this.selected.some((selectedItem) => this.compareFn(selectedItem, item)));
|
2291
|
+
}
|
2292
|
+
removeSelectedItem(item, event) {
|
2293
|
+
event.stopPropagation();
|
2294
|
+
this.selected = this.selected.filter((selectedItem) => !this.compareFn(selectedItem, item));
|
2295
|
+
const existsInAllItems = this.allItems.some((listItem) => this.compareFn(listItem, item));
|
2296
|
+
if (!existsInAllItems) {
|
2297
|
+
this.allItems.push(item);
|
2298
|
+
}
|
2299
|
+
this.filteredItems = of(this.filterByTerm(this.lastSearchTerm || ""));
|
2300
|
+
this.onSelectedChange(this.selected);
|
2301
|
+
}
|
2302
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: MultiSelectComponent, deps: [{ token: AuthService }, { token: i1$2.HttpClient }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
2303
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: MultiSelectComponent, selector: "argenta-custom-multi-select", inputs: { label: "label", data: "data", placeholder: "placeholder", selected: "selected", id: "id", bindLabel: "bindLabel", bindValue: "bindValue", permissions: "permissions", closeOnSelect: "closeOnSelect", searchUrl: "searchUrl", multiple: "multiple", searchParams: "searchParams" }, outputs: { keyupEvent: "keyupEvent" }, host: { listeners: { "document:click": "onClickOutside($event)" } }, providers: [
|
2532
2304
|
{
|
2533
2305
|
provide: NG_VALUE_ACCESSOR,
|
2534
2306
|
useExisting: forwardRef(() => MultiSelectComponent),
|
2535
|
-
multi: true
|
2536
|
-
}
|
2537
|
-
], usesOnChanges: true, ngImport: i0, template: "<div *ngIf=\"hasPermission()\" class=\"form-group\">\n <label [for]=\"id\" class=\"form-label\" style=\"margin-top: 1rem
|
2307
|
+
multi: true,
|
2308
|
+
},
|
2309
|
+
], usesOnChanges: true, ngImport: i0, template: "<div *ngIf=\"hasPermission()\" class=\"form-group\">\n <label [for]=\"id\" class=\"form-label\" style=\"margin-top: 1rem\">\n {{ label }}\n </label>\n <div class=\"custom-select-container\" tabindex=\"0\">\n <!-- Input com itens selecionados -->\n <div class=\"custom-input\">\n <span class=\"selected-item\" *ngFor=\"let item of selected\">\n {{ item[bindLabel] }}\n <button\n class=\"remove-item-btn\"\n (click)=\"removeSelectedItem(item, $event)\"\n >\n \u00D7\n </button>\n </span>\n <input\n type=\"text\"\n class=\"input-field\"\n [id]=\"id\"\n [placeholder]=\"placeholder\"\n (focus)=\"toggleDropdown()\"\n (keyup)=\"onKeyUp($event)\"\n (input)=\"onInputChange($event)\"\n />\n <!-- \u00CDcone flutuante -->\n <lucide-icon\n [name]=\"isOpen ? 'align-justify' : 'chevron-down'\"\n class=\"dropdown-icon\"\n ></lucide-icon>\n </div>\n\n <!-- Dropdown suspenso -->\n <div *ngIf=\"isOpen\" class=\"dropdown\">\n <div\n *ngFor=\"let item of filteredItems | async\"\n class=\"dropdown-item\"\n [class.selected]=\"isSelected(item)\"\n (click)=\"selectItem(item, $event)\"\n >\n {{ item[bindLabel] }}\n </div>\n <div *ngIf=\"(filteredItems | async)?.length === 0\" class=\"empty-dropdown\">\n Nenhum item dispon\u00EDvel\n </div>\n </div>\n </div>\n</div>\n", styles: ["@charset \"UTF-8\";.custom-select-container{position:relative;display:flex;flex-direction:column;border:1px solid #ccc;border-radius:4px;padding:.5rem;background-color:#fff;color:#333;font-family:var(--font-family)}.custom-select-container .custom-input{display:flex;flex-wrap:wrap;align-items:center;gap:.5rem;width:100%;min-height:20px;cursor:text;background:none;border:none;outline:none;position:relative}.custom-select-container .custom-input .selected-item{display:flex;align-items:center;background-color:#f8f8f8;color:#333;border:1px solid #e0e0e0;border-radius:4px;padding:.15rem .4rem;font-size:.85rem}.custom-select-container .custom-input .selected-item .remove-item-btn{display:flex;align-items:center;justify-content:center;background-color:#c7c7c7;border:none;color:#4b4b4b;font-weight:700;cursor:pointer;font-size:.6rem;line-height:1;border-radius:50%;width:14px;height:14px;margin-left:.3rem;padding:0;position:relative}.custom-select-container .custom-input .selected-item .remove-item-btn span{transition:transform .2s ease,color .2s ease}.custom-select-container .custom-input .selected-item .remove-item-btn:hover{background-color:#8f8a8b;color:#fff}.custom-select-container .custom-input .selected-item .remove-item-btn:hover span{transform:scale(1.2);color:#fff}.custom-select-container .custom-input .selected-item .remove-item-btn:active{background-color:#767072}.custom-select-container .custom-input .input-field{flex:1;border:none;outline:none;font-size:.85rem;padding:.1rem 3rem .1rem .2rem;background:transparent;min-width:80px}.custom-select-container .custom-input .dropdown-icon{position:absolute;right:.1rem;top:50%;transform:translateY(-50%);font-size:1.2rem;color:#888;pointer-events:none}.dropdown{position:absolute;top:100%;left:0;right:0;max-height:200px;overflow-y:auto;background-color:#fff;border:1px solid #ccc;border-radius:4px;z-index:1000}.dropdown::-webkit-scrollbar{width:8px}.dropdown::-webkit-scrollbar-thumb{background-color:#ccc;border-radius:4px}.dropdown::-webkit-scrollbar-thumb:hover{background-color:#aaa}.dropdown::-webkit-scrollbar-track{background-color:#f1f1f1;border-radius:4px}.dropdown .dropdown-item{padding:.5rem;cursor:pointer}.dropdown .dropdown-item:hover{background-color:#f1f1f1}.dropdown .dropdown-item.selected{font-weight:700;background-color:#e9e9e9}.empty-dropdown{padding:1rem;text-align:center;color:#999;font-size:.9rem}@media (max-width: 768px){.custom-input .input-field{padding-right:4rem}.custom-input .dropdown-icon{right:.75rem}}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i4.LucideAngularComponent, selector: "lucide-angular, lucide-icon, i-lucide, span-lucide", inputs: ["class", "name", "img", "color", "absoluteStrokeWidth", "size", "strokeWidth"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.Default, encapsulation: i0.ViewEncapsulation.None }); }
|
2538
2310
|
}
|
2539
2311
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: MultiSelectComponent, decorators: [{
|
2540
2312
|
type: Component,
|
2541
|
-
args: [{ selector:
|
2313
|
+
args: [{ selector: "argenta-custom-multi-select", encapsulation: ViewEncapsulation.None, providers: [
|
2542
2314
|
{
|
2543
2315
|
provide: NG_VALUE_ACCESSOR,
|
2544
2316
|
useExisting: forwardRef(() => MultiSelectComponent),
|
2545
|
-
multi: true
|
2546
|
-
}
|
2547
|
-
], changeDetection: ChangeDetectionStrategy.
|
2548
|
-
}], ctorParameters: function () { return [{ type: AuthService }, { type:
|
2317
|
+
multi: true,
|
2318
|
+
},
|
2319
|
+
], changeDetection: ChangeDetectionStrategy.Default, template: "<div *ngIf=\"hasPermission()\" class=\"form-group\">\n <label [for]=\"id\" class=\"form-label\" style=\"margin-top: 1rem\">\n {{ label }}\n </label>\n <div class=\"custom-select-container\" tabindex=\"0\">\n <!-- Input com itens selecionados -->\n <div class=\"custom-input\">\n <span class=\"selected-item\" *ngFor=\"let item of selected\">\n {{ item[bindLabel] }}\n <button\n class=\"remove-item-btn\"\n (click)=\"removeSelectedItem(item, $event)\"\n >\n \u00D7\n </button>\n </span>\n <input\n type=\"text\"\n class=\"input-field\"\n [id]=\"id\"\n [placeholder]=\"placeholder\"\n (focus)=\"toggleDropdown()\"\n (keyup)=\"onKeyUp($event)\"\n (input)=\"onInputChange($event)\"\n />\n <!-- \u00CDcone flutuante -->\n <lucide-icon\n [name]=\"isOpen ? 'align-justify' : 'chevron-down'\"\n class=\"dropdown-icon\"\n ></lucide-icon>\n </div>\n\n <!-- Dropdown suspenso -->\n <div *ngIf=\"isOpen\" class=\"dropdown\">\n <div\n *ngFor=\"let item of filteredItems | async\"\n class=\"dropdown-item\"\n [class.selected]=\"isSelected(item)\"\n (click)=\"selectItem(item, $event)\"\n >\n {{ item[bindLabel] }}\n </div>\n <div *ngIf=\"(filteredItems | async)?.length === 0\" class=\"empty-dropdown\">\n Nenhum item dispon\u00EDvel\n </div>\n </div>\n </div>\n</div>\n", styles: ["@charset \"UTF-8\";.custom-select-container{position:relative;display:flex;flex-direction:column;border:1px solid #ccc;border-radius:4px;padding:.5rem;background-color:#fff;color:#333;font-family:var(--font-family)}.custom-select-container .custom-input{display:flex;flex-wrap:wrap;align-items:center;gap:.5rem;width:100%;min-height:20px;cursor:text;background:none;border:none;outline:none;position:relative}.custom-select-container .custom-input .selected-item{display:flex;align-items:center;background-color:#f8f8f8;color:#333;border:1px solid #e0e0e0;border-radius:4px;padding:.15rem .4rem;font-size:.85rem}.custom-select-container .custom-input .selected-item .remove-item-btn{display:flex;align-items:center;justify-content:center;background-color:#c7c7c7;border:none;color:#4b4b4b;font-weight:700;cursor:pointer;font-size:.6rem;line-height:1;border-radius:50%;width:14px;height:14px;margin-left:.3rem;padding:0;position:relative}.custom-select-container .custom-input .selected-item .remove-item-btn span{transition:transform .2s ease,color .2s ease}.custom-select-container .custom-input .selected-item .remove-item-btn:hover{background-color:#8f8a8b;color:#fff}.custom-select-container .custom-input .selected-item .remove-item-btn:hover span{transform:scale(1.2);color:#fff}.custom-select-container .custom-input .selected-item .remove-item-btn:active{background-color:#767072}.custom-select-container .custom-input .input-field{flex:1;border:none;outline:none;font-size:.85rem;padding:.1rem 3rem .1rem .2rem;background:transparent;min-width:80px}.custom-select-container .custom-input .dropdown-icon{position:absolute;right:.1rem;top:50%;transform:translateY(-50%);font-size:1.2rem;color:#888;pointer-events:none}.dropdown{position:absolute;top:100%;left:0;right:0;max-height:200px;overflow-y:auto;background-color:#fff;border:1px solid #ccc;border-radius:4px;z-index:1000}.dropdown::-webkit-scrollbar{width:8px}.dropdown::-webkit-scrollbar-thumb{background-color:#ccc;border-radius:4px}.dropdown::-webkit-scrollbar-thumb:hover{background-color:#aaa}.dropdown::-webkit-scrollbar-track{background-color:#f1f1f1;border-radius:4px}.dropdown .dropdown-item{padding:.5rem;cursor:pointer}.dropdown .dropdown-item:hover{background-color:#f1f1f1}.dropdown .dropdown-item.selected{font-weight:700;background-color:#e9e9e9}.empty-dropdown{padding:1rem;text-align:center;color:#999;font-size:.9rem}@media (max-width: 768px){.custom-input .input-field{padding-right:4rem}.custom-input .dropdown-icon{right:.75rem}}\n"] }]
|
2320
|
+
}], ctorParameters: function () { return [{ type: AuthService }, { type: i1$2.HttpClient }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { onClickOutside: [{
|
2321
|
+
type: HostListener,
|
2322
|
+
args: ["document:click", ["$event"]]
|
2323
|
+
}], label: [{
|
2549
2324
|
type: Input
|
2550
2325
|
}], data: [{
|
2551
2326
|
type: Input
|
@@ -2703,7 +2478,7 @@ class SearchCustomerComponent {
|
|
2703
2478
|
this.searchTerm.emit(inputElement.value);
|
2704
2479
|
}
|
2705
2480
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SearchCustomerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
2706
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: SearchCustomerComponent, selector: "argenta-search-customer", inputs: { placeholder: "placeholder", id: "id", disabled: "disabled", readonly: "readonly", autofocus: "autofocus" }, outputs: { searchTerm: "searchTerm" }, ngImport: i0, template: "<div class=\"search-container\">\n <span class=\"search-icon\" [ngClass]=\"'search-icon-green'\">\n <lucide-icon name=\"search\" [size]=\"16\"></lucide-icon>\n </span>\n <input\n [id]=\"id\"\n [placeholder]=\"placeholder\"\n [disabled]=\"disabled\"\n [readonly]=\"readonly\"\n [autofocus]=\"autofocus\"\n (input)=\"onSearch($event)\"\n class=\"search-input custom-input\"\n />\n</div>\n", styles: [".search-container{display:flex;align-items:center;border:1px solid var(--primary-color);border-radius:8px;padding:5px;background-color:#f7f9fc}.search-icon{padding:0 10px;color:#b0b0b0}.search-input{border:none;outline:none;padding:8px;flex:1;background-color:transparent;font-family:var(--font-family);color:#333;font-size:.9rem;height:35px}.search-input::placeholder{color:#b0b0b0}.search-icon-green{color:var(--primary-color)}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type:
|
2481
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: SearchCustomerComponent, selector: "argenta-search-customer", inputs: { placeholder: "placeholder", id: "id", disabled: "disabled", readonly: "readonly", autofocus: "autofocus" }, outputs: { searchTerm: "searchTerm" }, ngImport: i0, template: "<div class=\"search-container\">\n <span class=\"search-icon\" [ngClass]=\"'search-icon-green'\">\n <lucide-icon name=\"search\" [size]=\"16\"></lucide-icon>\n </span>\n <input\n [id]=\"id\"\n [placeholder]=\"placeholder\"\n [disabled]=\"disabled\"\n [readonly]=\"readonly\"\n [autofocus]=\"autofocus\"\n (input)=\"onSearch($event)\"\n class=\"search-input custom-input\"\n />\n</div>\n", styles: [".search-container{display:flex;align-items:center;border:1px solid var(--primary-color);border-radius:8px;padding:5px;background-color:#f7f9fc}.search-icon{padding:0 10px;color:#b0b0b0}.search-input{border:none;outline:none;padding:8px;flex:1;background-color:transparent;font-family:var(--font-family);color:#333;font-size:.9rem;height:35px}.search-input::placeholder{color:#b0b0b0}.search-icon-green{color:var(--primary-color)}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: i4.LucideAngularComponent, selector: "lucide-angular, lucide-icon, i-lucide, span-lucide", inputs: ["class", "name", "img", "color", "absoluteStrokeWidth", "size", "strokeWidth"] }] }); }
|
2707
2482
|
}
|
2708
2483
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SearchCustomerComponent, decorators: [{
|
2709
2484
|
type: Component,
|
@@ -2947,7 +2722,7 @@ class SelectComponent {
|
|
2947
2722
|
<lucide-icon name="chevron-down" [size]="16" color="#5E6366" [strokeWidth]="1.75"></lucide-icon>
|
2948
2723
|
</div>
|
2949
2724
|
</div>
|
2950
|
-
`, isInline: true, styles: ["@charset \"UTF-8\";.form-group{font-family:var(--font-family);font-size:1rem;font-weight:700}.form-check-input{font-family:var(--font-family);color:#333;font-size:.9rem}.form-check-label{width:623px;height:19px;top:1608px;left:133px;gap:0px;opacity:0px;font-family:var(--font-family);font-size:16px;line-height:19.36px;text-align:left}.custom-select{font-family:var(--font-family);color:#333;font-size:1rem;font-weight:400;border:1px solid #ccc;border-radius:4px;padding:.5rem 2rem .5rem .5rem;appearance:none;-webkit-appearance:none;-moz-appearance:none;background-image:none;background-repeat:no-repeat;background-position:right .5rem center}.custom-input{font-family:var(--font-family);color:#333;font-size:1rem;font-weight:400;border:1px solid #ccc;border-radius:4px;padding:.5rem}.form-label{font-family:var(--font-family);color:#333;font-size:1rem;font-weight:700}.label-styles{font-weight:400;font-family:var(--font-family);font-size:16px;line-height:19.36px;text-align:left;margin-top:1rem;margin-bottom:.5rem}.select-container{position:relative;display:inline-block;width:100%}.select-container lucide-icon{position:absolute;right:.75rem;top:50%;transform:translateY(-50%);pointer-events:none;color:#5e6366}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "component", type:
|
2725
|
+
`, isInline: true, styles: ["@charset \"UTF-8\";.form-group{font-family:var(--font-family);font-size:1rem;font-weight:700}.form-check-input{font-family:var(--font-family);color:#333;font-size:.9rem}.form-check-label{width:623px;height:19px;top:1608px;left:133px;gap:0px;opacity:0px;font-family:var(--font-family);font-size:16px;line-height:19.36px;text-align:left}.custom-select{font-family:var(--font-family);color:#333;font-size:1rem;font-weight:400;border:1px solid #ccc;border-radius:4px;padding:.5rem 2rem .5rem .5rem;appearance:none;-webkit-appearance:none;-moz-appearance:none;background-image:none;background-repeat:no-repeat;background-position:right .5rem center}.custom-input{font-family:var(--font-family);color:#333;font-size:1rem;font-weight:400;border:1px solid #ccc;border-radius:4px;padding:.5rem}.form-label{font-family:var(--font-family);color:#333;font-size:1rem;font-weight:700}.label-styles{font-weight:400;font-family:var(--font-family);font-size:16px;line-height:19.36px;text-align:left;margin-top:1rem;margin-bottom:.5rem}.select-container{position:relative;display:inline-block;width:100%}.select-container lucide-icon{position:absolute;right:.75rem;top:50%;transform:translateY(-50%);pointer-events:none;color:#5e6366}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "component", type: i4.LucideAngularComponent, selector: "lucide-angular, lucide-icon, i-lucide, span-lucide", inputs: ["class", "name", "img", "color", "absoluteStrokeWidth", "size", "strokeWidth"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
2951
2726
|
}
|
2952
2727
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SelectComponent, decorators: [{
|
2953
2728
|
type: Component,
|
@@ -3287,7 +3062,7 @@ class DataTableComponent {
|
|
3287
3062
|
this.onButtonClick.emit(); // Emitindo o evento
|
3288
3063
|
}
|
3289
3064
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DataTableComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: AuthService }, { token: RefreshService }], target: i0.ɵɵFactoryTarget.Component }); }
|
3290
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: DataTableComponent, selector: "argenta-list-data-table", inputs: { columns: "columns", hiddenColumns: "hiddenColumns", defaultItemsPerPage: "defaultItemsPerPage", itemsPerPageLabel: "itemsPerPageLabel", showActionColumn: "showActionColumn", actionColumnLabel: "actionColumnLabel", totalItems: "totalItems", fetchDataFunction: "fetchDataFunction", editPermissions: "editPermissions", deletePermissions: "deletePermissions", viewPermissions: "viewPermissions", showPageInfo: "showPageInfo", pageText: "pageText", ofText: "ofText", filterDescription: "filterDescription", buttonLabel: "buttonLabel", pagedData: "pagedData", initialFilterField: "initialFilterField", buttonList: "buttonList" }, outputs: { sortChange: "sortChange", pageChange: "pageChange", itemsPerPageChange: "itemsPerPageChange", onEditTable: "onEditTable", onDeleteTable: "onDeleteTable", onViewTable: "onViewTable", onButtonClick: "onButtonClick", filterFieldChange: "filterFieldChange" }, ngImport: i0, template: "<div class=\"data-table-header\" style=\"margin-top: 2.5rem\">\n <div class=\"left-section\">\n <div class=\"form-group\">\n <label for=\"itemsPerPageSelect\" class=\"items-per-page-label\">{{\n itemsPerPageLabel\n }}</label>\n <select\n id=\"itemsPerPageSelect\"\n class=\"form-control form-control-sm d-inline-block w-auto custom-select\"\n [(ngModel)]=\"defaultItemsPerPage\"\n (ngModelChange)=\"onItemsPerPageChange()\"\n >\n <option *ngFor=\"let option of itemsPerPageOptions\" [value]=\"option\">\n {{ option }}\n </option>\n </select>\n </div>\n </div>\n <div class=\"right-section\">\n <div *ngIf=\"buttonList && buttonList.length > 0\" class=\"ng-button-row\">\n <ng-container *ngFor=\"let buttonTemplate of buttonList\">\n <ng-container\n *ngTemplateOutlet=\"buttonTemplate\"\n class=\"ng-button\"\n ></ng-container>\n </ng-container>\n </div>\n <button\n *ngIf=\"buttonLabel && buttonLabel.length > 0\"\n class=\"custom-button\"\n (click)=\"onNewButtonClick()\"\n >\n <lucide-icon name=\"plus\" [size]=\"28\" [strokeWidth]=\"1.75\"></lucide-icon>\n {{ buttonLabel }}\n </button>\n </div>\n</div>\n\n<div class=\"search-input-container\">\n <argenta-search-input\n id=\"search\"\n label=\"\"\n placeholder=\"Buscar\"\n [(ngModel)]=\"filterDescription\"\n (search)=\"onSearch($event)\"\n ></argenta-search-input>\n</div>\n\n<div class=\"table-responsive\" style=\"margin-top: 1rem\">\n <table class=\"table table-hover\">\n <thead>\n <tr>\n <ng-container *ngFor=\"let column of columns\">\n <th\n *ngIf=\"!isColumnHidden(column.prop)\"\n (click)=\"onSelectSearchField(column.prop)\"\n >\n {{ column.label }}\n <span>\n <i-lucide\n name=\"arrow-up\"\n [size]=\"14\"\n [class.selected]=\"\n column.isSearchSelected && sortDirection === 'asc'\n \"\n ></i-lucide>\n <i-lucide\n name=\"arrow-down\"\n [size]=\"14\"\n [class.selected]=\"\n column.isSearchSelected && sortDirection === 'desc'\n \"\n ></i-lucide>\n </span>\n </th>\n </ng-container>\n <th\n *ngIf=\"showActionColumn\"\n class=\"text-end\"\n style=\"padding-right: 6.3rem\"\n >\n {{ actionColumnLabel }}\n </th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let item of pagedData; let i = index\">\n <ng-container *ngFor=\"let column of columns\">\n <td *ngIf=\"!isColumnHidden(column.prop)\">\n {{ getNestedProperty(item, column.prop) }}\n </td>\n </ng-container>\n <td *ngIf=\"showActionColumn\" class=\"text-end\">\n <div class=\"d-flex justify-content-end\">\n <div\n *ngIf=\"\n hasPermission(editPermissions) &&\n onEditTable.observers.length > 0\n \"\n (click)=\"handleAction('edit', item, i)\"\n class=\"clickable-icon\"\n style=\"margin-right: 1.5rem\"\n >\n <lucide-icon\n name=\"square-pen\"\n [size]=\"20\"\n color=\"#2CA58D\"\n [strokeWidth]=\"1.75\"\n ></lucide-icon>\n </div>\n <div\n *ngIf=\"\n hasPermission(viewPermissions) &&\n onViewTable.observers.length > 0\n \"\n (click)=\"handleAction('view', item, i)\"\n class=\"clickable-icon\"\n style=\"margin-right: 1.5rem\"\n >\n <lucide-icon\n name=\"user-round\"\n [size]=\"20\"\n color=\"#2CA58D\"\n [strokeWidth]=\"1.75\"\n ></lucide-icon>\n </div>\n <div\n *ngIf=\"\n hasPermission(deletePermissions) &&\n onDeleteTable.observers.length > 0\n \"\n (click)=\"handleAction('delete', item, i)\"\n class=\"clickable-icon\"\n style=\"margin-right: 1.5rem\"\n >\n <i-lucide\n name=\"trash-2\"\n [size]=\"20\"\n color=\"#F26E6E\"\n [strokeWidth]=\"1.75\"\n ></i-lucide>\n </div>\n </div>\n </td>\n </tr>\n </tbody>\n </table>\n</div>\n\n<div class=\"text-center pagination-controls\">\n <custom-pagination\n [totalItems]=\"totalItems\"\n [itemsPerPage]=\"defaultItemsPerPage\"\n [currentPage]=\"currentPage\"\n [showPageInfo]=\"showPageInfo\"\n (pageChange)=\"onPageChange($event)\"\n >\n </custom-pagination>\n</div>\n", styles: ["@charset \"UTF-8\";.clickable-icon{cursor:pointer}:host{font-family:var(--font-family)}.data-table-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:-.2rem}.left-section,.right-section{display:flex;align-items:center}.search-input-container{display:flex;justify-content:flex-start}.left-section .form-group{display:flex;align-items:center}.items-per-page-label{font-family:var(--font-family);font-size:14px;color:#666;margin-right:.2rem}.custom-select{font-family:var(--font-family);font-size:14px;color:#666;background:#fff url('data:image/svg+xml;charset=US-ASCII,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 4 5\"><path fill=\"#666\" d=\"M2 0L0 2h4L2 0zM2 5l2-2H0l2 2z\"/></svg>') no-repeat right .75rem center/8px 10px;border:1px solid #ccc;border-radius:.25rem;padding:.375rem 1.75rem .375rem .75rem;appearance:none;-webkit-appearance:none;-moz-appearance:none}.custom-select:focus{border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem #007bff40}.table{font-family:var(--font-family);font-size:var(--table-font-size, 14px);color:var(--table-font-color, #737b7b);border-collapse:separate;border-spacing:0;border-radius:8px;overflow:hidden}.table thead tr{height:60px}.table thead th{background-color:var(--primary-color);color:var(--text-color);font-family:var(--font-family);font-size:14px;font-weight:600;padding:10px;border-bottom:.1rem solid #dcdcdc;text-align:center;line-height:2.5}.table thead th:first-child{text-align:left;padding-left:1.4rem}.table tbody td{font-family:var(--font-family);font-size:14px;color:#737b7b;padding:10px;border-bottom:.1rem solid #dcdcdc;text-align:center}.table tbody td:first-child{text-align:left;padding-left:1.4rem}.table tbody tr:last-child td{border-bottom:.1rem solid #dcdcdc}.table tbody td{border-right:none;border-left:none}.table thead th:first-child{border-top-left-radius:0}.table thead th:last-child{border-top-right-radius:0}.table tbody tr:last-child td:first-child{border-bottom-left-radius:0}.table tbody tr:last-child td:last-child{border-bottom-right-radius:0}.btn-icon{width:24px;height:24px;background-size:cover;display:inline-block;cursor:pointer;margin-right:16px}.pagination-controls{display:flex;justify-content:center;align-items:center;margin-top:1rem}.custom-button{display:flex;align-items:center;padding:.5rem 1rem .5rem .5rem;border-radius:.25rem;transition:background-color .3s,border-color .3s,filter .3s;font-family:var(--font-family);font-size:16px;font-weight:600;height:40px;letter-spacing:.005em;text-align:left;color:#fff;background-color:var(--secondary-color);border:none;cursor:pointer}.custom-button lucide-icon{margin-right:.5rem}.custom-button:hover{box-shadow:0 0 0 .15rem var(--secondary-color)}.custom-button:active{background-color:var(--secondary-color)}.custom-button:focus{outline:none;box-shadow:0 0 0 .15rem var(--secondary-color)}.selected{color:var(--secondary-color);stroke-width:8}.ng-button-row{display:flex;gap:10px;margin-right:10px;margin-left:10px}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i3.LucideAngularComponent, selector: "lucide-angular, lucide-icon, i-lucide, span-lucide", inputs: ["class", "name", "img", "color", "absoluteStrokeWidth", "size", "strokeWidth"] }, { kind: "component", type: CustomPaginationComponent, selector: "custom-pagination", inputs: ["totalItems", "itemsPerPage", "currentPage", "showPageInfo"], outputs: ["pageChange"] }, { kind: "component", type: SearchInputComponent, selector: "argenta-search-input", inputs: ["id", "label", "type", "placeholder", "value", "disabled", "readonly", "autofocus", "maxlength", "minlength", "required", "pattern", "debounceTime"], outputs: ["search", "inputChange", "change", "focus", "blur", "keyup", "keydown", "keypress"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
3065
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: DataTableComponent, selector: "argenta-list-data-table", inputs: { columns: "columns", hiddenColumns: "hiddenColumns", defaultItemsPerPage: "defaultItemsPerPage", itemsPerPageLabel: "itemsPerPageLabel", showActionColumn: "showActionColumn", actionColumnLabel: "actionColumnLabel", totalItems: "totalItems", fetchDataFunction: "fetchDataFunction", editPermissions: "editPermissions", deletePermissions: "deletePermissions", viewPermissions: "viewPermissions", showPageInfo: "showPageInfo", pageText: "pageText", ofText: "ofText", filterDescription: "filterDescription", buttonLabel: "buttonLabel", pagedData: "pagedData", initialFilterField: "initialFilterField", buttonList: "buttonList" }, outputs: { sortChange: "sortChange", pageChange: "pageChange", itemsPerPageChange: "itemsPerPageChange", onEditTable: "onEditTable", onDeleteTable: "onDeleteTable", onViewTable: "onViewTable", onButtonClick: "onButtonClick", filterFieldChange: "filterFieldChange" }, ngImport: i0, template: "<div class=\"data-table-header\" style=\"margin-top: 2.5rem\">\n <div class=\"left-section\">\n <div class=\"form-group\">\n <label for=\"itemsPerPageSelect\" class=\"items-per-page-label\">{{\n itemsPerPageLabel\n }}</label>\n <select\n id=\"itemsPerPageSelect\"\n class=\"form-control form-control-sm d-inline-block w-auto custom-select\"\n [(ngModel)]=\"defaultItemsPerPage\"\n (ngModelChange)=\"onItemsPerPageChange()\"\n >\n <option *ngFor=\"let option of itemsPerPageOptions\" [value]=\"option\">\n {{ option }}\n </option>\n </select>\n </div>\n </div>\n <div class=\"right-section\">\n <div *ngIf=\"buttonList && buttonList.length > 0\" class=\"ng-button-row\">\n <ng-container *ngFor=\"let buttonTemplate of buttonList\">\n <ng-container\n *ngTemplateOutlet=\"buttonTemplate\"\n class=\"ng-button\"\n ></ng-container>\n </ng-container>\n </div>\n <button\n *ngIf=\"buttonLabel && buttonLabel.length > 0\"\n class=\"custom-button\"\n (click)=\"onNewButtonClick()\"\n >\n <lucide-icon name=\"plus\" [size]=\"28\" [strokeWidth]=\"1.75\"></lucide-icon>\n {{ buttonLabel }}\n </button>\n </div>\n</div>\n\n<div class=\"search-input-container\">\n <argenta-search-input\n id=\"search\"\n label=\"\"\n placeholder=\"Buscar\"\n [(ngModel)]=\"filterDescription\"\n (search)=\"onSearch($event)\"\n ></argenta-search-input>\n</div>\n\n<div class=\"table-responsive\" style=\"margin-top: 1rem\">\n <table class=\"table table-hover\">\n <thead>\n <tr>\n <ng-container *ngFor=\"let column of columns\">\n <th\n *ngIf=\"!isColumnHidden(column.prop)\"\n (click)=\"onSelectSearchField(column.prop)\"\n >\n {{ column.label }}\n <span>\n <i-lucide\n name=\"arrow-up\"\n [size]=\"14\"\n [class.selected]=\"\n column.isSearchSelected && sortDirection === 'asc'\n \"\n ></i-lucide>\n <i-lucide\n name=\"arrow-down\"\n [size]=\"14\"\n [class.selected]=\"\n column.isSearchSelected && sortDirection === 'desc'\n \"\n ></i-lucide>\n </span>\n </th>\n </ng-container>\n <th\n *ngIf=\"showActionColumn\"\n class=\"text-end\"\n style=\"padding-right: 6.3rem\"\n >\n {{ actionColumnLabel }}\n </th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let item of pagedData; let i = index\">\n <ng-container *ngFor=\"let column of columns\">\n <td *ngIf=\"!isColumnHidden(column.prop)\">\n {{ getNestedProperty(item, column.prop) }}\n </td>\n </ng-container>\n <td *ngIf=\"showActionColumn\" class=\"text-end\">\n <div class=\"d-flex justify-content-end\">\n <div\n *ngIf=\"\n hasPermission(editPermissions) &&\n onEditTable.observers.length > 0\n \"\n (click)=\"handleAction('edit', item, i)\"\n class=\"clickable-icon\"\n style=\"margin-right: 1.5rem\"\n >\n <lucide-icon\n name=\"square-pen\"\n [size]=\"20\"\n color=\"#2CA58D\"\n [strokeWidth]=\"1.75\"\n ></lucide-icon>\n </div>\n <div\n *ngIf=\"\n hasPermission(viewPermissions) &&\n onViewTable.observers.length > 0\n \"\n (click)=\"handleAction('view', item, i)\"\n class=\"clickable-icon\"\n style=\"margin-right: 1.5rem\"\n >\n <lucide-icon\n name=\"user-round\"\n [size]=\"20\"\n color=\"#2CA58D\"\n [strokeWidth]=\"1.75\"\n ></lucide-icon>\n </div>\n <div\n *ngIf=\"\n hasPermission(deletePermissions) &&\n onDeleteTable.observers.length > 0\n \"\n (click)=\"handleAction('delete', item, i)\"\n class=\"clickable-icon\"\n style=\"margin-right: 1.5rem\"\n >\n <i-lucide\n name=\"trash-2\"\n [size]=\"20\"\n color=\"#F26E6E\"\n [strokeWidth]=\"1.75\"\n ></i-lucide>\n </div>\n </div>\n </td>\n </tr>\n </tbody>\n </table>\n</div>\n\n<div class=\"text-center pagination-controls\">\n <custom-pagination\n [totalItems]=\"totalItems\"\n [itemsPerPage]=\"defaultItemsPerPage\"\n [currentPage]=\"currentPage\"\n [showPageInfo]=\"showPageInfo\"\n (pageChange)=\"onPageChange($event)\"\n >\n </custom-pagination>\n</div>\n", styles: ["@charset \"UTF-8\";.clickable-icon{cursor:pointer}:host{font-family:var(--font-family)}.data-table-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:-.2rem}.left-section,.right-section{display:flex;align-items:center}.search-input-container{display:flex;justify-content:flex-start}.left-section .form-group{display:flex;align-items:center}.items-per-page-label{font-family:var(--font-family);font-size:14px;color:#666;margin-right:.2rem}.custom-select{font-family:var(--font-family);font-size:14px;color:#666;background:#fff url('data:image/svg+xml;charset=US-ASCII,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 4 5\"><path fill=\"#666\" d=\"M2 0L0 2h4L2 0zM2 5l2-2H0l2 2z\"/></svg>') no-repeat right .75rem center/8px 10px;border:1px solid #ccc;border-radius:.25rem;padding:.375rem 1.75rem .375rem .75rem;appearance:none;-webkit-appearance:none;-moz-appearance:none}.custom-select:focus{border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem #007bff40}.table{font-family:var(--font-family);font-size:var(--table-font-size, 14px);color:var(--table-font-color, #737b7b);border-collapse:separate;border-spacing:0;border-radius:8px;overflow:hidden}.table thead tr{height:60px}.table thead th{background-color:var(--primary-color);color:var(--text-color);font-family:var(--font-family);font-size:14px;font-weight:600;padding:10px;border-bottom:.1rem solid #dcdcdc;text-align:center;line-height:2.5}.table thead th:first-child{text-align:left;padding-left:1.4rem}.table tbody td{font-family:var(--font-family);font-size:14px;color:#737b7b;padding:10px;border-bottom:.1rem solid #dcdcdc;text-align:center}.table tbody td:first-child{text-align:left;padding-left:1.4rem}.table tbody tr:last-child td{border-bottom:.1rem solid #dcdcdc}.table tbody td{border-right:none;border-left:none}.table thead th:first-child{border-top-left-radius:0}.table thead th:last-child{border-top-right-radius:0}.table tbody tr:last-child td:first-child{border-bottom-left-radius:0}.table tbody tr:last-child td:last-child{border-bottom-right-radius:0}.btn-icon{width:24px;height:24px;background-size:cover;display:inline-block;cursor:pointer;margin-right:16px}.pagination-controls{display:flex;justify-content:center;align-items:center;margin-top:1rem}.custom-button{display:flex;align-items:center;padding:.5rem 1rem .5rem .5rem;border-radius:.25rem;transition:background-color .3s,border-color .3s,filter .3s;font-family:var(--font-family);font-size:16px;font-weight:600;height:40px;letter-spacing:.005em;text-align:left;color:#fff;background-color:var(--secondary-color);border:none;cursor:pointer}.custom-button lucide-icon{margin-right:.5rem}.custom-button:hover{box-shadow:0 0 0 .15rem var(--secondary-color)}.custom-button:active{background-color:var(--secondary-color)}.custom-button:focus{outline:none;box-shadow:0 0 0 .15rem var(--secondary-color)}.selected{color:var(--secondary-color);stroke-width:8}.ng-button-row{display:flex;gap:10px;margin-right:10px;margin-left:10px}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i4.LucideAngularComponent, selector: "lucide-angular, lucide-icon, i-lucide, span-lucide", inputs: ["class", "name", "img", "color", "absoluteStrokeWidth", "size", "strokeWidth"] }, { kind: "component", type: CustomPaginationComponent, selector: "custom-pagination", inputs: ["totalItems", "itemsPerPage", "currentPage", "showPageInfo"], outputs: ["pageChange"] }, { kind: "component", type: SearchInputComponent, selector: "argenta-search-input", inputs: ["id", "label", "type", "placeholder", "value", "disabled", "readonly", "autofocus", "maxlength", "minlength", "required", "pattern", "debounceTime"], outputs: ["search", "inputChange", "change", "focus", "blur", "keyup", "keydown", "keypress"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
3291
3066
|
}
|
3292
3067
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DataTableComponent, decorators: [{
|
3293
3068
|
type: Component,
|
@@ -3591,10 +3366,888 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
3591
3366
|
type: Output
|
3592
3367
|
}] } });
|
3593
3368
|
|
3369
|
+
class JsonViewerComponent {
|
3370
|
+
constructor() {
|
3371
|
+
this.isRoot = true;
|
3372
|
+
this.allExpanded = true;
|
3373
|
+
this.expandedMap = new Map();
|
3374
|
+
}
|
3375
|
+
toggleAll() {
|
3376
|
+
this.allExpanded = !this.allExpanded;
|
3377
|
+
this.expandedMap.clear();
|
3378
|
+
}
|
3379
|
+
toggleExpand(key) {
|
3380
|
+
const currentState = this.isExpanded(key);
|
3381
|
+
this.expandedMap.set(key, !currentState);
|
3382
|
+
}
|
3383
|
+
isObject(val) {
|
3384
|
+
return val !== null && typeof val === 'object';
|
3385
|
+
}
|
3386
|
+
objectKeys(obj) {
|
3387
|
+
return Object.keys(obj);
|
3388
|
+
}
|
3389
|
+
isExpanded(key) {
|
3390
|
+
return this.expandedMap.has(key) ? this.expandedMap.get(key) : this.allExpanded;
|
3391
|
+
}
|
3392
|
+
copyJson() {
|
3393
|
+
const jsonString = JSON.stringify(this.jsonData, null, 2);
|
3394
|
+
navigator.clipboard.writeText(jsonString).then(() => {
|
3395
|
+
alert('JSON copiado com sucesso!');
|
3396
|
+
}).catch(err => {
|
3397
|
+
console.error('Error copying JSON to clipboard:', err);
|
3398
|
+
});
|
3399
|
+
}
|
3400
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: JsonViewerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
3401
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: JsonViewerComponent, selector: "argenta-json-viewer", inputs: { jsonData: "jsonData", isRoot: "isRoot", copyLabel: "copyLabel", showLabel: "showLabel", hideLabel: "hideLabel" }, ngImport: i0, template: "<div class=\"json-viewer-box\">\n <div class=\"toolbar\">\n <button\n *ngIf=\"isRoot\"\n class=\"action-button copy-button\"\n (click)=\"copyJson()\"\n >\n {{ copyLabel }}\n </button>\n <button\n *ngIf=\"isRoot\"\n class=\"action-button toggle-button\"\n (click)=\"toggleAll()\"\n >\n {{ allExpanded ? \"\u25BC \" + hideLabel : \"\u25BA \" + showLabel }}\n </button>\n </div>\n\n <div class=\"json-content\">\n <div *ngIf=\"isObject(jsonData)\">\n <div class=\"json-pair\" *ngFor=\"let key of objectKeys(jsonData)\">\n <span class=\"key\">\n {{ key }}:\n <button class=\"minimal-toggle-button\" (click)=\"toggleExpand(key)\">\n {{ isExpanded(key) ? \"\u25BC\" : \"\u25BA\" }}\n </button>\n </span>\n\n <div class=\"nested-json\" *ngIf=\"isExpanded(key)\">\n <argenta-json-viewer\n [jsonData]=\"jsonData[key]\"\n [isRoot]=\"false\"\n ></argenta-json-viewer>\n </div>\n <span *ngIf=\"!isExpanded(key) && isObject(jsonData[key])\">[...]</span>\n </div>\n </div>\n <span *ngIf=\"!isObject(jsonData)\">\n {{ jsonData }}\n </span>\n </div>\n</div>\n", styles: [".json-viewer-box{border:1px solid #ccc;padding:10px;border-radius:8px;font-family:Arial,sans-serif;background-color:#f9f9f9}.json-viewer-box .toolbar{display:flex;justify-content:space-between;align-items:center;margin-bottom:10px;padding-bottom:5px;border-bottom:1px solid #ddd}.json-viewer-box .action-button{background-color:#4caf50;color:#fff;border:none;padding:8px 16px;font-size:14px;border-radius:4px;cursor:pointer;transition:background-color .3s ease}.json-viewer-box .action-button:hover{background-color:#45a049}.json-viewer-box .minimal-toggle-button{background:none;border:none;color:#007bff;cursor:pointer;font-size:12px;margin-left:5px;padding:0;line-height:1}.json-viewer-box .minimal-toggle-button:hover{color:#0056b3}.json-viewer-box .json-content{margin-top:10px}.json-viewer-box .json-content .json-pair{margin-bottom:5px}.json-viewer-box .json-content .json-pair .key{font-weight:700;margin-right:5px;display:flex;align-items:center}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: JsonViewerComponent, selector: "argenta-json-viewer", inputs: ["jsonData", "isRoot", "copyLabel", "showLabel", "hideLabel"] }] }); }
|
3402
|
+
}
|
3403
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: JsonViewerComponent, decorators: [{
|
3404
|
+
type: Component,
|
3405
|
+
args: [{ selector: 'argenta-json-viewer', template: "<div class=\"json-viewer-box\">\n <div class=\"toolbar\">\n <button\n *ngIf=\"isRoot\"\n class=\"action-button copy-button\"\n (click)=\"copyJson()\"\n >\n {{ copyLabel }}\n </button>\n <button\n *ngIf=\"isRoot\"\n class=\"action-button toggle-button\"\n (click)=\"toggleAll()\"\n >\n {{ allExpanded ? \"\u25BC \" + hideLabel : \"\u25BA \" + showLabel }}\n </button>\n </div>\n\n <div class=\"json-content\">\n <div *ngIf=\"isObject(jsonData)\">\n <div class=\"json-pair\" *ngFor=\"let key of objectKeys(jsonData)\">\n <span class=\"key\">\n {{ key }}:\n <button class=\"minimal-toggle-button\" (click)=\"toggleExpand(key)\">\n {{ isExpanded(key) ? \"\u25BC\" : \"\u25BA\" }}\n </button>\n </span>\n\n <div class=\"nested-json\" *ngIf=\"isExpanded(key)\">\n <argenta-json-viewer\n [jsonData]=\"jsonData[key]\"\n [isRoot]=\"false\"\n ></argenta-json-viewer>\n </div>\n <span *ngIf=\"!isExpanded(key) && isObject(jsonData[key])\">[...]</span>\n </div>\n </div>\n <span *ngIf=\"!isObject(jsonData)\">\n {{ jsonData }}\n </span>\n </div>\n</div>\n", styles: [".json-viewer-box{border:1px solid #ccc;padding:10px;border-radius:8px;font-family:Arial,sans-serif;background-color:#f9f9f9}.json-viewer-box .toolbar{display:flex;justify-content:space-between;align-items:center;margin-bottom:10px;padding-bottom:5px;border-bottom:1px solid #ddd}.json-viewer-box .action-button{background-color:#4caf50;color:#fff;border:none;padding:8px 16px;font-size:14px;border-radius:4px;cursor:pointer;transition:background-color .3s ease}.json-viewer-box .action-button:hover{background-color:#45a049}.json-viewer-box .minimal-toggle-button{background:none;border:none;color:#007bff;cursor:pointer;font-size:12px;margin-left:5px;padding:0;line-height:1}.json-viewer-box .minimal-toggle-button:hover{color:#0056b3}.json-viewer-box .json-content{margin-top:10px}.json-viewer-box .json-content .json-pair{margin-bottom:5px}.json-viewer-box .json-content .json-pair .key{font-weight:700;margin-right:5px;display:flex;align-items:center}\n"] }]
|
3406
|
+
}], propDecorators: { jsonData: [{
|
3407
|
+
type: Input
|
3408
|
+
}], isRoot: [{
|
3409
|
+
type: Input
|
3410
|
+
}], copyLabel: [{
|
3411
|
+
type: Input
|
3412
|
+
}], showLabel: [{
|
3413
|
+
type: Input
|
3414
|
+
}], hideLabel: [{
|
3415
|
+
type: Input
|
3416
|
+
}] } });
|
3417
|
+
|
3418
|
+
class ModalComponent {
|
3419
|
+
constructor(activeModal) {
|
3420
|
+
this.activeModal = activeModal;
|
3421
|
+
this.onButtonClick = new EventEmitter(); // Novo evento
|
3422
|
+
}
|
3423
|
+
ngOnInit() {
|
3424
|
+
const componentRef = this.dynamicComponent.createComponent(this.component);
|
3425
|
+
const instance = componentRef.instance;
|
3426
|
+
if (this.componentInputs) {
|
3427
|
+
Object.keys(this.componentInputs).forEach(inputName => {
|
3428
|
+
instance[inputName] = this.componentInputs[inputName];
|
3429
|
+
});
|
3430
|
+
}
|
3431
|
+
}
|
3432
|
+
closeModal() {
|
3433
|
+
this.activeModal.close();
|
3434
|
+
}
|
3435
|
+
buttonClicked() {
|
3436
|
+
this.onButtonClick.emit(); // Emitindo o evento
|
3437
|
+
}
|
3438
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ModalComponent, deps: [{ token: i1$1.NgbActiveModal }], target: i0.ɵɵFactoryTarget.Component }); }
|
3439
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: ModalComponent, selector: "argenta-modal", inputs: { title: "title", component: "component", componentInputs: "componentInputs", closeButtonLabel: "closeButtonLabel", buttonLabel: "buttonLabel" }, outputs: { onButtonClick: "onButtonClick" }, viewQueries: [{ propertyName: "dynamicComponent", first: true, predicate: ["dynamicComponent"], descendants: true, read: ViewContainerRef, static: true }], ngImport: i0, template: "<div class=\"modal-header custom-modal-header\">\n <h4 class=\"modal-title\">{{ title }}</h4>\n <p class=\"float-right close-modal\" (click)=\"closeModal()\">X</p>\n</div>\n<div class=\"modal-body\">\n <ng-container #dynamicComponent></ng-container>\n</div>\n<div class=\"modal-footer\">\n <button class=\"btn btn-secondary\" (click)=\"closeModal()\">\n {{ closeButtonLabel }}\n </button>\n <button *ngIf=\"buttonLabel\" class=\"btn btn-custom\" (click)=\"buttonClicked()\">\n {{ buttonLabel }}\n </button>\n</div>\n", styles: [".modal-content{border-radius:15px;overflow:hidden}.custom-modal-header{background-color:var(--primary-color);color:var(--text-color);border-bottom:none;font-family:var(--font-family);display:flex;justify-content:space-between;align-items:center;padding:1rem}.modal-title{color:var(--text-color);font-size:20px}.close-modal{margin:0;cursor:pointer;font-size:1.5rem;color:var(--text-color)}.close-modal:hover{color:#ccc}.modal-footer{border-top:none}.btn-custom{background-color:var(--primary-color);color:var(--text-color);border-bottom:none}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] }); }
|
3440
|
+
}
|
3441
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ModalComponent, decorators: [{
|
3442
|
+
type: Component,
|
3443
|
+
args: [{ selector: 'argenta-modal', template: "<div class=\"modal-header custom-modal-header\">\n <h4 class=\"modal-title\">{{ title }}</h4>\n <p class=\"float-right close-modal\" (click)=\"closeModal()\">X</p>\n</div>\n<div class=\"modal-body\">\n <ng-container #dynamicComponent></ng-container>\n</div>\n<div class=\"modal-footer\">\n <button class=\"btn btn-secondary\" (click)=\"closeModal()\">\n {{ closeButtonLabel }}\n </button>\n <button *ngIf=\"buttonLabel\" class=\"btn btn-custom\" (click)=\"buttonClicked()\">\n {{ buttonLabel }}\n </button>\n</div>\n", styles: [".modal-content{border-radius:15px;overflow:hidden}.custom-modal-header{background-color:var(--primary-color);color:var(--text-color);border-bottom:none;font-family:var(--font-family);display:flex;justify-content:space-between;align-items:center;padding:1rem}.modal-title{color:var(--text-color);font-size:20px}.close-modal{margin:0;cursor:pointer;font-size:1.5rem;color:var(--text-color)}.close-modal:hover{color:#ccc}.modal-footer{border-top:none}.btn-custom{background-color:var(--primary-color);color:var(--text-color);border-bottom:none}\n"] }]
|
3444
|
+
}], ctorParameters: function () { return [{ type: i1$1.NgbActiveModal }]; }, propDecorators: { title: [{
|
3445
|
+
type: Input
|
3446
|
+
}], component: [{
|
3447
|
+
type: Input
|
3448
|
+
}], componentInputs: [{
|
3449
|
+
type: Input
|
3450
|
+
}], closeButtonLabel: [{
|
3451
|
+
type: Input
|
3452
|
+
}], buttonLabel: [{
|
3453
|
+
type: Input
|
3454
|
+
}], onButtonClick: [{
|
3455
|
+
type: Output
|
3456
|
+
}], dynamicComponent: [{
|
3457
|
+
type: ViewChild,
|
3458
|
+
args: ['dynamicComponent', { read: ViewContainerRef, static: true }]
|
3459
|
+
}] } });
|
3460
|
+
|
3461
|
+
class DynamicModalComponent {
|
3462
|
+
constructor() {
|
3463
|
+
this.modalTitle = "Modal Title";
|
3464
|
+
this.modalSizeClass = "";
|
3465
|
+
this.modalId = "dynamicModal"; // ID único para cada modal
|
3466
|
+
}
|
3467
|
+
openModal() {
|
3468
|
+
const modalElement = document.getElementById(this.modalId);
|
3469
|
+
if (modalElement) {
|
3470
|
+
modalElement.classList.add("show");
|
3471
|
+
modalElement.setAttribute("aria-hidden", "false");
|
3472
|
+
modalElement.style.display = "block";
|
3473
|
+
document.body.classList.add("modal-open");
|
3474
|
+
// Adiciona o backdrop manualmente se não existir
|
3475
|
+
if (!document.querySelector(`.modal-backdrop[data-modal-id="${this.modalId}"]`)) {
|
3476
|
+
const backdrop = document.createElement("div");
|
3477
|
+
backdrop.className = "modal-backdrop fade show";
|
3478
|
+
backdrop.setAttribute("data-modal-id", this.modalId);
|
3479
|
+
document.body.appendChild(backdrop);
|
3480
|
+
}
|
3481
|
+
}
|
3482
|
+
}
|
3483
|
+
closeModal() {
|
3484
|
+
const modalElement = document.getElementById(this.modalId);
|
3485
|
+
if (modalElement) {
|
3486
|
+
modalElement.classList.remove("show");
|
3487
|
+
modalElement.setAttribute("aria-hidden", "true");
|
3488
|
+
modalElement.style.display = "none";
|
3489
|
+
document.body.classList.remove("modal-open");
|
3490
|
+
document
|
3491
|
+
.querySelector(`.modal-backdrop[data-modal-id="${this.modalId}"]`)
|
3492
|
+
?.remove();
|
3493
|
+
}
|
3494
|
+
}
|
3495
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DynamicModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
3496
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: DynamicModalComponent, selector: "argenta-dynamic-modal", inputs: { modalTitle: "modalTitle", modalSizeClass: "modalSizeClass", modalId: "modalId" }, ngImport: i0, template: "<div\n class=\"modal fade\"\n [id]=\"modalId\"\n tabindex=\"-1\"\n [attr.aria-labelledby]=\"modalId + 'Label'\"\n aria-hidden=\"true\"\n>\n <div class=\"modal-dialog\" [ngClass]=\"modalSizeClass\">\n <div class=\"modal-content\">\n <div class=\"modal-header custom-header\">\n <h5 class=\"modal-title custom-modal-title\" [id]=\"modalId + 'Label'\">\n {{ modalTitle }}\n </h5>\n <button\n type=\"button\"\n class=\"custom-close-button\"\n (click)=\"closeModal()\"\n aria-label=\"Close\"\n >\n ×\n </button>\n </div>\n <div class=\"modal-body custom-body\">\n <ng-content select=\"[modal-body]\"></ng-content>\n </div>\n <div class=\"modal-footer custom-footer\">\n <ng-content select=\"[modal-footer]\"></ng-content>\n </div>\n </div>\n </div>\n</div>\n", styles: [".custom-header{background-color:var(--primary-color)!important;color:var(--text-color)!important;font-size:1.25rem!important;font-family:var(--font-family)!important;padding:1rem;position:relative}.custom-header .custom-close-button{position:absolute;right:1rem;background:none;border:none;font-size:2.5rem;color:var(--text-color);cursor:pointer}.custom-header .custom-close-button:hover{color:var(--danger-color)}.custom-modal-title{color:var(--text-color)!important;font-size:1.8rem!important;font-family:var(--font-family)!important}.custom-body{background-color:#fff;padding:1rem}.custom-footer{background-color:#fff;padding:.75rem;display:flex;justify-content:flex-end;gap:.5rem}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] }); }
|
3497
|
+
}
|
3498
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DynamicModalComponent, decorators: [{
|
3499
|
+
type: Component,
|
3500
|
+
args: [{ selector: "argenta-dynamic-modal", template: "<div\n class=\"modal fade\"\n [id]=\"modalId\"\n tabindex=\"-1\"\n [attr.aria-labelledby]=\"modalId + 'Label'\"\n aria-hidden=\"true\"\n>\n <div class=\"modal-dialog\" [ngClass]=\"modalSizeClass\">\n <div class=\"modal-content\">\n <div class=\"modal-header custom-header\">\n <h5 class=\"modal-title custom-modal-title\" [id]=\"modalId + 'Label'\">\n {{ modalTitle }}\n </h5>\n <button\n type=\"button\"\n class=\"custom-close-button\"\n (click)=\"closeModal()\"\n aria-label=\"Close\"\n >\n ×\n </button>\n </div>\n <div class=\"modal-body custom-body\">\n <ng-content select=\"[modal-body]\"></ng-content>\n </div>\n <div class=\"modal-footer custom-footer\">\n <ng-content select=\"[modal-footer]\"></ng-content>\n </div>\n </div>\n </div>\n</div>\n", styles: [".custom-header{background-color:var(--primary-color)!important;color:var(--text-color)!important;font-size:1.25rem!important;font-family:var(--font-family)!important;padding:1rem;position:relative}.custom-header .custom-close-button{position:absolute;right:1rem;background:none;border:none;font-size:2.5rem;color:var(--text-color);cursor:pointer}.custom-header .custom-close-button:hover{color:var(--danger-color)}.custom-modal-title{color:var(--text-color)!important;font-size:1.8rem!important;font-family:var(--font-family)!important}.custom-body{background-color:#fff;padding:1rem}.custom-footer{background-color:#fff;padding:.75rem;display:flex;justify-content:flex-end;gap:.5rem}\n"] }]
|
3501
|
+
}], propDecorators: { modalTitle: [{
|
3502
|
+
type: Input
|
3503
|
+
}], modalSizeClass: [{
|
3504
|
+
type: Input
|
3505
|
+
}], modalId: [{
|
3506
|
+
type: Input
|
3507
|
+
}] } });
|
3508
|
+
|
3509
|
+
class DynamicTableComponent {
|
3510
|
+
constructor() {
|
3511
|
+
this.itemsPerPageOptions = [10, 20, 50];
|
3512
|
+
this.showPageInfo = true;
|
3513
|
+
this.currentPage = 1;
|
3514
|
+
this.itemsPerPage = 10;
|
3515
|
+
}
|
3516
|
+
get totalItems() {
|
3517
|
+
return this.config.totalItems ?? this.config.data.length;
|
3518
|
+
}
|
3519
|
+
get paginatedData() {
|
3520
|
+
if (!this.config.pagination) {
|
3521
|
+
// Retorna todos os dados se a paginação estiver desativada
|
3522
|
+
return this.config.data;
|
3523
|
+
}
|
3524
|
+
const itemsPerPage = this.config.itemsPerPage || this.itemsPerPage;
|
3525
|
+
const startIndex = (this.currentPage - 1) * itemsPerPage;
|
3526
|
+
return this.config.data.slice(startIndex, startIndex + itemsPerPage);
|
3527
|
+
}
|
3528
|
+
ngOnInit() {
|
3529
|
+
if (!this.config || !this.config.columns || !this.config.data) {
|
3530
|
+
throw new Error("DynamicTableComponent: Configuração inválida.");
|
3531
|
+
}
|
3532
|
+
// Define valores padrão se não especificados
|
3533
|
+
this.config.showHeader = this.config.showHeader ?? true; // Exibe o cabeçalho por padrão
|
3534
|
+
this.config.pagination = this.config.pagination ?? true; // Ativa paginação por padrão
|
3535
|
+
this.itemsPerPage = this.config.itemsPerPage || 10;
|
3536
|
+
}
|
3537
|
+
onPageChange(newPage) {
|
3538
|
+
this.currentPage = newPage;
|
3539
|
+
}
|
3540
|
+
onItemsPerPageChange(event) {
|
3541
|
+
const target = event.target;
|
3542
|
+
this.itemsPerPage = +target.value;
|
3543
|
+
this.currentPage = 1; // Reinicia a paginação ao alterar os itens por página
|
3544
|
+
}
|
3545
|
+
// Getter para garantir que totalItems nunca seja undefined
|
3546
|
+
get safeTotalItems() {
|
3547
|
+
return this.totalItems || 0;
|
3548
|
+
}
|
3549
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DynamicTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
3550
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: DynamicTableComponent, selector: "argenta-dynamic-table", inputs: { config: "config", itemsPerPageOptions: "itemsPerPageOptions", showPageInfo: "showPageInfo" }, ngImport: i0, template: "<table class=\"table\" [ngClass]=\"{ nested: config.isNested }\">\n <thead *ngIf=\"config.showHeader\">\n <tr>\n <th *ngFor=\"let column of config.columns\">{{ column.header }}</th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let row of paginatedData\">\n <td *ngFor=\"let column of config.columns\">\n <ng-container [ngSwitch]=\"column.type\">\n <span *ngSwitchCase=\"'text'\">{{ row[column.key] }}</span>\n <ng-container *ngSwitchCase=\"'template'\">\n <ng-container\n *ngTemplateOutlet=\"\n column.template || null;\n context: { $implicit: row }\n \"\n ></ng-container>\n </ng-container>\n </ng-container>\n </td>\n </tr>\n </tbody>\n</table>\n\n<div\n class=\"text-center pagination-controls\"\n [ngClass]=\"{ nested: config.isNested }\"\n *ngIf=\"config.pagination\"\n>\n <custom-pagination\n [totalItems]=\"safeTotalItems\"\n [itemsPerPage]=\"itemsPerPage\"\n [currentPage]=\"currentPage\"\n [showPageInfo]=\"showPageInfo\"\n (pageChange)=\"onPageChange($event)\"\n >\n </custom-pagination>\n</div>\n", styles: ["@charset \"UTF-8\";.table{width:100%;border-collapse:collapse;border-spacing:0}.table{width:100%;border-collapse:separate;border-spacing:0;overflow:hidden}.table thead th{background-color:var(--primary-color);color:var(--text-color);font-family:var(--font-family);font-size:14px;font-weight:600;padding:10px;border-bottom:.1rem solid #dcdcdc;text-align:center;line-height:2.5}.table thead th:first-child{border-top-left-radius:10px}.table thead th:last-child{border-top-right-radius:10px}.table.nested thead th{font-size:.7rem;padding:7px;line-height:.8}.table tbody td{font-family:var(--font-family);font-size:14px;color:#737b7b;padding:10px;border-bottom:.1rem solid #dcdcdc;text-align:center}.table tbody td:first-child{text-align:left;padding-left:1.4rem}.table.nested tbody td:first-child{padding-left:1rem}.table tbody tr:hover{background-color:#f5f5f5!important;transition:background-color .3s ease}.table.nested tbody tr:hover{background-color:#f0f0f0!important}.pagination-controls{display:flex;justify-content:center;align-items:center;margin-top:1rem}.pagination-controls.nested{font-size:.7rem;transform:scale(.7);margin-top:.5rem}.data-table-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:1rem}.left-section{display:flex;align-items:center}.items-per-page-label{font-family:var(--font-family);font-size:14px;color:#666;margin-right:.5rem}.custom-select{font-family:var(--font-family);font-size:14px;padding:.375rem 1.75rem .375rem .75rem;border:1px solid #ccc;border-radius:.25rem;appearance:none;background:#fff url('data:image/svg+xml;charset=US-ASCII,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 4 5\"><path fill=\"#666\" d=\"M2 0L0 2h4L2 0zM2 5l2-2H0l2 2z\"/></svg>') no-repeat right .75rem center/8px 10px}.custom-select:focus{border-color:#80bdff;outline:none;box-shadow:0 0 0 .2rem #007bff40}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "component", type: CustomPaginationComponent, selector: "custom-pagination", inputs: ["totalItems", "itemsPerPage", "currentPage", "showPageInfo"], outputs: ["pageChange"] }] }); }
|
3551
|
+
}
|
3552
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DynamicTableComponent, decorators: [{
|
3553
|
+
type: Component,
|
3554
|
+
args: [{ selector: "argenta-dynamic-table", template: "<table class=\"table\" [ngClass]=\"{ nested: config.isNested }\">\n <thead *ngIf=\"config.showHeader\">\n <tr>\n <th *ngFor=\"let column of config.columns\">{{ column.header }}</th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let row of paginatedData\">\n <td *ngFor=\"let column of config.columns\">\n <ng-container [ngSwitch]=\"column.type\">\n <span *ngSwitchCase=\"'text'\">{{ row[column.key] }}</span>\n <ng-container *ngSwitchCase=\"'template'\">\n <ng-container\n *ngTemplateOutlet=\"\n column.template || null;\n context: { $implicit: row }\n \"\n ></ng-container>\n </ng-container>\n </ng-container>\n </td>\n </tr>\n </tbody>\n</table>\n\n<div\n class=\"text-center pagination-controls\"\n [ngClass]=\"{ nested: config.isNested }\"\n *ngIf=\"config.pagination\"\n>\n <custom-pagination\n [totalItems]=\"safeTotalItems\"\n [itemsPerPage]=\"itemsPerPage\"\n [currentPage]=\"currentPage\"\n [showPageInfo]=\"showPageInfo\"\n (pageChange)=\"onPageChange($event)\"\n >\n </custom-pagination>\n</div>\n", styles: ["@charset \"UTF-8\";.table{width:100%;border-collapse:collapse;border-spacing:0}.table{width:100%;border-collapse:separate;border-spacing:0;overflow:hidden}.table thead th{background-color:var(--primary-color);color:var(--text-color);font-family:var(--font-family);font-size:14px;font-weight:600;padding:10px;border-bottom:.1rem solid #dcdcdc;text-align:center;line-height:2.5}.table thead th:first-child{border-top-left-radius:10px}.table thead th:last-child{border-top-right-radius:10px}.table.nested thead th{font-size:.7rem;padding:7px;line-height:.8}.table tbody td{font-family:var(--font-family);font-size:14px;color:#737b7b;padding:10px;border-bottom:.1rem solid #dcdcdc;text-align:center}.table tbody td:first-child{text-align:left;padding-left:1.4rem}.table.nested tbody td:first-child{padding-left:1rem}.table tbody tr:hover{background-color:#f5f5f5!important;transition:background-color .3s ease}.table.nested tbody tr:hover{background-color:#f0f0f0!important}.pagination-controls{display:flex;justify-content:center;align-items:center;margin-top:1rem}.pagination-controls.nested{font-size:.7rem;transform:scale(.7);margin-top:.5rem}.data-table-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:1rem}.left-section{display:flex;align-items:center}.items-per-page-label{font-family:var(--font-family);font-size:14px;color:#666;margin-right:.5rem}.custom-select{font-family:var(--font-family);font-size:14px;padding:.375rem 1.75rem .375rem .75rem;border:1px solid #ccc;border-radius:.25rem;appearance:none;background:#fff url('data:image/svg+xml;charset=US-ASCII,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 4 5\"><path fill=\"#666\" d=\"M2 0L0 2h4L2 0zM2 5l2-2H0l2 2z\"/></svg>') no-repeat right .75rem center/8px 10px}.custom-select:focus{border-color:#80bdff;outline:none;box-shadow:0 0 0 .2rem #007bff40}\n"] }]
|
3555
|
+
}], ctorParameters: function () { return []; }, propDecorators: { config: [{
|
3556
|
+
type: Input
|
3557
|
+
}], itemsPerPageOptions: [{
|
3558
|
+
type: Input
|
3559
|
+
}], showPageInfo: [{
|
3560
|
+
type: Input
|
3561
|
+
}] } });
|
3562
|
+
|
3563
|
+
function formatToBrazilianNumber(value) {
|
3564
|
+
return value.toLocaleString("pt-BR", {
|
3565
|
+
minimumFractionDigits: 2,
|
3566
|
+
maximumFractionDigits: 2,
|
3567
|
+
});
|
3568
|
+
}
|
3569
|
+
|
3570
|
+
class ArgentaPdfDataHandlerComponent {
|
3571
|
+
constructor() {
|
3572
|
+
this.data = [];
|
3573
|
+
}
|
3574
|
+
isNumericColumn(key) {
|
3575
|
+
// Se 'numericColumns' estiver definido no pdfConfig, use-o como referência
|
3576
|
+
return this.config?.numericColumns?.includes(key) ?? false;
|
3577
|
+
}
|
3578
|
+
processData(data) {
|
3579
|
+
if (!data || !this.config?.tableKeys?.length) {
|
3580
|
+
console.warn("Dados ou chaves de tabela ausentes!");
|
3581
|
+
return [];
|
3582
|
+
}
|
3583
|
+
// Identificar colunas numéricas
|
3584
|
+
const numericColumns = this.config.numericColumns || [];
|
3585
|
+
return data.map((item) => {
|
3586
|
+
const processedItem = {};
|
3587
|
+
this.config.tableKeys.forEach((key) => {
|
3588
|
+
if (numericColumns.includes(key)) {
|
3589
|
+
const value = item[key];
|
3590
|
+
if (typeof value === "string") {
|
3591
|
+
// Converte o valor no formato brasileiro para número
|
3592
|
+
processedItem[key] = parseFloat(value.replace(".", "").replace(",", "."));
|
3593
|
+
}
|
3594
|
+
else if (typeof value === "number") {
|
3595
|
+
processedItem[key] = value;
|
3596
|
+
}
|
3597
|
+
else {
|
3598
|
+
processedItem[key] = 0; // Valor padrão para entradas inválidas
|
3599
|
+
}
|
3600
|
+
}
|
3601
|
+
else {
|
3602
|
+
// Mantém o valor original para colunas não numéricas
|
3603
|
+
processedItem[key] = item[key];
|
3604
|
+
}
|
3605
|
+
});
|
3606
|
+
return processedItem;
|
3607
|
+
});
|
3608
|
+
}
|
3609
|
+
exportToPdf() {
|
3610
|
+
if (!this.config || !this.data.length) {
|
3611
|
+
console.warn("Configuração ou dados ausentes para exportação de PDF!");
|
3612
|
+
return;
|
3613
|
+
}
|
3614
|
+
const doc = new jsPDF();
|
3615
|
+
// Configuração do título
|
3616
|
+
const titleStyle = this.styles?.titleStyle || {};
|
3617
|
+
doc.setFont(titleStyle.fontFamily || "helvetica", "normal");
|
3618
|
+
doc.setFontSize(titleStyle.fontSize || 14);
|
3619
|
+
doc.setTextColor(titleStyle.fontColor || "#000");
|
3620
|
+
doc.text(this.config.pdfTitle || "Relatório", titleStyle.align === "center" ? 105 : 10, 10, { align: titleStyle.align || "left" });
|
3621
|
+
// Processar os dados
|
3622
|
+
const processedData = this.processData(this.data);
|
3623
|
+
// Calcular totais por linha
|
3624
|
+
const calculatedData = processedData.map((row) => {
|
3625
|
+
const newRow = { ...row };
|
3626
|
+
this.config.rowCalculations?.forEach((calc) => {
|
3627
|
+
const result = calc.formula(row);
|
3628
|
+
newRow[calc.label] = isNaN(result)
|
3629
|
+
? "-"
|
3630
|
+
: formatToBrazilianNumber(result); // Formata os totais por linha
|
3631
|
+
});
|
3632
|
+
return newRow;
|
3633
|
+
});
|
3634
|
+
// Calcular o total geral
|
3635
|
+
let totalRow = {};
|
3636
|
+
if (this.config.totalizer?.include) {
|
3637
|
+
this.config.totalizer.columns.forEach((column) => {
|
3638
|
+
const values = calculatedData
|
3639
|
+
.map((item) => {
|
3640
|
+
const value = item[column.field];
|
3641
|
+
if (typeof value === "string") {
|
3642
|
+
return parseFloat(value.replace(".", "").replace(",", "."));
|
3643
|
+
}
|
3644
|
+
return typeof value === "number" ? value : 0; // Valores inválidos tratados como 0
|
3645
|
+
})
|
3646
|
+
.filter((value) => !isNaN(value)); // Filtra valores válidos
|
3647
|
+
const total = column.formula(values);
|
3648
|
+
totalRow[column.field] = formatToBrazilianNumber(total); // Formata o total geral
|
3649
|
+
});
|
3650
|
+
}
|
3651
|
+
// Preparar os dados para a tabela
|
3652
|
+
const tableHeaders = [...this.config.tableHeaders];
|
3653
|
+
const tableKeys = [...this.config.tableKeys];
|
3654
|
+
const tableData = calculatedData.map((item) => tableKeys.map((key) => {
|
3655
|
+
const value = item[key];
|
3656
|
+
if (typeof value === "number") {
|
3657
|
+
return formatToBrazilianNumber(value); // Formata números
|
3658
|
+
}
|
3659
|
+
return value || "-"; // Retorna o valor original
|
3660
|
+
}));
|
3661
|
+
// Adicionar a linha totalizadora ao final da tabela
|
3662
|
+
if (this.config.totalizer?.include) {
|
3663
|
+
const totalizerRow = tableKeys.map((key, index) => {
|
3664
|
+
if (index === 0) {
|
3665
|
+
return this.config.totalizer?.columns[0].label || "-"; // Adiciona o label na primeira coluna
|
3666
|
+
}
|
3667
|
+
return totalRow[key] || "-";
|
3668
|
+
});
|
3669
|
+
tableData.push(totalizerRow);
|
3670
|
+
}
|
3671
|
+
// Configurar estilos e gerar a tabela
|
3672
|
+
const tableStyle = this.styles?.tableStyle || {};
|
3673
|
+
const headerStyle = this.styles?.headerStyle || {};
|
3674
|
+
const dataStyle = this.styles?.dataStyle || {};
|
3675
|
+
doc.autoTable({
|
3676
|
+
head: [tableHeaders],
|
3677
|
+
body: tableData,
|
3678
|
+
startY: 20,
|
3679
|
+
headStyles: {
|
3680
|
+
fontSize: headerStyle.fontSize || 12,
|
3681
|
+
textColor: headerStyle.fontColor || "#fff",
|
3682
|
+
fillColor: headerStyle.backgroundColor || "#007bff",
|
3683
|
+
},
|
3684
|
+
bodyStyles: {
|
3685
|
+
fontSize: dataStyle.fontSize || 10,
|
3686
|
+
textColor: dataStyle.fontColor || "#555",
|
3687
|
+
},
|
3688
|
+
styles: {
|
3689
|
+
fontSize: tableStyle.fontSize || 10,
|
3690
|
+
textColor: tableStyle.fontColor || "#000",
|
3691
|
+
fillColor: tableStyle.backgroundColor || "#fff",
|
3692
|
+
},
|
3693
|
+
theme: "grid",
|
3694
|
+
});
|
3695
|
+
// Salvar o PDF
|
3696
|
+
doc.save(this.config.fileName || "relatorio.pdf");
|
3697
|
+
}
|
3698
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ArgentaPdfDataHandlerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
3699
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: ArgentaPdfDataHandlerComponent, selector: "argenta-pdf-data-handler", inputs: { config: "config", data: "data", styles: "styles" }, ngImport: i0, template: "<div class=\"pdf-data-handler-container\">\n <button class=\"pdf-button\" (click)=\"exportToPdf()\">\n {{ config.buttonLabel || \"Export PDF\" }}\n </button>\n</div>\n", styles: [".pdf-data-handler-container{display:flex;justify-content:center;align-items:center;padding:1rem}.pdf-data-handler-container .pdf-button{font-family:var(--font-family, Arial, sans-serif);font-size:16px;font-weight:600;padding:.5rem 1rem;border-radius:.25rem;color:var(--text-color, #fff);background-color:var(--primary-color);border:none;cursor:pointer;transition:background-color .3s,box-shadow .3s}.pdf-data-handler-container .pdf-button:hover{background-color:var(--secondary-color)}.pdf-data-handler-container .pdf-button:active{transform:scale(.98)}\n"] }); }
|
3700
|
+
}
|
3701
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ArgentaPdfDataHandlerComponent, decorators: [{
|
3702
|
+
type: Component,
|
3703
|
+
args: [{ selector: "argenta-pdf-data-handler", template: "<div class=\"pdf-data-handler-container\">\n <button class=\"pdf-button\" (click)=\"exportToPdf()\">\n {{ config.buttonLabel || \"Export PDF\" }}\n </button>\n</div>\n", styles: [".pdf-data-handler-container{display:flex;justify-content:center;align-items:center;padding:1rem}.pdf-data-handler-container .pdf-button{font-family:var(--font-family, Arial, sans-serif);font-size:16px;font-weight:600;padding:.5rem 1rem;border-radius:.25rem;color:var(--text-color, #fff);background-color:var(--primary-color);border:none;cursor:pointer;transition:background-color .3s,box-shadow .3s}.pdf-data-handler-container .pdf-button:hover{background-color:var(--secondary-color)}.pdf-data-handler-container .pdf-button:active{transform:scale(.98)}\n"] }]
|
3704
|
+
}], propDecorators: { config: [{
|
3705
|
+
type: Input
|
3706
|
+
}], data: [{
|
3707
|
+
type: Input
|
3708
|
+
}], styles: [{
|
3709
|
+
type: Input
|
3710
|
+
}] } });
|
3711
|
+
|
3712
|
+
class ArgentaPdfDownloadComponent {
|
3713
|
+
constructor(http) {
|
3714
|
+
this.http = http;
|
3715
|
+
this.apiEndpoint = ""; // Endpoint do back-end ou URL pública
|
3716
|
+
this.buttonText = "Baixar PDF"; // Texto do botão
|
3717
|
+
this.loadingText = "Baixando..."; // Texto durante o carregamento
|
3718
|
+
this.isLoading = false;
|
3719
|
+
}
|
3720
|
+
downloadPdf() {
|
3721
|
+
if (!this.apiEndpoint) {
|
3722
|
+
console.error("O endpoint da API não foi fornecido.");
|
3723
|
+
return;
|
3724
|
+
}
|
3725
|
+
// Verifica se a URL é pública (HTTPS ou HTTP)
|
3726
|
+
if (this.apiEndpoint.startsWith("http://") ||
|
3727
|
+
this.apiEndpoint.startsWith("https://")) {
|
3728
|
+
window.open(this.apiEndpoint, "_blank"); // Abre a URL diretamente
|
3729
|
+
return;
|
3730
|
+
}
|
3731
|
+
this.isLoading = true;
|
3732
|
+
// Requisição para obter o arquivo como blob
|
3733
|
+
this.http.get(this.apiEndpoint, { responseType: "blob" }).subscribe({
|
3734
|
+
next: (blob) => {
|
3735
|
+
const fileURL = window.URL.createObjectURL(blob);
|
3736
|
+
window.open(fileURL, "_blank"); // Abre o arquivo como blob
|
3737
|
+
this.isLoading = false;
|
3738
|
+
},
|
3739
|
+
error: (err) => {
|
3740
|
+
console.error("Erro ao baixar o PDF:", err);
|
3741
|
+
this.isLoading = false;
|
3742
|
+
},
|
3743
|
+
});
|
3744
|
+
}
|
3745
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ArgentaPdfDownloadComponent, deps: [{ token: i1$2.HttpClient }], target: i0.ɵɵFactoryTarget.Component }); }
|
3746
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: ArgentaPdfDownloadComponent, selector: "argenta-pdf-download", inputs: { apiEndpoint: "apiEndpoint", buttonText: "buttonText", loadingText: "loadingText" }, ngImport: i0, template: "<button (click)=\"downloadPdf()\" [disabled]=\"isLoading\">\n <span *ngIf=\"!isLoading\">{{ buttonText }}</span>\n <span *ngIf=\"isLoading\">{{ loadingText }}</span>\n</button>\n", styles: ["button{font-family:var(--font-family);font-size:16px;font-weight:600;padding:.5rem 1rem;border-radius:.25rem;color:var(--text-color);background-color:var(--primary-color);border:none;cursor:pointer;transition:background-color .3s ease-in-out,box-shadow .3s ease-in-out,transform .2s ease;box-shadow:0 4px 6px #0000001a}button:hover{background-color:var(--secondary-color);box-shadow:0 6px 8px #00000026}button:active{transform:scale(.96);box-shadow:0 2px 4px #0000001a}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] }); }
|
3747
|
+
}
|
3748
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ArgentaPdfDownloadComponent, decorators: [{
|
3749
|
+
type: Component,
|
3750
|
+
args: [{ selector: "argenta-pdf-download", template: "<button (click)=\"downloadPdf()\" [disabled]=\"isLoading\">\n <span *ngIf=\"!isLoading\">{{ buttonText }}</span>\n <span *ngIf=\"isLoading\">{{ loadingText }}</span>\n</button>\n", styles: ["button{font-family:var(--font-family);font-size:16px;font-weight:600;padding:.5rem 1rem;border-radius:.25rem;color:var(--text-color);background-color:var(--primary-color);border:none;cursor:pointer;transition:background-color .3s ease-in-out,box-shadow .3s ease-in-out,transform .2s ease;box-shadow:0 4px 6px #0000001a}button:hover{background-color:var(--secondary-color);box-shadow:0 6px 8px #00000026}button:active{transform:scale(.96);box-shadow:0 2px 4px #0000001a}\n"] }]
|
3751
|
+
}], ctorParameters: function () { return [{ type: i1$2.HttpClient }]; }, propDecorators: { apiEndpoint: [{
|
3752
|
+
type: Input
|
3753
|
+
}], buttonText: [{
|
3754
|
+
type: Input
|
3755
|
+
}], loadingText: [{
|
3756
|
+
type: Input
|
3757
|
+
}] } });
|
3758
|
+
|
3759
|
+
class DragDropListComponent {
|
3760
|
+
constructor() {
|
3761
|
+
this.nonSelectedList = [];
|
3762
|
+
this.nonSelectedButtonClick = new EventEmitter();
|
3763
|
+
this.nonSelectedInputChanged = new EventEmitter();
|
3764
|
+
this.selectedList = [];
|
3765
|
+
this.selectedButtonClick = new EventEmitter();
|
3766
|
+
this.selectedInputChanged = new EventEmitter();
|
3767
|
+
this.nonSelectedListInputSubject = new Subject();
|
3768
|
+
this.selectedListInputSubject = new Subject();
|
3769
|
+
this.ButtonClasses = ButtonClasses; // Adicione a enumeração ao componente
|
3770
|
+
this.draggedItem = null;
|
3771
|
+
this.nonSelectedListInputSubject.pipe(debounceTime(2000)).subscribe((value) => {
|
3772
|
+
this.nonSelectedInputChanged.emit(value);
|
3773
|
+
});
|
3774
|
+
this.selectedListInputSubject.pipe(debounceTime(2000)).subscribe((value) => {
|
3775
|
+
this.selectedInputChanged.emit(value);
|
3776
|
+
});
|
3777
|
+
}
|
3778
|
+
onDragStart(item) {
|
3779
|
+
this.draggedItem = item;
|
3780
|
+
}
|
3781
|
+
onDragOver(event) {
|
3782
|
+
event.preventDefault();
|
3783
|
+
}
|
3784
|
+
onDrop(list, event) {
|
3785
|
+
event.preventDefault();
|
3786
|
+
if (this.draggedItem) {
|
3787
|
+
const index = list.indexOf(this.draggedItem);
|
3788
|
+
if (index === -1) {
|
3789
|
+
this.removeItem(this.draggedItem);
|
3790
|
+
list.push(this.draggedItem);
|
3791
|
+
}
|
3792
|
+
this.draggedItem = null;
|
3793
|
+
}
|
3794
|
+
}
|
3795
|
+
removeItem(item) {
|
3796
|
+
[this.nonSelectedList, this.selectedList].forEach((list) => {
|
3797
|
+
const index = list.indexOf(item);
|
3798
|
+
if (index !== -1) {
|
3799
|
+
list.splice(index, 1);
|
3800
|
+
}
|
3801
|
+
});
|
3802
|
+
}
|
3803
|
+
nonSelectedListInputChange(event) {
|
3804
|
+
this.nonSelectedListInputSubject.next(event.target.value);
|
3805
|
+
}
|
3806
|
+
selectedListInputChange(event) {
|
3807
|
+
this.selectedListInputSubject.next(event.target.value);
|
3808
|
+
}
|
3809
|
+
selButtonClick() {
|
3810
|
+
this.selectedButtonClick.emit();
|
3811
|
+
}
|
3812
|
+
nonSelButtonClick() {
|
3813
|
+
this.nonSelectedButtonClick.emit();
|
3814
|
+
}
|
3815
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DragDropListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
3816
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: DragDropListComponent, selector: "argenta-drag-drop-list", inputs: { nonSelectedTitle: "nonSelectedTitle", nonSelectedList: "nonSelectedList", nonSelectedButtonLabel: "nonSelectedButtonLabel", selectedTitle: "selectedTitle", selectedList: "selectedList", selectedButtonLabel: "selectedButtonLabel" }, outputs: { nonSelectedButtonClick: "nonSelectedButtonClick", nonSelectedInputChanged: "nonSelectedInputChanged", selectedButtonClick: "selectedButtonClick", selectedInputChanged: "selectedInputChanged" }, ngImport: i0, template: "<!-- Cont\u00EAiner externo para dar a apar\u00EAncia de grupo -->\n<div class=\"group-container\">\n <div class=\"container\">\n <!-- Lista 1 com input -->\n <div\n class=\"list\"\n (dragover)=\"onDragOver($event)\"\n (drop)=\"onDrop(nonSelectedList, $event)\"\n >\n <div class=\"row\">\n <h6 class=\"col-md-8\">{{ nonSelectedTitle }}</h6>\n <div *ngIf=\"nonSelectedButtonLabel\" class=\"col-md-4 align-end\">\n <argenta-custom-button\n label=\"{{ nonSelectedButtonLabel }}\"\n (onButtonClick)=\"nonSelButtonClick()\"\n class=\"align-end\"\n [btnClass]=\"ButtonClasses.Primary\"\n >\n </argenta-custom-button>\n </div>\n </div>\n <input\n type=\"text\"\n class=\"list-input\"\n (input)=\"nonSelectedListInputChange($event)\"\n />\n <div\n *ngFor=\"let item of nonSelectedList\"\n class=\"item-card\"\n draggable=\"true\"\n (dragstart)=\"onDragStart(item)\"\n >\n {{ item.descricao }}\n </div>\n </div>\n\n <!-- Lista 2 com input -->\n <div\n class=\"list\"\n (dragover)=\"onDragOver($event)\"\n (drop)=\"onDrop(selectedList, $event)\"\n >\n <div class=\"row\">\n <h6 class=\"col-md-8\">{{ selectedTitle }}</h6>\n <div *ngIf=\"selectedButtonLabel\" class=\"col-md-4 align-end\">\n <argenta-custom-button\n label=\"{{ selectedButtonLabel }}\"\n (onButtonClick)=\"selButtonClick()\"\n class=\"align-end\"\n [btnClass]=\"ButtonClasses.Primary\"\n >\n </argenta-custom-button>\n </div>\n </div>\n <input\n type=\"text\"\n class=\"list-input\"\n (input)=\"selectedListInputChange($event)\"\n />\n <div\n *ngFor=\"let item of selectedList\"\n class=\"item-card\"\n draggable=\"true\"\n (dragstart)=\"onDragStart(item)\"\n >\n {{ item.descricao }}\n </div>\n </div>\n </div>\n</div>\n", styles: ["@charset \"UTF-8\";.group-container{display:flex;justify-content:center;padding:20px;background-color:#fff;border-radius:12px;box-shadow:0 4px 8px #0000001a;width:80%;margin:auto}.container{display:flex;gap:20px;width:100%}.list{flex:1;padding:10px;background-color:#f0f0f0;border-radius:8px;display:flex;flex-direction:column;align-items:flex-start;gap:10px}.list-input{width:100%;height:40px;margin-bottom:15px;border-radius:4px;border:1px solid #ccc;outline:none;font-size:1rem;resize:none}.item-card{width:100%;padding:15px;background-color:#fff;border-radius:8px;box-shadow:0 2px 5px #0003;cursor:move;display:flex;align-items:center;justify-content:center;text-align:center;font-family:var(--font-family);font-weight:500;font-size:1.1rem;color:#333}.row{display:flex;justify-content:space-between;align-items:center;width:100%;max-height:50px;height:50px}.align-end{display:flex;justify-content:flex-end}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: ButtonComponent, selector: "argenta-custom-button", inputs: ["type", "label", "btnClass", "fontSize", "disabled", "autofocus", "form", "formaction", "formenctype", "formmethod", "formnovalidate", "formtarget", "name", "value", "permissions"], outputs: ["onButtonClick"] }] }); }
|
3817
|
+
}
|
3818
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DragDropListComponent, decorators: [{
|
3819
|
+
type: Component,
|
3820
|
+
args: [{ selector: "argenta-drag-drop-list", template: "<!-- Cont\u00EAiner externo para dar a apar\u00EAncia de grupo -->\n<div class=\"group-container\">\n <div class=\"container\">\n <!-- Lista 1 com input -->\n <div\n class=\"list\"\n (dragover)=\"onDragOver($event)\"\n (drop)=\"onDrop(nonSelectedList, $event)\"\n >\n <div class=\"row\">\n <h6 class=\"col-md-8\">{{ nonSelectedTitle }}</h6>\n <div *ngIf=\"nonSelectedButtonLabel\" class=\"col-md-4 align-end\">\n <argenta-custom-button\n label=\"{{ nonSelectedButtonLabel }}\"\n (onButtonClick)=\"nonSelButtonClick()\"\n class=\"align-end\"\n [btnClass]=\"ButtonClasses.Primary\"\n >\n </argenta-custom-button>\n </div>\n </div>\n <input\n type=\"text\"\n class=\"list-input\"\n (input)=\"nonSelectedListInputChange($event)\"\n />\n <div\n *ngFor=\"let item of nonSelectedList\"\n class=\"item-card\"\n draggable=\"true\"\n (dragstart)=\"onDragStart(item)\"\n >\n {{ item.descricao }}\n </div>\n </div>\n\n <!-- Lista 2 com input -->\n <div\n class=\"list\"\n (dragover)=\"onDragOver($event)\"\n (drop)=\"onDrop(selectedList, $event)\"\n >\n <div class=\"row\">\n <h6 class=\"col-md-8\">{{ selectedTitle }}</h6>\n <div *ngIf=\"selectedButtonLabel\" class=\"col-md-4 align-end\">\n <argenta-custom-button\n label=\"{{ selectedButtonLabel }}\"\n (onButtonClick)=\"selButtonClick()\"\n class=\"align-end\"\n [btnClass]=\"ButtonClasses.Primary\"\n >\n </argenta-custom-button>\n </div>\n </div>\n <input\n type=\"text\"\n class=\"list-input\"\n (input)=\"selectedListInputChange($event)\"\n />\n <div\n *ngFor=\"let item of selectedList\"\n class=\"item-card\"\n draggable=\"true\"\n (dragstart)=\"onDragStart(item)\"\n >\n {{ item.descricao }}\n </div>\n </div>\n </div>\n</div>\n", styles: ["@charset \"UTF-8\";.group-container{display:flex;justify-content:center;padding:20px;background-color:#fff;border-radius:12px;box-shadow:0 4px 8px #0000001a;width:80%;margin:auto}.container{display:flex;gap:20px;width:100%}.list{flex:1;padding:10px;background-color:#f0f0f0;border-radius:8px;display:flex;flex-direction:column;align-items:flex-start;gap:10px}.list-input{width:100%;height:40px;margin-bottom:15px;border-radius:4px;border:1px solid #ccc;outline:none;font-size:1rem;resize:none}.item-card{width:100%;padding:15px;background-color:#fff;border-radius:8px;box-shadow:0 2px 5px #0003;cursor:move;display:flex;align-items:center;justify-content:center;text-align:center;font-family:var(--font-family);font-weight:500;font-size:1.1rem;color:#333}.row{display:flex;justify-content:space-between;align-items:center;width:100%;max-height:50px;height:50px}.align-end{display:flex;justify-content:flex-end}\n"] }]
|
3821
|
+
}], ctorParameters: function () { return []; }, propDecorators: { nonSelectedTitle: [{
|
3822
|
+
type: Input
|
3823
|
+
}], nonSelectedList: [{
|
3824
|
+
type: Input
|
3825
|
+
}], nonSelectedButtonLabel: [{
|
3826
|
+
type: Input
|
3827
|
+
}], nonSelectedButtonClick: [{
|
3828
|
+
type: Output
|
3829
|
+
}], nonSelectedInputChanged: [{
|
3830
|
+
type: Output
|
3831
|
+
}], selectedTitle: [{
|
3832
|
+
type: Input
|
3833
|
+
}], selectedList: [{
|
3834
|
+
type: Input
|
3835
|
+
}], selectedButtonLabel: [{
|
3836
|
+
type: Input
|
3837
|
+
}], selectedButtonClick: [{
|
3838
|
+
type: Output
|
3839
|
+
}], selectedInputChanged: [{
|
3840
|
+
type: Output
|
3841
|
+
}] } });
|
3842
|
+
|
3843
|
+
class DataExcelExporterComponent {
|
3844
|
+
constructor() {
|
3845
|
+
this.data = [];
|
3846
|
+
}
|
3847
|
+
exportToExcel() {
|
3848
|
+
if (!this.config || (!this.data.length && !this.config.multipleSheets)) {
|
3849
|
+
console.warn("Nenhuma configuração ou dados fornecidos.");
|
3850
|
+
return;
|
3851
|
+
}
|
3852
|
+
const workbook = XLSX.utils.book_new();
|
3853
|
+
// Verifica se múltiplas planilhas estão configuradas
|
3854
|
+
if (this.config.multipleSheets) {
|
3855
|
+
this.config.multipleSheets.forEach((sheetConfig) => {
|
3856
|
+
const worksheet = XLSX.utils.aoa_to_sheet([]);
|
3857
|
+
// Adiciona o título, se houver
|
3858
|
+
let startRow = 0;
|
3859
|
+
if (sheetConfig.title) {
|
3860
|
+
XLSX.utils.sheet_add_aoa(worksheet, [[sheetConfig.title]], {
|
3861
|
+
origin: "A1",
|
3862
|
+
});
|
3863
|
+
// Define larguras personalizadas do título
|
3864
|
+
if (sheetConfig.titleWidths) {
|
3865
|
+
worksheet["!cols"] = sheetConfig.titleWidths.map((width) => ({
|
3866
|
+
wch: width,
|
3867
|
+
}));
|
3868
|
+
}
|
3869
|
+
// Mescla o título
|
3870
|
+
if (sheetConfig.tableHeaders) {
|
3871
|
+
worksheet["!merges"] = worksheet["!merges"] || [];
|
3872
|
+
worksheet["!merges"].push({
|
3873
|
+
s: { r: 0, c: 0 },
|
3874
|
+
e: { r: 0, c: sheetConfig.tableHeaders.length - 1 },
|
3875
|
+
});
|
3876
|
+
}
|
3877
|
+
startRow = 1;
|
3878
|
+
}
|
3879
|
+
// Adiciona cabeçalhos
|
3880
|
+
if (sheetConfig.tableHeaders) {
|
3881
|
+
XLSX.utils.sheet_add_aoa(worksheet, [sheetConfig.tableHeaders], {
|
3882
|
+
origin: `A${startRow + 1}`,
|
3883
|
+
});
|
3884
|
+
}
|
3885
|
+
// Adiciona dados
|
3886
|
+
if (sheetConfig.data) {
|
3887
|
+
XLSX.utils.sheet_add_json(worksheet, sheetConfig.data, {
|
3888
|
+
origin: `A${startRow + 2}`,
|
3889
|
+
skipHeader: true,
|
3890
|
+
});
|
3891
|
+
}
|
3892
|
+
// Define larguras das colunas
|
3893
|
+
if (sheetConfig.columnWidths) {
|
3894
|
+
worksheet["!cols"] = sheetConfig.columnWidths.map((width) => ({
|
3895
|
+
wch: width,
|
3896
|
+
}));
|
3897
|
+
}
|
3898
|
+
// Adiciona a planilha ao workbook
|
3899
|
+
XLSX.utils.book_append_sheet(workbook, worksheet, sheetConfig.sheetName);
|
3900
|
+
});
|
3901
|
+
}
|
3902
|
+
else {
|
3903
|
+
// Caso não haja múltiplas planilhas, processa a planilha única
|
3904
|
+
const worksheet = XLSX.utils.aoa_to_sheet([]);
|
3905
|
+
// Adiciona título, se houver
|
3906
|
+
let startRow = 0;
|
3907
|
+
if (this.config.title) {
|
3908
|
+
XLSX.utils.sheet_add_aoa(worksheet, [[this.config.title]], {
|
3909
|
+
origin: "A1",
|
3910
|
+
});
|
3911
|
+
// Define larguras do título
|
3912
|
+
if (this.config.titleWidths) {
|
3913
|
+
worksheet["!cols"] = this.config.titleWidths.map((width) => ({
|
3914
|
+
wch: width,
|
3915
|
+
}));
|
3916
|
+
}
|
3917
|
+
// Mescla o título
|
3918
|
+
if (this.config.tableHeaders) {
|
3919
|
+
worksheet["!merges"] = worksheet["!merges"] || [];
|
3920
|
+
worksheet["!merges"].push({
|
3921
|
+
s: { r: 0, c: 0 },
|
3922
|
+
e: { r: 0, c: this.config.tableHeaders.length - 1 },
|
3923
|
+
});
|
3924
|
+
}
|
3925
|
+
startRow = 1;
|
3926
|
+
}
|
3927
|
+
// Adiciona cabeçalhos
|
3928
|
+
if (this.config.tableHeaders) {
|
3929
|
+
XLSX.utils.sheet_add_aoa(worksheet, [this.config.tableHeaders], {
|
3930
|
+
origin: `A${startRow + 1}`,
|
3931
|
+
});
|
3932
|
+
}
|
3933
|
+
// Adiciona dados
|
3934
|
+
XLSX.utils.sheet_add_json(worksheet, this.data, {
|
3935
|
+
origin: `A${startRow + 2}`,
|
3936
|
+
skipHeader: true,
|
3937
|
+
});
|
3938
|
+
// Define larguras das colunas
|
3939
|
+
if (this.config.columnWidths) {
|
3940
|
+
worksheet["!cols"] = this.config.columnWidths.map((width) => ({
|
3941
|
+
wch: width,
|
3942
|
+
}));
|
3943
|
+
}
|
3944
|
+
// Adiciona a planilha ao workbook
|
3945
|
+
XLSX.utils.book_append_sheet(workbook, worksheet, this.config.sheetName);
|
3946
|
+
}
|
3947
|
+
// Salva o arquivo Excel
|
3948
|
+
XLSX.writeFile(workbook, this.config.fileName);
|
3949
|
+
}
|
3950
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DataExcelExporterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
3951
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: DataExcelExporterComponent, selector: "argenta-excel-exporter", inputs: { config: "config", data: "data" }, ngImport: i0, template: `
|
3952
|
+
<button (click)="exportToExcel()">{{ config?.buttonLabel }}</button>
|
3953
|
+
`, isInline: true, styles: ["button{background-color:var(--primary-color);color:var(--text-color);font-family:var(--font-family);padding:10px 20px;border:none;cursor:pointer}button:hover{background-color:var(--secondary-color)}\n"] }); }
|
3954
|
+
}
|
3955
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DataExcelExporterComponent, decorators: [{
|
3956
|
+
type: Component,
|
3957
|
+
args: [{ selector: "argenta-excel-exporter", template: `
|
3958
|
+
<button (click)="exportToExcel()">{{ config?.buttonLabel }}</button>
|
3959
|
+
`, styles: ["button{background-color:var(--primary-color);color:var(--text-color);font-family:var(--font-family);padding:10px 20px;border:none;cursor:pointer}button:hover{background-color:var(--secondary-color)}\n"] }]
|
3960
|
+
}], propDecorators: { config: [{
|
3961
|
+
type: Input
|
3962
|
+
}], data: [{
|
3963
|
+
type: Input
|
3964
|
+
}] } });
|
3965
|
+
|
3966
|
+
class DataExcelImporterComponent {
|
3967
|
+
constructor() {
|
3968
|
+
this.excelData = new EventEmitter(); // Evento para enviar dados processados
|
3969
|
+
// Configurações padrão
|
3970
|
+
this.config = {
|
3971
|
+
acceptedFileTypes: [".xlsx", ".xls", ".csv"],
|
3972
|
+
onImport: (data) => this.defaultImportHandler(data),
|
3973
|
+
excludeRows: [],
|
3974
|
+
excludeColumns: [],
|
3975
|
+
hasHeader: true,
|
3976
|
+
headerRowIndex: 1,
|
3977
|
+
titleRowIndex: 1,
|
3978
|
+
};
|
3979
|
+
// Controle do modal e inputs de configuração
|
3980
|
+
this.userConfig = { ...this.config };
|
3981
|
+
this.excludeRowsInput = ""; // Para capturar linhas a excluir
|
3982
|
+
this.excludeColumnsInput = ""; // Para capturar colunas a excluir
|
3983
|
+
this.showConfigModal = false;
|
3984
|
+
this.buttonLabel = "Importar Dados";
|
3985
|
+
}
|
3986
|
+
// Abre o modal de configurações
|
3987
|
+
openModal() {
|
3988
|
+
this.showConfigModal = true;
|
3989
|
+
}
|
3990
|
+
// Fecha o modal de configurações
|
3991
|
+
closeModal() {
|
3992
|
+
this.showConfigModal = false;
|
3993
|
+
}
|
3994
|
+
// Salva as configurações ajustadas no modal
|
3995
|
+
saveConfig() {
|
3996
|
+
this.config = {
|
3997
|
+
...this.userConfig,
|
3998
|
+
titleRowIndex: (this.userConfig.titleRowIndex ?? 1) - 1,
|
3999
|
+
headerRowIndex: (this.userConfig.headerRowIndex ?? 2) - 1,
|
4000
|
+
excludeRows: this.excludeRowsInput
|
4001
|
+
.split(",")
|
4002
|
+
.map((row) => parseInt(row.trim(), 10) - 1),
|
4003
|
+
excludeColumns: this.excludeColumnsInput
|
4004
|
+
.split(",")
|
4005
|
+
.map((col) => this.columnLetterToIndex(col.trim())), // Converte letras para índices
|
4006
|
+
};
|
4007
|
+
this.closeModal();
|
4008
|
+
}
|
4009
|
+
// Valida que as linhas informadas sejam pelo menos 1
|
4010
|
+
validateRowInput(field) {
|
4011
|
+
if (field === "headerRow" && this.userConfig.headerRowIndex < 1) {
|
4012
|
+
this.userConfig.headerRowIndex = 1;
|
4013
|
+
}
|
4014
|
+
if (field === "titleRow" && this.userConfig.titleRowIndex < 1) {
|
4015
|
+
this.userConfig.titleRowIndex = 1;
|
4016
|
+
}
|
4017
|
+
}
|
4018
|
+
// Processa o arquivo selecionado
|
4019
|
+
handleFileInput(event) {
|
4020
|
+
const file = event.target.files[0];
|
4021
|
+
if (file) {
|
4022
|
+
const fileType = file.name.split(".").pop()?.toLowerCase();
|
4023
|
+
if (fileType === "csv") {
|
4024
|
+
this.processCSVFile(file); // Processa o CSV de forma isolada
|
4025
|
+
}
|
4026
|
+
else {
|
4027
|
+
this.processExcelFile(file); // Mantém o fluxo atual para Excel
|
4028
|
+
}
|
4029
|
+
event.target.value = ""; // Reseta o input para permitir reimportação
|
4030
|
+
}
|
4031
|
+
}
|
4032
|
+
processExcelFile(file) {
|
4033
|
+
const reader = new FileReader();
|
4034
|
+
reader.onload = (e) => {
|
4035
|
+
const data = new Uint8Array(e.target.result);
|
4036
|
+
const workbook = XLSX.read(data, { type: "array" });
|
4037
|
+
const sheetName = workbook.SheetNames[0];
|
4038
|
+
const worksheet = workbook.Sheets[sheetName];
|
4039
|
+
const titleRowIndex = this.config.titleRowIndex ?? 0;
|
4040
|
+
const headerRowIndex = this.config.headerRowIndex ?? titleRowIndex + 1;
|
4041
|
+
if (worksheet["!ref"]) {
|
4042
|
+
worksheet["!ref"] = this.adjustRange(worksheet["!ref"], headerRowIndex + 1);
|
4043
|
+
}
|
4044
|
+
else {
|
4045
|
+
console.error("Intervalo da planilha ('!ref') não encontrado.");
|
4046
|
+
return;
|
4047
|
+
}
|
4048
|
+
const jsonData = XLSX.utils.sheet_to_json(worksheet, {
|
4049
|
+
header: 1,
|
4050
|
+
defval: "",
|
4051
|
+
blankrows: false,
|
4052
|
+
});
|
4053
|
+
this.processData(jsonData);
|
4054
|
+
};
|
4055
|
+
reader.readAsArrayBuffer(file); // Lê o Excel como array buffer
|
4056
|
+
}
|
4057
|
+
processCSVFile(file) {
|
4058
|
+
if (this.userConfig.hasHeader) {
|
4059
|
+
if (this.config?.headerRowIndex !== undefined) {
|
4060
|
+
this.config.headerRowIndex =
|
4061
|
+
this.config.headerRowIndex === 0 ? 1 : this.config.headerRowIndex + 1;
|
4062
|
+
}
|
4063
|
+
const sum = (this.config.excludeRows ?? []).reduce((acc, value) => acc + value, 0) +
|
4064
|
+
1;
|
4065
|
+
this.config.excludeRows = [sum];
|
4066
|
+
}
|
4067
|
+
const reader = new FileReader();
|
4068
|
+
reader.onload = (e) => {
|
4069
|
+
const csvData = e.target.result;
|
4070
|
+
// Converte CSV em JSON usando XLSX
|
4071
|
+
const workbook = XLSX.read(csvData, { type: "string" });
|
4072
|
+
const sheetName = workbook.SheetNames[0];
|
4073
|
+
const worksheet = workbook.Sheets[sheetName];
|
4074
|
+
const jsonData = XLSX.utils.sheet_to_json(worksheet, {
|
4075
|
+
header: 1,
|
4076
|
+
defval: "",
|
4077
|
+
blankrows: false,
|
4078
|
+
});
|
4079
|
+
this.processData(jsonData);
|
4080
|
+
};
|
4081
|
+
reader.readAsText(file); // Lê o CSV como texto
|
4082
|
+
}
|
4083
|
+
processData(jsonData) {
|
4084
|
+
const titleRowIndex = this.config.titleRowIndex ?? 0;
|
4085
|
+
const headerRowIndex = this.config.headerRowIndex ?? titleRowIndex + 1;
|
4086
|
+
const headers = jsonData[0];
|
4087
|
+
if (!headers) {
|
4088
|
+
console.error("Cabeçalhos não encontrados. Verifique o headerRowIndex.");
|
4089
|
+
return;
|
4090
|
+
}
|
4091
|
+
const normalizedHeaders = headers.map((header, index) => this.normalizeHeader(header || `col_${index}`));
|
4092
|
+
const dataRows = jsonData.slice(1); // Remove a linha de cabeçalho
|
4093
|
+
// Filtra as linhas baseando-se no índice informado pelo usuário (1-based)
|
4094
|
+
const filteredRows = dataRows.filter((_, index) => !this.config.excludeRows?.includes(index + headerRowIndex + 1));
|
4095
|
+
const formattedData = filteredRows.map((row) => {
|
4096
|
+
const record = {};
|
4097
|
+
normalizedHeaders.forEach((header, index) => {
|
4098
|
+
record[header] = row[index] ?? "";
|
4099
|
+
});
|
4100
|
+
return record;
|
4101
|
+
});
|
4102
|
+
const finalData = this.filterColumns(formattedData);
|
4103
|
+
this.config.onImport(finalData); // Chama o callback com os dados processados
|
4104
|
+
this.excelData.emit(finalData); // Emite os dados processados para o cliente
|
4105
|
+
}
|
4106
|
+
// Ajusta o intervalo da planilha com base na linha do cabeçalho
|
4107
|
+
adjustRange(range, startRow) {
|
4108
|
+
const [start, end] = range.split(":");
|
4109
|
+
const startCol = start.replace(/[0-9]/g, "");
|
4110
|
+
const endCol = end.replace(/[0-9]/g, "");
|
4111
|
+
const endRow = end.replace(/[A-Za-z]/g, "");
|
4112
|
+
return `${startCol}${startRow}:${endCol}${endRow}`;
|
4113
|
+
}
|
4114
|
+
// Normaliza os cabeçalhos removendo acentos e espaços
|
4115
|
+
normalizeHeader(header) {
|
4116
|
+
return header
|
4117
|
+
.normalize("NFD")
|
4118
|
+
.replace(/[\u0300-\u036f]/g, "")
|
4119
|
+
.replace(/\s+/g, "_")
|
4120
|
+
.toLowerCase();
|
4121
|
+
}
|
4122
|
+
// Filtra as colunas configuradas para exclusão
|
4123
|
+
filterColumns(data) {
|
4124
|
+
const { excludeColumns } = this.config;
|
4125
|
+
return data.map((row) => {
|
4126
|
+
const filteredRow = {};
|
4127
|
+
Object.keys(row).forEach((key, index) => {
|
4128
|
+
if (!excludeColumns?.includes(index)) {
|
4129
|
+
filteredRow[key] = row[key];
|
4130
|
+
}
|
4131
|
+
});
|
4132
|
+
return filteredRow;
|
4133
|
+
});
|
4134
|
+
}
|
4135
|
+
// Converte letra da coluna para índice (A -> 0, B -> 1, etc.)
|
4136
|
+
columnLetterToIndex(letter) {
|
4137
|
+
let index = 0;
|
4138
|
+
for (let i = 0; i < letter.length; i++) {
|
4139
|
+
index = index * 26 + (letter.charCodeAt(i) - "A".charCodeAt(0) + 1);
|
4140
|
+
}
|
4141
|
+
return index - 1;
|
4142
|
+
}
|
4143
|
+
// Callback padrão para manipular dados importados
|
4144
|
+
defaultImportHandler(data) { }
|
4145
|
+
transformToUppercase() {
|
4146
|
+
this.excludeColumnsInput = this.excludeColumnsInput.toUpperCase();
|
4147
|
+
}
|
4148
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DataExcelImporterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
4149
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: DataExcelImporterComponent, selector: "argenta-excel-importer", outputs: { excelData: "excelData" }, ngImport: i0, template: "<div class=\"excel-importer\">\n <input\n type=\"file\"\n (change)=\"handleFileInput($event)\"\n [accept]=\"config.acceptedFileTypes?.join(',')\"\n style=\"display: none\"\n #fileInput\n />\n <button (click)=\"fileInput.click()\">{{ buttonLabel }}</button>\n <lucide-icon\n name=\"settings\"\n [size]=\"24\"\n [strokeWidth]=\"2.25\"\n class=\"settings-icon\"\n (click)=\"openModal()\"\n ></lucide-icon>\n</div>\n\n<div class=\"modal-container\" *ngIf=\"showConfigModal\">\n <div class=\"modal-content\">\n <h4 class=\"titulo\">Configura\u00E7\u00E3o de Importa\u00E7\u00E3o</h4>\n <form (ngSubmit)=\"saveConfig()\">\n <div class=\"form-group\">\n <label for=\"acceptedFileTypes\">Tipos de Arquivo Permitidos</label>\n <input\n id=\"acceptedFileTypes\"\n type=\"text\"\n [(ngModel)]=\"userConfig.acceptedFileTypes\"\n name=\"acceptedFileTypes\"\n placeholder=\".xlsx, .xls\"\n />\n </div>\n <div class=\"form-group\" style=\"display: none\">\n <label for=\"titleRow\">Linha do T\u00EDtulo (se aplic\u00E1vel)</label>\n <input\n id=\"titleRow\"\n type=\"number\"\n [(ngModel)]=\"userConfig.titleRowIndex\"\n name=\"titleRow\"\n placeholder=\"Ex: 1\"\n (change)=\"validateRowInput('titleRow')\"\n />\n </div>\n <div class=\"form-group checkbox-group\">\n <div class=\"row\">\n <div class=\"col-md-8\">\n <label for=\"hasHeader\">A planilha cont\u00E9m cabe\u00E7alho?</label>\n </div>\n <div class=\"col-md-4\">\n <input\n id=\"hasHeader\"\n class=\"input-checkbox\"\n type=\"checkbox\"\n [(ngModel)]=\"userConfig.hasHeader\"\n name=\"hasHeader\"\n />\n </div>\n </div>\n </div>\n\n <!-- Exibe a linha do cabe\u00E7alho apenas se o checkbox estiver marcado -->\n <div class=\"form-group\" *ngIf=\"userConfig.hasHeader\">\n <label for=\"headerRow\">Linha do Cabe\u00E7alho</label>\n <input\n id=\"headerRow\"\n type=\"number\"\n [(ngModel)]=\"userConfig.headerRowIndex\"\n name=\"headerRow\"\n placeholder=\"Ex: 2\"\n (change)=\"validateRowInput('headerRow')\"\n />\n </div>\n\n <div class=\"form-group\">\n <label for=\"excludeRows\">Linhas a Excluir</label>\n <input\n id=\"excludeRows\"\n type=\"text\"\n [(ngModel)]=\"excludeRowsInput\"\n name=\"excludeRows\"\n placeholder=\"Ex: 1, 3\"\n />\n </div>\n <div class=\"form-group\">\n <label for=\"excludeColumns\">Colunas a Excluir</label>\n <input\n id=\"excludeColumns\"\n type=\"text\"\n [(ngModel)]=\"excludeColumnsInput\"\n name=\"excludeColumns\"\n placeholder=\"Ex: A, C\"\n (input)=\"transformToUppercase()\"\n />\n </div>\n <button type=\"submit\">Salvar Configura\u00E7\u00F5es</button>\n <button type=\"button\" (click)=\"closeModal()\">Fechar</button>\n </form>\n </div>\n</div>\n", styles: [".excel-importer{display:flex;align-items:center;gap:10px}.excel-importer button{background-color:var(--primary-color);color:var(--text-color);font-family:var(--font-family);padding:10px 20px;border:none;cursor:pointer;display:flex;align-items:center}.excel-importer button:hover{background-color:var(--secondary-color)}.excel-importer .settings-icon{color:var(--text-color);background-color:var(--primary-color);border-radius:50%;padding:5px;cursor:pointer;transition:background-color .3s,color .3s}.excel-importer .settings-icon:hover{background-color:var(--secondary-color);color:#fff}.modal-container{position:fixed;top:0;left:0;width:100%;height:100%;background-color:#00000080;display:flex;justify-content:center;align-items:center}.modal-content{background:#fff;padding:20px;border-radius:5px;width:400px}.modal-content h2{margin-bottom:20px}.modal-content .form-group{margin-bottom:15px}.modal-content .form-group label{display:block;margin-bottom:5px}.modal-content .form-group input{width:100%;padding:8px;border:1px solid #ccc;border-radius:4px}.modal-content button{margin-right:10px;padding:8px 15px;border:none;cursor:pointer}.modal-content button:first-of-type{background-color:var(--primary-color);color:#fff}.modal-content button:last-of-type{background-color:#ccc}input#excludeColumns{text-transform:uppercase}.small-label{font-size:.7rem;color:#555}.input-checkbox{margin-left:-5rem}.titulo{margin-bottom:2rem}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.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: i2.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i2.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i2.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: i4.LucideAngularComponent, selector: "lucide-angular, lucide-icon, i-lucide, span-lucide", inputs: ["class", "name", "img", "color", "absoluteStrokeWidth", "size", "strokeWidth"] }] }); }
|
4150
|
+
}
|
4151
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DataExcelImporterComponent, decorators: [{
|
4152
|
+
type: Component,
|
4153
|
+
args: [{ selector: "argenta-excel-importer", template: "<div class=\"excel-importer\">\n <input\n type=\"file\"\n (change)=\"handleFileInput($event)\"\n [accept]=\"config.acceptedFileTypes?.join(',')\"\n style=\"display: none\"\n #fileInput\n />\n <button (click)=\"fileInput.click()\">{{ buttonLabel }}</button>\n <lucide-icon\n name=\"settings\"\n [size]=\"24\"\n [strokeWidth]=\"2.25\"\n class=\"settings-icon\"\n (click)=\"openModal()\"\n ></lucide-icon>\n</div>\n\n<div class=\"modal-container\" *ngIf=\"showConfigModal\">\n <div class=\"modal-content\">\n <h4 class=\"titulo\">Configura\u00E7\u00E3o de Importa\u00E7\u00E3o</h4>\n <form (ngSubmit)=\"saveConfig()\">\n <div class=\"form-group\">\n <label for=\"acceptedFileTypes\">Tipos de Arquivo Permitidos</label>\n <input\n id=\"acceptedFileTypes\"\n type=\"text\"\n [(ngModel)]=\"userConfig.acceptedFileTypes\"\n name=\"acceptedFileTypes\"\n placeholder=\".xlsx, .xls\"\n />\n </div>\n <div class=\"form-group\" style=\"display: none\">\n <label for=\"titleRow\">Linha do T\u00EDtulo (se aplic\u00E1vel)</label>\n <input\n id=\"titleRow\"\n type=\"number\"\n [(ngModel)]=\"userConfig.titleRowIndex\"\n name=\"titleRow\"\n placeholder=\"Ex: 1\"\n (change)=\"validateRowInput('titleRow')\"\n />\n </div>\n <div class=\"form-group checkbox-group\">\n <div class=\"row\">\n <div class=\"col-md-8\">\n <label for=\"hasHeader\">A planilha cont\u00E9m cabe\u00E7alho?</label>\n </div>\n <div class=\"col-md-4\">\n <input\n id=\"hasHeader\"\n class=\"input-checkbox\"\n type=\"checkbox\"\n [(ngModel)]=\"userConfig.hasHeader\"\n name=\"hasHeader\"\n />\n </div>\n </div>\n </div>\n\n <!-- Exibe a linha do cabe\u00E7alho apenas se o checkbox estiver marcado -->\n <div class=\"form-group\" *ngIf=\"userConfig.hasHeader\">\n <label for=\"headerRow\">Linha do Cabe\u00E7alho</label>\n <input\n id=\"headerRow\"\n type=\"number\"\n [(ngModel)]=\"userConfig.headerRowIndex\"\n name=\"headerRow\"\n placeholder=\"Ex: 2\"\n (change)=\"validateRowInput('headerRow')\"\n />\n </div>\n\n <div class=\"form-group\">\n <label for=\"excludeRows\">Linhas a Excluir</label>\n <input\n id=\"excludeRows\"\n type=\"text\"\n [(ngModel)]=\"excludeRowsInput\"\n name=\"excludeRows\"\n placeholder=\"Ex: 1, 3\"\n />\n </div>\n <div class=\"form-group\">\n <label for=\"excludeColumns\">Colunas a Excluir</label>\n <input\n id=\"excludeColumns\"\n type=\"text\"\n [(ngModel)]=\"excludeColumnsInput\"\n name=\"excludeColumns\"\n placeholder=\"Ex: A, C\"\n (input)=\"transformToUppercase()\"\n />\n </div>\n <button type=\"submit\">Salvar Configura\u00E7\u00F5es</button>\n <button type=\"button\" (click)=\"closeModal()\">Fechar</button>\n </form>\n </div>\n</div>\n", styles: [".excel-importer{display:flex;align-items:center;gap:10px}.excel-importer button{background-color:var(--primary-color);color:var(--text-color);font-family:var(--font-family);padding:10px 20px;border:none;cursor:pointer;display:flex;align-items:center}.excel-importer button:hover{background-color:var(--secondary-color)}.excel-importer .settings-icon{color:var(--text-color);background-color:var(--primary-color);border-radius:50%;padding:5px;cursor:pointer;transition:background-color .3s,color .3s}.excel-importer .settings-icon:hover{background-color:var(--secondary-color);color:#fff}.modal-container{position:fixed;top:0;left:0;width:100%;height:100%;background-color:#00000080;display:flex;justify-content:center;align-items:center}.modal-content{background:#fff;padding:20px;border-radius:5px;width:400px}.modal-content h2{margin-bottom:20px}.modal-content .form-group{margin-bottom:15px}.modal-content .form-group label{display:block;margin-bottom:5px}.modal-content .form-group input{width:100%;padding:8px;border:1px solid #ccc;border-radius:4px}.modal-content button{margin-right:10px;padding:8px 15px;border:none;cursor:pointer}.modal-content button:first-of-type{background-color:var(--primary-color);color:#fff}.modal-content button:last-of-type{background-color:#ccc}input#excludeColumns{text-transform:uppercase}.small-label{font-size:.7rem;color:#555}.input-checkbox{margin-left:-5rem}.titulo{margin-bottom:2rem}\n"] }]
|
4154
|
+
}], propDecorators: { excelData: [{
|
4155
|
+
type: Output
|
4156
|
+
}] } });
|
4157
|
+
|
4158
|
+
class CsvImporterComponent {
|
4159
|
+
constructor() {
|
4160
|
+
this.config = {
|
4161
|
+
acceptedFileTypes: [".xlsx", ".xls", ".csv"],
|
4162
|
+
detectHeaders: true,
|
4163
|
+
delimiter: ";",
|
4164
|
+
onImport: () => { },
|
4165
|
+
};
|
4166
|
+
}
|
4167
|
+
handleFileInput(event) {
|
4168
|
+
const file = event.target.files[0];
|
4169
|
+
if (file) {
|
4170
|
+
const reader = new FileReader();
|
4171
|
+
// Detecta se o arquivo é CSV
|
4172
|
+
if (file.name.endsWith(".csv")) {
|
4173
|
+
reader.onload = (e) => {
|
4174
|
+
const csvData = e.target.result;
|
4175
|
+
const delimiter = this.config.delimiter ?? ";"; // Usa delimitador configurado ou padrão
|
4176
|
+
const jsonData = this.parseCSV(csvData, delimiter);
|
4177
|
+
this.processData(jsonData);
|
4178
|
+
};
|
4179
|
+
reader.readAsText(file);
|
4180
|
+
}
|
4181
|
+
else {
|
4182
|
+
// Processa arquivos Excel (XLSX/XLS)
|
4183
|
+
reader.onload = (e) => {
|
4184
|
+
const data = new Uint8Array(e.target.result);
|
4185
|
+
const workbook = XLSX.read(data, { type: "array" });
|
4186
|
+
const sheetName = workbook.SheetNames[0];
|
4187
|
+
const worksheet = workbook.Sheets[sheetName];
|
4188
|
+
const jsonData = XLSX.utils.sheet_to_json(worksheet, {
|
4189
|
+
header: 1,
|
4190
|
+
defval: "",
|
4191
|
+
});
|
4192
|
+
this.processData(jsonData);
|
4193
|
+
};
|
4194
|
+
reader.readAsArrayBuffer(file);
|
4195
|
+
}
|
4196
|
+
}
|
4197
|
+
}
|
4198
|
+
parseCSV(csvData, delimiter = ";") {
|
4199
|
+
return csvData
|
4200
|
+
.split("\n")
|
4201
|
+
.map((row) => row.split(delimiter).map((cell) => cell.trim()));
|
4202
|
+
}
|
4203
|
+
processData(jsonData) {
|
4204
|
+
const headers = this.getHeaders(jsonData);
|
4205
|
+
const dataRows = jsonData.slice(headers ? 1 : 0);
|
4206
|
+
const formattedData = this.formatData(dataRows, headers);
|
4207
|
+
this.config.onImport(formattedData);
|
4208
|
+
}
|
4209
|
+
getHeaders(data) {
|
4210
|
+
if (this.config.customHeaders) {
|
4211
|
+
return this.config.customHeaders;
|
4212
|
+
}
|
4213
|
+
if (this.config.detectHeaders && data.length > 0) {
|
4214
|
+
return data[0].map((header, index) => this.normalizeHeader(header || `col_${index}`));
|
4215
|
+
}
|
4216
|
+
return null; // Nenhum cabeçalho detectado
|
4217
|
+
}
|
4218
|
+
formatData(dataRows, headers) {
|
4219
|
+
if (!headers) {
|
4220
|
+
return dataRows; // Retorna dados brutos se não houver cabeçalhos
|
4221
|
+
}
|
4222
|
+
return dataRows.map((row) => {
|
4223
|
+
const record = {};
|
4224
|
+
headers.forEach((header, index) => {
|
4225
|
+
record[header] = row[index] ?? "";
|
4226
|
+
});
|
4227
|
+
return record;
|
4228
|
+
});
|
4229
|
+
}
|
4230
|
+
normalizeHeader(header) {
|
4231
|
+
return String(header)
|
4232
|
+
.normalize("NFD")
|
4233
|
+
.replace(/[\u0300-\u036f]/g, "")
|
4234
|
+
.replace(/\s+/g, "_")
|
4235
|
+
.toLowerCase();
|
4236
|
+
}
|
4237
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CsvImporterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
4238
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: CsvImporterComponent, selector: "argenta-csv-importer", inputs: { config: "config" }, ngImport: i0, template: "<div class=\"excel-importer\">\n <input\n type=\"file\"\n (change)=\"handleFileInput($event)\"\n [accept]=\"config.acceptedFileTypes?.join(',')\"\n style=\"display: none\"\n #fileInput\n />\n <button (click)=\"fileInput.click()\">Importar Arquivo</button>\n</div>\n", styles: [".excel-importer button{background-color:var(--primary-color);color:var(--text-color);font-family:var(--font-family);padding:10px 20px;border:none;cursor:pointer}.excel-importer button:hover{background-color:var(--secondary-color)}\n"] }); }
|
4239
|
+
}
|
4240
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CsvImporterComponent, decorators: [{
|
4241
|
+
type: Component,
|
4242
|
+
args: [{ selector: "argenta-csv-importer", template: "<div class=\"excel-importer\">\n <input\n type=\"file\"\n (change)=\"handleFileInput($event)\"\n [accept]=\"config.acceptedFileTypes?.join(',')\"\n style=\"display: none\"\n #fileInput\n />\n <button (click)=\"fileInput.click()\">Importar Arquivo</button>\n</div>\n", styles: [".excel-importer button{background-color:var(--primary-color);color:var(--text-color);font-family:var(--font-family);padding:10px 20px;border:none;cursor:pointer}.excel-importer button:hover{background-color:var(--secondary-color)}\n"] }]
|
4243
|
+
}], propDecorators: { config: [{
|
4244
|
+
type: Input
|
4245
|
+
}] } });
|
4246
|
+
|
3594
4247
|
// Select some icons (use an object, not an array)
|
3595
4248
|
class LucideIconsModule {
|
3596
4249
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LucideIconsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
3597
|
-
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: LucideIconsModule, imports: [
|
4250
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: LucideIconsModule, imports: [i4.LucideAngularModule], exports: [LucideAngularModule] }); }
|
3598
4251
|
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LucideIconsModule, imports: [LucideAngularModule.pick(icons), LucideAngularModule] }); }
|
3599
4252
|
}
|
3600
4253
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LucideIconsModule, decorators: [{
|
@@ -3640,7 +4293,12 @@ class ComponentsModule {
|
|
3640
4293
|
ModalComponent,
|
3641
4294
|
DragDropListComponent,
|
3642
4295
|
DynamicModalComponent,
|
3643
|
-
DynamicTableComponent
|
4296
|
+
DynamicTableComponent,
|
4297
|
+
ArgentaPdfDataHandlerComponent,
|
4298
|
+
ArgentaPdfDownloadComponent,
|
4299
|
+
DataExcelExporterComponent,
|
4300
|
+
DataExcelImporterComponent,
|
4301
|
+
CsvImporterComponent], imports: [CommonModule,
|
3644
4302
|
FormsModule,
|
3645
4303
|
ReactiveFormsModule,
|
3646
4304
|
NgSelectModule,
|
@@ -3681,7 +4339,12 @@ class ComponentsModule {
|
|
3681
4339
|
ModalComponent,
|
3682
4340
|
DragDropListComponent,
|
3683
4341
|
DynamicModalComponent,
|
3684
|
-
DynamicTableComponent
|
4342
|
+
DynamicTableComponent,
|
4343
|
+
ArgentaPdfDataHandlerComponent,
|
4344
|
+
ArgentaPdfDownloadComponent,
|
4345
|
+
DataExcelExporterComponent,
|
4346
|
+
DataExcelImporterComponent,
|
4347
|
+
CsvImporterComponent] }); }
|
3685
4348
|
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ComponentsModule, imports: [CommonModule,
|
3686
4349
|
FormsModule,
|
3687
4350
|
ReactiveFormsModule,
|
@@ -3729,6 +4392,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
3729
4392
|
DragDropListComponent,
|
3730
4393
|
DynamicModalComponent,
|
3731
4394
|
DynamicTableComponent,
|
4395
|
+
ArgentaPdfDataHandlerComponent,
|
4396
|
+
ArgentaPdfDownloadComponent,
|
4397
|
+
DataExcelExporterComponent,
|
4398
|
+
DataExcelImporterComponent,
|
4399
|
+
CsvImporterComponent,
|
3732
4400
|
],
|
3733
4401
|
imports: [
|
3734
4402
|
CommonModule,
|
@@ -3776,6 +4444,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
3776
4444
|
DragDropListComponent,
|
3777
4445
|
DynamicModalComponent,
|
3778
4446
|
DynamicTableComponent,
|
4447
|
+
ArgentaPdfDataHandlerComponent,
|
4448
|
+
ArgentaPdfDownloadComponent,
|
4449
|
+
DataExcelExporterComponent,
|
4450
|
+
DataExcelImporterComponent,
|
4451
|
+
CsvImporterComponent,
|
3779
4452
|
],
|
3780
4453
|
}]
|
3781
4454
|
}] });
|
@@ -3869,7 +4542,7 @@ class DataPaginateService {
|
|
3869
4542
|
};
|
3870
4543
|
}));
|
3871
4544
|
}
|
3872
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DataPaginateService, deps: [{ token:
|
4545
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DataPaginateService, deps: [{ token: i1$2.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
3873
4546
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DataPaginateService, providedIn: "root" }); }
|
3874
4547
|
}
|
3875
4548
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DataPaginateService, decorators: [{
|
@@ -3877,7 +4550,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
3877
4550
|
args: [{
|
3878
4551
|
providedIn: "root",
|
3879
4552
|
}]
|
3880
|
-
}], ctorParameters: function () { return [{ type:
|
4553
|
+
}], ctorParameters: function () { return [{ type: i1$2.HttpClient }]; } });
|
3881
4554
|
|
3882
4555
|
class RouterParameterService {
|
3883
4556
|
constructor() {
|
@@ -3976,7 +4649,7 @@ function setThemeColors(config) {
|
|
3976
4649
|
}
|
3977
4650
|
|
3978
4651
|
/*
|
3979
|
-
* Public API Surface of
|
4652
|
+
* Public API Surface of lib-atriun-angular
|
3980
4653
|
*
|
3981
4654
|
* Este arquivo exporta todos os componentes, enums e módulos necessários
|
3982
4655
|
* para que os consumidores da biblioteca possam utilizá-los em suas aplicações.
|
@@ -3987,5 +4660,5 @@ function setThemeColors(config) {
|
|
3987
4660
|
* Generated bundle index. Do not edit.
|
3988
4661
|
*/
|
3989
4662
|
|
3990
|
-
export { AccordionArgentaComponent, AlertComponent, AppBackgroundComponent, AutofocusDirective, BadgeComponent, BasicRegistrationComponent, ButtonClasses, ButtonComponent, CalendarArgentaComponent, CardComponent, CepMaskDirective, CheckboxComponent, CnpjMaskDirective, CodeHighlightComponent, ComponentsModule, ConfirmationComponent, ConfirmationService, CpfMaskDirective, CustomPaginationComponent, CustomSwitchComponent, DataPaginateService, DataTableComponent, DragDropListComponent, DynamicModalComponent, DynamicTableComponent, FileUploadComponent, InputComponent, JsonViewerComponent, LibPortalAngularModule, LucideIconsModule, ModalComponent, MultiSelectCategoryComponent, MultiSelectComponent, NotificationService, RadioComponent, RefreshService, RouterParameterService, SearchCustomerComponent, SearchInputComponent, SelectComponent, TabComponent, TextareaComponent, TreeNodeComponent, convertToSnakeCase, setThemeColors };
|
4663
|
+
export { AccordionArgentaComponent, AlertComponent, AppBackgroundComponent, ArgentaPdfDataHandlerComponent, ArgentaPdfDownloadComponent, AutofocusDirective, BadgeComponent, BasicRegistrationComponent, ButtonClasses, ButtonComponent, CalendarArgentaComponent, CardComponent, CepMaskDirective, CheckboxComponent, CnpjMaskDirective, CodeHighlightComponent, ComponentsModule, ConfirmationComponent, ConfirmationService, CpfMaskDirective, CsvImporterComponent, CustomPaginationComponent, CustomSwitchComponent, DataExcelExporterComponent, DataExcelImporterComponent, DataPaginateService, DataTableComponent, DragDropListComponent, DynamicModalComponent, DynamicTableComponent, FileUploadComponent, InputComponent, JsonViewerComponent, LibPortalAngularModule, LucideIconsModule, ModalComponent, MultiSelectCategoryComponent, MultiSelectComponent, NotificationService, RadioComponent, RefreshService, RouterParameterService, SearchCustomerComponent, SearchInputComponent, SelectComponent, TabComponent, TextareaComponent, TreeNodeComponent, convertToSnakeCase, setThemeColors };
|
3991
4664
|
//# sourceMappingURL=lib-portal-angular.mjs.map
|