import {
AfterViewInit,
Component,
Inject,
Input,
OnDestroy,
OnInit,
ViewChild
} from '@angular/core';
import { APP_CONFIG, CoreConfig, TranslationService } from '@arcelormittal-platform/core';
import { AuthenticationService } from '@arcelormittal-platform/security';
import { SnackBarService, SnackBarType } from '@arcelormittal-platform/ui';
import { StrategicalAxisDropdownItem, ThemeDropdownItem } from '@masterdata/models';
import {
ProcessesGridService,
StrategicalAxisesService,
ThemesService
} from '@masterdata/services';
import { TranslateService } from '@ngx-translate/core';
import { GridService, ToolbarConfigService } from '@shared/services';
import { FieldSettingsModel } from '@syncfusion/ej2-angular-dropdowns';
import {
ColumnChooserService,
DataResult,
DataStateChangeEventArgs,
EditService,
EditSettingsModel,
ExcelExportService,
FilterService,
FreezeService,
GridComponent,
GridLine,
PageService,
PageSettingsModel,
PdfExportService,
ReorderService,
ResizeService,
RowDDService,
RowDropEventArgs,
SaveEventArgs,
SortService,
ToolbarService
} from '@syncfusion/ej2-angular-grids';
import { MenuEventArgs } from '@syncfusion/ej2-angular-splitbuttons';
import { DataManager, Query, RemoteSaveAdaptor } from '@syncfusion/ej2-data';
import { catchError, finalize, retry, Subject, takeUntil, tap } from 'rxjs';
@Component({
selector: 'am-process-tab-item',
templateUrl: './process-tab-item.component.html',
styleUrls: ['./process-tab-item.component.scss'],
providers: [
PageService,
EditService,
ToolbarService,
ColumnChooserService,
FilterService,
FreezeService,
ReorderService,
ResizeService,
SortService,
RowDDService,
PdfExportService,
ExcelExportService,
],
})
export class ProcessTabItemComponent implements OnInit, AfterViewInit, OnDestroy {
@Input() public fetchActive = true;
@ViewChild('grid') grid: GridComponent | undefined;
public clientData: DataResult | undefined;
public showLoader = true;
public pageSettings: PageSettingsModel;
public editSettings: EditSettingsModel;
public toolbar: (string | object)[];
public themes: ThemeDropdownItem[] | undefined;
public selectedThemeIds: { [key: number]: number[] };
public themeFields: FieldSettingsModel;
public strategicalAxises: StrategicalAxisDropdownItem[] | undefined;
public selectedStrategicalAxisIds: { [key: number]: number[] };
public strategicalAxisFields: FieldSettingsModel;
public freezingOptions: { text: string; field: string }[];
public filterTypeItems = [
{ text: 'FilterBar', iconCss: 'e-icons e-bullet-5' },
{ text: 'Menu', iconCss: 'e-icons e-bullet-5' },
{ text: 'CheckBox', iconCss: 'e-icons e-bullet-5' },
{ text: 'Excel', iconCss: 'e-icons e-bullet-5' },
];
public gridLineItems = [
{ text: 'None', iconCss: 'e-icons e-bullet-5' },
{ text: 'Default', iconCss: 'e-icons e-bullet-5' },
{ text: 'Both', iconCss: 'e-icons e-bullet-5' },
{ text: 'Horizontal', iconCss: 'e-icons e-bullet-5' },
{ text: 'Vertical', iconCss: 'e-icons e-bullet-5' },
];
public allowRowDragAndDrop = true;
public currentLanguage: string | undefined;
public nameENRules: any;
private _baseUrl: string | undefined;
private _accessToken: string | undefined;
private userSettingsKey: string | undefined;
private destroy$ = new Subject<void>();
constructor(
private readonly processesGridService: ProcessesGridService,
private readonly themeService: ThemesService,
private readonly strategicalAxisesService: StrategicalAxisesService,
private readonly toolbarConfigService: ToolbarConfigService,
private readonly gridService: GridService,
private readonly translationService: TranslationService,
@Inject(APP_CONFIG) private readonly appConfig: CoreConfig,
private readonly snackBarService: SnackBarService,
private readonly translateService: TranslateService,
private readonly authService: AuthenticationService
) {
this._baseUrl = `${this.appConfig.api}masterdata/lists/processes/grid`;
const authValue = JSON.parse(
sessionStorage.getItem('oidc.user:https://sts.belgium.arcelormittal.com/TokenService:PROMATO')
);
this._accessToken = authValue.access_token;
}
public get selectedFrozenColumns() {
return this.gridService.selectedFrozenColumns;
}
public get lines() {
return this.gridService.lines;
}
public ngOnInit(): void {
this.authService.userProfile$
.pipe(
tap((userProfile) => {
this.userSettingsKey = `${userProfile.sid}-processes-gridState-${
this.fetchActive ? 'active' : 'inactive'
}`;
}),
takeUntil(this.destroy$)
)
.subscribe();
this.currentLanguage = this.translationService.getCurrentLanguage();
this.fetchData();
this.configureValidationRules();
this.pageSettings = { pageSize: 20 };
this.editSettings = {
allowEditing: true,
allowAdding: true,
allowDeleting: true,
mode: 'Normal',
newRowPosition: 'Bottom',
};
this.setupThemes();
this.setupStrategicalAxises();
this.configureToolbar();
}
public ngAfterViewInit(): void {
this.configureToolbar();
this.gridService.loadGridState(this.userSettingsKey, this.grid);
}
public ngOnDestroy(): void {
this.destroy$.next();
this.destroy$.complete();
}
public dataBound() {
this.configureFreezingOptions();
}
public dataStateChange(state: DataStateChangeEventArgs) {
console.log('🚀 ~ ProcessTabItemComponent ~ dataStateChange ~ state:', state);
const query = this.grid.getDataModule().generateQuery().requiresCount();
if (state.action) {
this.grid.dataSource = new DataManager(this.clientData.result).executeLocal(query);
if (state.dataSource) {
state.dataSource(this.clientData.result);
}
} else {
this.fetchDataFromService(query);
}
}
public actionBegin(args: any) {
const requestType = args.requestType;
if (requestType === 'beginEdit' || requestType === 'add') {
this.setCurrentThemeValues(args.rowData);
this.setCurrentStrategicalAxises(args.rowData);
}
if (requestType === 'save') {
args.data.attachedThemeIds = this.selectedThemeIds[args.rowData.id];
args.data.attachedStrategicalAxisIds = this.selectedStrategicalAxisIds[args.rowData.id];
const isChanges = JSON.stringify(args.data) !== JSON.stringify(args.previousData);
if (!isChanges) {
args.cancel = true;
this.grid.closeEdit();
}
}
if (requestType === 'add') {
args.data.isActive = true;
args.data.order = ++(this.grid.getPreviousRowData() as any).order;
}
if (requestType === 'sorting') {
this.allowRowDragAndDrop =
!args.columnName || (args.columnName === 'order' && args.direction === 'Ascending');
}
}
public onActionComplete(args: SaveEventArgs) {
if (args.requestType === 'save') {
this.snackBarService.open(
{
message: this.translateService.instant('Processes.SuccessMessages.Save'),
},
SnackBarType.CONFIRM
);
this.fetchData();
}
}
public rowDrop(args: RowDropEventArgs) {
const data = args.data[0] as any;
const pageSize = this.grid.pageSettings.pageSize;
const currentPage = this.grid.pageSettings.currentPage;
const newIndex = args.dropIndex + pageSize * (currentPage - 1) + 1;
const oldIndex = args.fromIndex + pageSize * (currentPage - 1) + 1;
this.processesGridService
.saveNewOrder$({ id: data.id, newIndex, oldIndex })
.pipe(
finalize(() => this.fetchData()),
takeUntil(this.destroy$)
)
.subscribe();
}
public filterChangeHandler(args: MenuEventArgs) {
this.gridService.handleFilterChange(args, this.grid);
setTimeout(() => {
this.saveGridState();
}, 0);
}
public gridLinesChangeHandler(args: MenuEventArgs) {
const type = args.item.text;
this.gridService.lines = type as GridLine;
this.saveGridState();
setTimeout(() => {
this.grid.refresh();
}, 0);
}
public handleFreezeChange(args: any, fieldColumn: string) {
this.gridService.selectedFrozenColumns = this.gridService.handleFreezeChange(
args,
fieldColumn,
this.grid
);
this.saveGridState();
}
public pdfExport() {
this.grid.pdfExport();
}
public excelExport() {
this.grid.excelExport();
}
public addNewRecord() {
this.grid.addRecord();
}
public handleClearFiltering() {
this.gridService.handleClearFiltering(this.grid);
}
public fetchData() {
const state = { skip: 0, take: 20 };
const query = new Query().skip(state.skip).take(state.take).requiresCount();
this.fetchDataFromService(query);
}
public searchList(searchTerm: string) {
const state = { skip: 0, take: 20 };
const query = new Query().skip(state.skip).take(state.take).requiresCount();
this.fetchDataFromService(query, searchTerm);
}
public onActionFailure() {
this.showLoader = false;
this.snackBarService.open(
{
message: this.translateService.instant('Processes.ErrorMessages.Save'),
},
SnackBarType.ERROR
);
}
public saveGridState() {
this.gridService.saveGridState(this.userSettingsKey, this.grid);
}
private fetchDataFromService(query: Query, searchTerm = '') {
this.processesGridService
.getAllData$(query, this.fetchActive, searchTerm)
.pipe(
tap((response: DataResult | Response) => {
this.showLoader = false;
this.clientData = response as DataResult;
this.grid.dataSource = new DataManager({
json: this.clientData.result,
updateUrl: `${this._baseUrl}/update`,
insertUrl: `${this._baseUrl}/create`,
adaptor: new RemoteSaveAdaptor(),
headers: [
{
Authorization: `Bearer ${this._accessToken}`,
},
],
});
}),
catchError((err) => {
this.showLoader = false;
this.snackBarService.open(
{
message: this.translateService.instant('Processes.ErrorMessages.Fetch'),
},
SnackBarType.ERROR
);
return err;
}),
retry(3),
takeUntil(this.destroy$)
)
.subscribe();
}
private setCurrentThemeValues(data: any) {
this.selectedThemeIds = { ...this.selectedThemeIds, [data?.id ?? -1]: data.attachedThemeIds };
}
private setupThemes() {
this.themeService
.getDropdownItems$()
.pipe(
tap((theme) => (this.themes = theme)),
takeUntil(this.destroy$)
)
.subscribe();
this.themeFields = { value: 'id', text: 'name' };
}
private setCurrentStrategicalAxises(data: any) {
this.selectedStrategicalAxisIds = {
...this.selectedStrategicalAxisIds,
[data?.id ?? -1]: data.attachedStrategicalAxisIds,
};
}
private setupStrategicalAxises() {
this.strategicalAxisesService
.getDropdownItems$()
.pipe(
tap((strategicalAxises) => (this.strategicalAxises = strategicalAxises)),
takeUntil(this.destroy$)
)
.subscribe();
this.strategicalAxisFields = { value: 'id', text: 'name' };
}
private configureFreezingOptions() {
if (this.grid) {
this.freezingOptions = this.grid
?.getVisibleColumns()
.map((column) => ({ text: column.headerText, field: column.field }))
.filter((x) => !!x.field && !!x.text)
.sort((a, b) => a.text?.localeCompare(b.text));
}
}
private configureToolbar() {
this.toolbar = this.toolbarConfigService.getConfig();
}
private configureValidationRules() {
this.nameENRules = {
required: [true, this.translateService.instant('Processes.ErrorMessages.NameEN.Required')],
};
}
}
This allows me to fetch the data remotely, do the crud actions on server, but sort and filter locally.
Only pagination is not working, and I suspect it's because the grid doesn't know how much records there are, as I never pass this.clientData.