import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { TranslationService } from '@arcelormittal-platform/core';
import {
ProcessesGridService,
WcmPillarsService,
StrategicalAxisesService,
} from '@masterdata/services';
import {
LoadingIndicator,
PageSettingsModel,
EditSettingsModel,
GridComponent,
RecordDoubleClickEventArgs,
EditService,
PageService,
ToolbarService,
RowDropEventArgs,
FilterSettings,
GridLine,
ColumnChooserService,
FilterService,
FreezeService,
ReorderService,
ResizeService,
SortService,
RowDDService,
DataResult,
DataStateChangeEventArgs,
} from '@syncfusion/ej2-angular-grids';
import { FormArray, FormBuilder, Validators } from '@angular/forms';
import { FieldSettingsModel } from '@syncfusion/ej2-angular-dropdowns';
import { StrategicalAxisDropdownItem, WcmPillarDropdownItem } from '@masterdata/models';
import { Observable, Subject, takeUntil } from 'rxjs';
import { GridService, ToolbarConfigService } from '@shared/services';
import { MenuEventArgs } from '@syncfusion/ej2-angular-splitbuttons';
import { Query, DataManager } from '@syncfusion/ej2-data';
@Component({
selector: 'am-processes',
templateUrl: './processes.component.html',
styleUrls: ['./processes.component.scss'],
providers: [
PageService,
EditService,
ToolbarService,
ColumnChooserService,
FilterService,
FreezeService,
ReorderService,
ResizeService,
SortService,
RowDDService,
],
})
export class ProcessesComponent implements OnInit, OnDestroy {
@ViewChild('grid') grid: GridComponent | undefined;
public clientData: DataResult | undefined;
public loadingIndicator: Partial<LoadingIndicator>;
public pageSettings: PageSettingsModel;
public editSettings: EditSettingsModel;
public toolbar: (string | object)[];
public currentNameFormArray: FormArray | undefined;
public nameDialogVisible = false;
public currentDescriptionFormArray: FormArray | undefined;
public descriptionDialogVisible = false;
public wcmPillars$: Observable<WcmPillarDropdownItem[]> | undefined;
public selectedWcmPillarIds: number[] | undefined;
public wcmPillarFields: FieldSettingsModel;
public strategicalAxises$: Observable<StrategicalAxisDropdownItem[]> | undefined;
public selectedStrategicalAxisIds: number[] | undefined;
public strategicalAxisFields: FieldSettingsModel;
public freezingOptions: { text: string; field: string }[];
public selectedFrozenColumns: string[] = [];
public filterTypeItems = [
{ text: 'FilterBar' },
{ text: 'Menu' },
{ text: 'CheckBox' },
{ text: 'Excel' },
];
public gridLineItems = [
{ text: 'None' },
{ text: 'Default' },
{ text: 'Both' },
{ text: 'Horizontal' },
{ text: 'Vertical' },
];
public lines: GridLine;
public filterSettings: Partial<FilterSettings>;
private currentRowData: any | undefined;
private currentColumnName: string | undefined;
private destroy$ = new Subject<void>();
constructor(
private readonly processesService: ProcessesGridService,
private readonly translationService: TranslationService,
private readonly fb: FormBuilder,
private readonly wcmPillarsService: WcmPillarsService,
private readonly strategicalAxisesService: StrategicalAxisesService,
private readonly toolbarConfigService: ToolbarConfigService,
private readonly gridService: GridService
) {}
get nameField(): string {
return `name${this.translationService.getCurrentLanguage().toUpperCase()}`;
}
get descriptionField(): string {
return `description${this.translationService.getCurrentLanguage().toUpperCase()}`;
}
public ngOnInit(): void {
this.loadingIndicator = { indicatorType: 'Shimmer' };
this.fetchData();
this.pageSettings = { pageSize: 20 };
this.editSettings = {
allowEditing: true,
allowAdding: true,
allowDeleting: true,
mode: 'Normal',
newRowPosition: 'Bottom',
};
this.toolbar = ['Add'];
this.setupWcmPillars();
this.setupStrategicalAxises();
this.configureToolbar();
}
public ngOnDestroy(): void {
this.destroy$.next();
this.destroy$.complete();
}
public dataStateChange(state: DataStateChangeEventArgs) {
const query = this.grid.getDataModule().generateQuery().requiresCount();
if (state.action && (state.action as any).action === 'filter') {
this.grid.dataSource = new DataManager(this.clientData.result).executeLocal(query);
} else {
this.processesService.getAllData(state, query).then((response: DataResult | Response) => {
this.grid.dataSource = response;
this.clientData = response as DataResult;
});
}
}
public dataBound() {
this.configureFreezingOptions();
}
public recordDoubleClick(args: RecordDoubleClickEventArgs) {
this.currentColumnName = args.column.field;
this.currentRowData = args.rowData;
this.currentNameFormArray = this.buildFormArray(args, 'name');
this.currentDescriptionFormArray = this.buildFormArray(args, 'description');
}
public actionBegin(args: any) {
const requestType = args.requestType;
if (requestType === 'beginEdit') {
if (this.currentColumnName.startsWith('name')) {
args.cancel = true;
this.nameDialogVisible = true;
}
if (this.currentColumnName.startsWith('description')) {
args.cancel = true;
this.descriptionDialogVisible = true;
}
this.setCurrentWcmPillarValues(args.rowData);
this.setCurrentStrategicalAxises(args.rowData);
}
if (requestType === 'save' || requestType === 'add') {
args.data.attachedWcmPillars = this.selectedWcmPillarIds;
args.data.attachedStrategicalAxises = this.selectedStrategicalAxisIds;
const nameTranslationsAsLocalizedText = this.currentNameFormArray?.value.map(
(translation) => ({
code: translation.code,
text: translation.text,
})
);
args.data.names = nameTranslationsAsLocalizedText ?? [
{
code: this.translationService.getCurrentLanguage().toUpperCase(),
text: args.data[`name${this.translationService.getCurrentLanguage().toUpperCase()}`],
},
];
const descriptionTranslationsAsLocalizedText = this.currentDescriptionFormArray?.value.map(
(translation) => ({
code: translation.code,
text: translation.text,
})
);
args.data.descriptions = descriptionTranslationsAsLocalizedText ?? [
{
code: this.translationService.getCurrentLanguage().toUpperCase(),
text: args.data[
`description${this.translationService.getCurrentLanguage().toUpperCase()}`
],
},
];
if (requestType === 'add') {
args.data.isActive = true;
args.data.order = this.grid.pageSettings.totalRecordsCount + 1;
}
}
}
public hideNameDialog() {
this.nameDialogVisible = false;
}
public hideDescriptionDialog() {
this.descriptionDialogVisible = false;
}
public saveNameTranslations() {
this.saveTranslations(this.currentNameFormArray);
}
public saveDescriptionTranslations() {
this.saveTranslations(this.currentDescriptionFormArray);
}
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.processesService
.saveNewOrder({ id: data.id, newIndex, oldIndex })
.pipe(takeUntil(this.destroy$))
.subscribe();
}
public filterChangeHandler(args: MenuEventArgs) {
this.gridService.handleFilterChange(args, this.grid);
}
public gridLinesChangeHandler(args: MenuEventArgs) {
const type = args.item.text;
this.lines = type as GridLine;
setTimeout(() => {
this.grid.refresh();
}, 0);
}
public handleFreezeChange(args: any, fieldColumn: string) {
this.gridService.handleFreezeChange(args, fieldColumn, this.grid, this.selectedFrozenColumns);
}
private fetchData() {
const state = { skip: 0, take: 20 };
const query = new Query().skip(state.skip).take(state.take).requiresCount();
this.processesService.getAllData(state, query).then((response: DataResult | Response) => {
this.grid.dataSource = response;
this.clientData = response as DataResult;
});
}
private setCurrentWcmPillarValues(data: any) {
this.selectedWcmPillarIds = data.wcmPillars.map((x) => x.id);
}
private setupWcmPillars() {
this.wcmPillars$ = this.wcmPillarsService.GetDropdownItems();
this.wcmPillarFields = { value: 'id', text: 'name' };
}
private setCurrentStrategicalAxises(data: any) {
this.selectedStrategicalAxisIds = data.strategicalAxises.map((x) => x.id);
}
private setupStrategicalAxises() {
this.strategicalAxises$ = this.strategicalAxisesService.getDropdownItems();
this.strategicalAxisFields = { value: 'id', text: 'name' };
}
private buildFormArray(args: RecordDoubleClickEventArgs, fieldPrefix: string): FormArray {
const newFormArray = new FormArray([]);
Object.keys(args.rowData)
.filter((key) => key.startsWith(fieldPrefix) && key !== fieldPrefix && !!args.rowData[key])
.forEach((key) => {
newFormArray.push(
this.fb.group({
code: this.fb.control(key.slice(-2), Validators.required),
text: this.fb.control(args.rowData[key], Validators.required),
})
);
});
return newFormArray;
}
private saveTranslations(formArray: FormArray | undefined): void {
if (!formArray || !this.currentRowData) return;
const translations = formArray?.value;
const initialValues = JSON.parse(JSON.stringify(this.currentRowData));
const columnName = this.currentColumnName.slice(0, -2);
translations.forEach((translation) => {
const field = `${columnName}${translation.code.toUpperCase()}`;
this.currentRowData[field] = translation.text;
});
this.currentRowData['names'] = Object.keys(this.currentRowData)
.filter((key) => key.startsWith('name') && key !== 'name' && !!this.currentRowData[key])
.map((key) => ({ code: key.slice(-2), text: this.currentRowData[key] }));
this.currentRowData['descriptions'] = Object.keys(this.currentRowData)
.filter(
(key) =>
key.startsWith('description') && key !== 'description' && !!this.currentRowData[key]
)
.map((key) => ({ code: key.slice(-2), text: this.currentRowData[key] }));
this.currentRowData['attachedWcmPillars'] = this.selectedWcmPillarIds;
this.currentRowData['attachedStrategicalAxises'] = this.selectedStrategicalAxisIds;
const allHaveValues = translations.every((translation) => translation.text);
if (JSON.stringify(initialValues) !== JSON.stringify(this.currentRowData) && allHaveValues) {
const rowIndex = this.grid.getRowIndexByPrimaryKey(this.currentRowData.id);
this.grid.updateRowValue(rowIndex, this.currentRowData);
}
this.nameDialogVisible = false;
this.descriptionDialogVisible = false;
}
private configureFreezingOptions() {
if (this.grid) {
this.freezingOptions = this.grid
?.getVisibleColumns()
.map((column) => ({ text: column.headerText, field: column.field }))
.filter((x) => !!x.field)
.sort((a, b) => a.text?.localeCompare(b.text));
}
}
private configureToolbar() {
this.toolbar = this.toolbarConfigService.getConfig();
}
}