1160 lines
43 KiB
TypeScript
1160 lines
43 KiB
TypeScript
import { remoteData } from './../../data';
|
||
import { LanguageService } from '../language.service';
|
||
import { PlanTimeBarComponent } from '../plan-time-bar/plan-time-bar.component';
|
||
import { FilterDialogComponent } from '../filter-dialog/filter-dialog.component';
|
||
import { filteredData, editingData } from '../../data';
|
||
import { ImplementerDialogComponent } from '../implementer-dialog/implementer-dialog.component';
|
||
import { Component, Inject, OnInit, ViewChild } from '@angular/core';
|
||
import { MatPaginator, PageEvent } from '@angular/material/paginator';
|
||
import { GanttComponent } from '@syncfusion/ej2-angular-gantt';
|
||
import { DataService } from 'src/app/data.service';
|
||
import { projectNewData } from 'src/data';
|
||
import {FormGroup, FormControl} from '@angular/forms';
|
||
import {MatDialog} from '@angular/material/dialog';
|
||
import * as $ from 'jquery';
|
||
import { StateDialogComponent } from 'src/app/state-dialog/state-dialog.component';
|
||
import { MatSnackBar, MatSnackBarHorizontalPosition, MatSnackBarVerticalPosition } from '@angular/material/snack-bar';
|
||
import { MAT_DATE_FORMATS } from '@angular/material/core';
|
||
|
||
export const MY_DATE_FORMATS = {
|
||
parse: {
|
||
dateInput: 'DD.MM.YYYY',
|
||
},
|
||
display: {
|
||
dateInput: 'DD.MM.YYYY',
|
||
monthYearLabel: 'MMMM YYYY',
|
||
dateA11yLabel: 'LL',
|
||
monthYearA11yLabel: 'MMMM YYYY'
|
||
},
|
||
};
|
||
interface Preset {
|
||
id: string;
|
||
name: string;
|
||
presetType: string;
|
||
definition: any;
|
||
}
|
||
|
||
interface presetGroup {
|
||
disabled?: boolean;
|
||
name: string;
|
||
presets: Preset[];
|
||
}
|
||
|
||
|
||
@Component({
|
||
selector: 'ntt-gantt',
|
||
templateUrl: './ntt-gantt.component.html',
|
||
styleUrls: ['./ntt-gantt.component.css'],
|
||
providers: [
|
||
{ provide: MAT_DATE_FORMATS, useValue: MY_DATE_FORMATS }
|
||
]
|
||
})
|
||
/**
|
||
* The NttGanttComponent is the core Component of the application
|
||
*/
|
||
export class NttGanttComponent implements OnInit {
|
||
|
||
/**###################################################################### Variable Declarations and Definitions ######################################################################*/
|
||
|
||
/**############################### ViewChild Components /**###############################*/
|
||
@ViewChild('ganttObject')
|
||
public ganttDefault!: GanttComponent;
|
||
|
||
@ViewChild('plantimeComponent')
|
||
public plantimeComponent!: PlanTimeBarComponent;
|
||
|
||
@ViewChild(MatPaginator) paginator: MatPaginator;
|
||
|
||
/**############################### Default Variables /**###############################*/
|
||
|
||
public range = new FormGroup({
|
||
start: new FormControl<Date | null>(new Date('12/01/2022')),
|
||
end: new FormControl<Date | null>(new Date('01/31/2024')),
|
||
});
|
||
|
||
public data: any[] = [];
|
||
public allResources: any[] = [];
|
||
public resources: any[] = [];
|
||
public userSupportGroup: string;
|
||
public taskSettings: object = {};
|
||
public labelSettings: object = {};
|
||
public projectStartDate: Date = new Date('12/01/2022');
|
||
public projectEndDate: Date = new Date('01/31/2024');
|
||
public resourceFields: object ={};
|
||
public editSettings: object = {};
|
||
public tooltipSettings: object ={};
|
||
public columns: object[] = [];
|
||
public toolbar: any[] = [];
|
||
public timelineSettings: object = {};
|
||
public rendering: boolean = true;
|
||
public blockedTaskIDs : number [] = [8];
|
||
public selectionSettings : object = {};
|
||
public spin: boolean = true;
|
||
public sliceStart: number;
|
||
public sliceEnd: number;
|
||
|
||
public filterSettings: object;
|
||
public splitterSettings : object;
|
||
public renderGantt: boolean;
|
||
public firstLoad: boolean;
|
||
public selectedScalar: string;
|
||
public scalars: string[];
|
||
public showDetails: boolean = true;
|
||
public panelOpenState:boolean;
|
||
public showNoResultsError: boolean = false;
|
||
|
||
public horizontalPosition: MatSnackBarHorizontalPosition = 'end';
|
||
public verticalPosition: MatSnackBarVerticalPosition = 'bottom';
|
||
public inputForTimeline = [];
|
||
public renderplanTime: boolean = false;
|
||
public planTimeScrollLeft: number = 0;
|
||
|
||
public stateList: any[] = [];
|
||
public filterStartDate: Date;
|
||
public filterEndDate: Date;
|
||
public showFilters: boolean = false;
|
||
public filterEnabled: boolean = false;
|
||
private oldFilters:{};
|
||
public filters: any = null;
|
||
public sortEnabled: boolean = false;
|
||
public sortedData: any[] = [];
|
||
|
||
private selectedRescourceIds : any[] = [];
|
||
private selectedrowindex: number[] = [];
|
||
private selectedrecords: any[] = [];
|
||
private selRecs: any[] = [];
|
||
public states : any[] = [];
|
||
private approvalPending: boolean;
|
||
public sort = null;
|
||
public oldSort = null;
|
||
public planTimes : any[] = [];
|
||
public sortSelectorName: any;
|
||
|
||
public presets : any[] = [];
|
||
public selectedPreset: Preset = {id: 'test', name : 'test', presetType: 'test', definition: {}};
|
||
public presetControl: FormControl = new FormControl('');;
|
||
public presetGroups: presetGroup[] = [
|
||
{
|
||
name: 'Sysdemdefault',
|
||
presets: [
|
||
{id: '0', name: 'TEST', presetType: 'Sysdemdefault', definition: {}},
|
||
|
||
],
|
||
},
|
||
{
|
||
name: 'Admin',
|
||
presets: [
|
||
{id: '1', name: 'TEST1', presetType: 'Admin', definition: {}},
|
||
|
||
],
|
||
},
|
||
{
|
||
name: 'User',
|
||
presets: [
|
||
{id: '2', name: 'TEST2', presetType: 'User', definition: {}},
|
||
|
||
],
|
||
},
|
||
];
|
||
public userPreferences: {language:'', showDetails: false, view: ''};
|
||
public showSaveButton: boolean = false;
|
||
public showSaveUnderButton: boolean = false;
|
||
|
||
|
||
/**###################################################################### Initial Loading functions ######################################################################*/
|
||
|
||
/**
|
||
* The constructor injects required dependencies
|
||
* @param languageService injects the languageService for language management in the component
|
||
* @param dataService injects the dataService for data management and backend communication
|
||
* @param matDialog injects the matDialog
|
||
*/
|
||
constructor(public languageService: LanguageService, public dataService: DataService, public matDialog : MatDialog, private _snackBar: MatSnackBar ) {
|
||
this.initLanguge(true);
|
||
}
|
||
|
||
/**
|
||
* The function ngOnInit sets values which are required for rendering the gantt Chart. Furthermore it triggers the Dataservice to fetch Changes from the backend and trims the resources (Changes Array) and sets the paginator to the first page.
|
||
*/
|
||
public ngOnInit(): void {
|
||
var WebFont = require('webfontloader');
|
||
WebFont.load({google: {families: ['Material Icons',],},});
|
||
this.renderGantt = false;
|
||
this.firstLoad = true;
|
||
this.sliceStart = 0;
|
||
this.sliceEnd = 20;
|
||
|
||
// this.dataService.initPresets().then((res: any)=>{
|
||
// this.presets = res.presets;
|
||
// this.selectedPreset = res.selectedPreset;
|
||
// this.presetGroups = res.presetGroups;
|
||
// this.filters = this.selectedPreset.definition;
|
||
// this.filterEnabled = true;
|
||
// this.showDetails = res.userPreferences.showDetails;
|
||
// this.selectedScalar = this.scalars[res.userPreferences.view];
|
||
|
||
// this.dataService.fetchUserSupportGroup().then((res: any)=>{
|
||
// this.userSupportGroup = res.name;
|
||
// this.refreshData();
|
||
// this.states = this.dataService.getStates();
|
||
// this.dataService.fetchStates().then((res: any [])=>{
|
||
// this.states = res;
|
||
// this.stateList = res;
|
||
// this.spin = false;
|
||
// console.log(this.states);
|
||
// this.inputForTimeline = [this.splitterSettings, this.projectStartDate, this.projectEndDate];
|
||
// });
|
||
// });
|
||
// });
|
||
this.refreshGanttwithPresets();
|
||
|
||
|
||
this.taskSettings = {
|
||
id: 'TaskID',
|
||
name: 'TaskName',
|
||
startDate: 'StartDate',
|
||
endDate: 'EndDate',
|
||
duration: 'Duration',
|
||
progress: 'Progress',
|
||
dependency: 'Predecessor',
|
||
resourceInfo: 'resources',
|
||
work: 'work',
|
||
expandState: 'isExpand',
|
||
child: 'subtasks',
|
||
isFixed: 'isFixed',
|
||
vertrag: 'vertrag'
|
||
};
|
||
|
||
this.resourceFields = {
|
||
id: 'resourceId',
|
||
name: 'resourceName',
|
||
unit: 'Unit',
|
||
group: 'resourceGroup',
|
||
state: 'state',
|
||
stateName: 'stateName',
|
||
isRes: 'isRes',
|
||
vertrag: 'vertrag',
|
||
vertragName: 'vertragName',
|
||
supportGroup: 'supportGroup',
|
||
supportGroupId: 'supportGroupId',
|
||
implementerEdit: 'implementerEdit',
|
||
plantime : 'plantime'
|
||
};
|
||
|
||
this.columns = [
|
||
{ field: 'TaskName', headerText: 'Kurzbeschreibung', width: 230 },
|
||
{ field: 'stateName', headerText: 'Status', width: 250},
|
||
{ field: 'vertragName', headerText: 'Vertrag / Provider Cluster', width: 150 },
|
||
{ field: 'supportGroup', headerText: 'Gewählte Support Gruppe' },
|
||
{ field: 'StartDate', headerText: 'Geplantes Start-Datum', format : {type:'date', format:'dd.MM.yyyy'}},
|
||
{ field: 'plantime', headerText: 'Planzeit in H', width: 100 },
|
||
{ field: 'changeNr', headerText: 'Change Nummer', width: 140 }
|
||
];
|
||
|
||
this.timelineSettings = {topTier: {unit: 'Month'}, bottomTier: {format: 'WW', unit: 'Week', count: 1}};
|
||
this.editSettings = {allowAdding: true, allowEditing: true, allowDeleting: true, allowTaskbarEditing: true, showDeleteConfirmDialog: true};
|
||
this.filterSettings = {ignoreAccent: true};
|
||
this.selectionSettings = {mode: 'Row',type: 'Multiple'};
|
||
this.toolbar = ['Cancel'];
|
||
this.labelSettings = {rightLabel: 'resources',taskLabel: 'TaskName'};
|
||
this.tooltipSettings = {showTooltip: true}
|
||
this.projectStartDate = this.range.controls.start.value;
|
||
this.projectEndDate = this.range.controls.end.value;
|
||
this.splitterSettings = {position: 30 + '%'};
|
||
this.inputForTimeline = [this.splitterSettings, this.projectStartDate, this.projectEndDate];
|
||
}
|
||
|
||
public selectPreset(event: any){
|
||
this.showSaveButton = false;
|
||
this.showSaveUnderButton = false;
|
||
console.log(event);
|
||
this.dataService.selectPreset(event.value).then((res)=>{
|
||
this.refreshGanttwithPresets();
|
||
});
|
||
|
||
}
|
||
public savePreset(preset: any){
|
||
this.showSaveButton = false;
|
||
this.showSaveUnderButton = false;
|
||
|
||
this.dataService.savePreset(preset).then((res)=>{{
|
||
console.log(res);
|
||
}})
|
||
}
|
||
public updatePreset(){
|
||
this.showSaveButton = false;
|
||
this.selectedPreset.definition = this.filters;
|
||
this.dataService.updatePreset(this.selectedPreset).then((res)=>{
|
||
console.log(res);
|
||
});
|
||
}
|
||
public renamePreset(preset: any){
|
||
|
||
}
|
||
public deletePreset(preset: any){
|
||
|
||
}
|
||
|
||
public editUserPreferences(){
|
||
let showDetails = 0;
|
||
if(this.showDetails){
|
||
showDetails = 1;
|
||
}
|
||
let view;
|
||
let index = 0;
|
||
for (const scalar of this.scalars) {
|
||
index++;
|
||
if(scalar == this.selectedScalar){
|
||
view = index;
|
||
}
|
||
}
|
||
if(this.userPreferences.language == this.languageService.language && this.userPreferences.showDetails == this.showDetails && this.userPreferences.view == view){
|
||
}else{
|
||
this.dataService.editUserPreferences({language: this.languageService.language, showDetails: showDetails, view: view}).then((res)=>{
|
||
console.log(res);
|
||
});
|
||
}
|
||
}
|
||
|
||
public refreshGanttwithPresets(){
|
||
this.showSaveButton = false;
|
||
this.showSaveUnderButton = false;
|
||
this.dataService.initPresets().then((res: any)=>{
|
||
this.presets = res.presets;
|
||
this.selectedPreset = res.selectedPreset;
|
||
this.presetGroups = res.presetGroups;
|
||
this.filters = this.selectedPreset.definition;
|
||
this.filterEnabled = true;
|
||
this.userPreferences = res.userPreferences;
|
||
this.showDetails = res.userPreferences.showDetails;
|
||
this.selectedScalar = this.scalars[res.userPreferences.view];
|
||
this.changeScalar();
|
||
|
||
|
||
this.dataService.fetchUserSupportGroup().then((res: any)=>{
|
||
this.userSupportGroup = res.name;
|
||
this.refreshData();
|
||
this.states = this.dataService.getStates();
|
||
this.dataService.fetchStates().then((res: any [])=>{
|
||
this.states = res;
|
||
this.stateList = res;
|
||
this.spin = false;
|
||
console.log(this.states);
|
||
this.inputForTimeline = [this.splitterSettings, this.projectStartDate, this.projectEndDate];
|
||
});
|
||
});
|
||
});
|
||
}
|
||
|
||
|
||
|
||
/**###################################################################### Data Mapping, Filter and Sorting Functions ######################################################################*/
|
||
|
||
/**
|
||
* The function mapTasksToResources slices the allResources array to the resources array according the actual page conditions maps the actual tasks (Dates) to the actual resources (Changes)
|
||
* This function is triggered when a pageEvent is thrown respectively a user changes the page on the paginator
|
||
* @param start begin of slice
|
||
* @param end end of slice
|
||
*/
|
||
public mapTasksToResources(start : number, end : number){
|
||
this.data = [];
|
||
this.resources = this.allResources;
|
||
for (const resource of this.resources) {
|
||
for (const task of resource.tasks) {
|
||
this.data.push(task);
|
||
}
|
||
}
|
||
}
|
||
/**
|
||
* The function refreshData fetches a new changes Array from the backend, therefore the mapRequestJSON function is called to map the requestJSON with all filter and sort parameters.
|
||
* Furthermore it evaluates the result if the applied filters delivered any Results.
|
||
* This function is the most called Funktion in the whole project, it is triggered by a pageEvent, when a filter gets applied and much more...
|
||
*/
|
||
refreshData(){
|
||
this.editUserPreferences();
|
||
this.showNoResultsError = false;
|
||
this.renderGantt = false;
|
||
this.dataService.fetchChanges(this.mapRequestJSON()).then((res: any[])=>{
|
||
this.allResources = res;
|
||
this.mapTasksToResources(this.sliceStart,this.sliceEnd);
|
||
if(res.length > 0){
|
||
this.spin = true;
|
||
this.renderGantt = true;
|
||
this.showNoResultsError = false;
|
||
if(this.selectedScalar == this.scalars[1]){
|
||
this.renderplanTime = true;
|
||
}
|
||
|
||
}else{
|
||
this.renderGantt = false;
|
||
this.spin = false;
|
||
this.showNoResultsError = true;
|
||
this.renderplanTime = false;
|
||
}
|
||
});
|
||
}
|
||
/**
|
||
* The function clearFilter clears allFilter parameters and set them to inital values, then it triggers the refreshData function to fetch the changes without any filters except the supportGroup filter.
|
||
* This function is triggered if the user disables the apply filter switch
|
||
*/
|
||
clearFilter(){
|
||
this.filters = null;
|
||
this.filterEnabled = false;
|
||
this.sort = null;
|
||
this.sortEnabled = false;
|
||
this.refreshData();
|
||
}
|
||
/**
|
||
* The function mapRequestJSON maps the requestObject for the refreshData function, it evaluates if filters or sort parameters are set.
|
||
* Furtheremore it adds the sliceStart and sliceEnd values of the paginator to the requestObject, because the frontend only delivers the changes that can be displayed on one selected page of the paginator.
|
||
* If no filter is applied the function sets a default supportGroup filter, so that the user gets only changes displayed, which are in his supportGroup.
|
||
*/
|
||
mapRequestJSON(){
|
||
let request =
|
||
{
|
||
'sliceStart': this.sliceStart,
|
||
'sliceEnd': this.sliceEnd,
|
||
filter: this.filterEnabled ? this.filters : {filterElement: [{column: "SupportGroup", filter: "equals", criteria: [this.userSupportGroup]}]},
|
||
sort: this.sortEnabled ? this.sort : {
|
||
'column': 'ChangeNr',
|
||
'mode': 'asc'
|
||
},
|
||
}
|
||
// request.filter = null;
|
||
return request;
|
||
}
|
||
/**
|
||
* The function applyFilter applies the selected filters and refrehses the gantt chart with the new filters.
|
||
* Furthermore it stores the old filters in a help variable to restore it when to user turns the apply filter switch back on.
|
||
* This function is triggered by the a filter action of the filterdialog, or if the user switches the apply filter switch.
|
||
*/
|
||
applyFilter(){
|
||
if(this.filterEnabled){
|
||
this.oldFilters = this.filters
|
||
this.filters = null;
|
||
this.refreshData();
|
||
this.plantimeComponent.fetchPlanTimes(this.filters);
|
||
}else{
|
||
this.filters = this.oldFilters;
|
||
this.refreshData();
|
||
this.plantimeComponent.fetchPlanTimes(this.filters);
|
||
}
|
||
|
||
}
|
||
/**
|
||
* The function openFilterDialog triggers the opening of the filterDialog, recieves the results of the filterDialog and refrehses the gantt chart.
|
||
* This function is triggered by the filter button.
|
||
*/
|
||
openFilterDialog(){
|
||
console.log(this.filters);
|
||
let dialogRef = FilterDialogComponent;
|
||
this.matDialog.open(dialogRef,
|
||
{data : [{filters: this.filters, userSg: this.userSupportGroup}], width: '50%', maxWidth: '800px'}).afterClosed().subscribe((res)=>{
|
||
if(res){
|
||
this.filters = res;
|
||
this.filterEnabled = true;
|
||
// this.dataService.savePreset({name: "FRONTEND TEST PRESET", definition: JSON.stringify(this.filters)}).then((res)=>{
|
||
// console.log(res);
|
||
// });
|
||
// this.dataService.updatePreset({id: 'AGGAA5V0G2LS6ASCSUZZSBS79E40O5', definition: JSON.stringify(this.filters)}).then((res)=>{
|
||
// console.log(res);
|
||
// });
|
||
if(this.filters !== this.selectedPreset.definition){
|
||
if(this.selectedPreset.presetType == ''){
|
||
this.showSaveButton = true;
|
||
}else{
|
||
this.showSaveUnderButton = true;
|
||
}
|
||
|
||
}
|
||
this.refreshData();
|
||
}
|
||
});
|
||
}
|
||
|
||
/**###################################################################### Reaction on EVENTS ######################################################################*/
|
||
|
||
/**############################### NTT Gantt Component Helper Functions /**###############################*/
|
||
|
||
/**
|
||
* The function languageChange executes a language change in the language service and triggers the initLanguage function.
|
||
* This function is triggered by a manual language of the user.
|
||
*/
|
||
public languageChange(args: any){
|
||
this.languageService.languageChange(args.value),
|
||
this.initLanguge();
|
||
this.plantimeComponent.changeLanguage();
|
||
this.editUserPreferences();
|
||
}
|
||
|
||
/**
|
||
* The function initLanguge executes a language change for the ntt gantt component. Therefore the time scalar and the gantt columns get the corresponding values determined by the selected language.
|
||
* This function is triggered by the ngOnInit function or the languageChange function
|
||
* @param initial determines if the function is initially trigger by the ngOnInit function, in all other cases the gantt chart should be refrehed
|
||
*/
|
||
initLanguge(initial: boolean = false){
|
||
|
||
if(this.languageService.language == 'DE'){
|
||
this.scalars = ['Woche', 'Monat', 'Jahr'];
|
||
this.selectedScalar = 'Monat';
|
||
}
|
||
else{
|
||
this.scalars = ['Week', 'Month', 'Year'];
|
||
this.selectedScalar = 'Month';
|
||
|
||
}
|
||
this.columns = this.languageService.getColumns();
|
||
if(!initial){
|
||
this.refreshData();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* The function changeScalar executes a change of the displayed time scalar.
|
||
* This function is triggered if the user changes the time scalar.
|
||
*/
|
||
public changeScalar(){
|
||
if(this.selectedScalar == this.scalars[0]){
|
||
this.timelineSettings = {topTier: {unit: 'Week'}, bottomTier: {format: 'dd', unit: 'Day', count: 1}};
|
||
this.renderplanTime = false;
|
||
}
|
||
if(this.selectedScalar == this.scalars[1]){
|
||
this.timelineSettings = {topTier: {unit: 'Month'}, bottomTier: {format: 'WW', unit: 'Week', count: 1}};
|
||
this.renderplanTime = true;
|
||
}
|
||
if(this.selectedScalar == this.scalars[2]){
|
||
this.timelineSettings = {topTier: {unit: 'Year'}, bottomTier: {format: 'MM',unit: 'Month',count: 1}};
|
||
this.renderplanTime = false;
|
||
}
|
||
this.editUserPreferences();
|
||
|
||
}
|
||
|
||
/**############################### NTT Gantt Component EVENTS /**###############################*/
|
||
|
||
/**
|
||
* The function handlePageEvent catches the corresponding matpaginator event and slices the gantt chart, that it fits to the actual page
|
||
* @param e pageEvent from the matpaginator
|
||
*/
|
||
public handlePageEvent(e: PageEvent):void {
|
||
let start = e.pageSize*e.pageIndex;
|
||
let end = start+ e.pageSize;
|
||
this.sliceStart = start;
|
||
this.sliceEnd = end;
|
||
this.refreshData();
|
||
}
|
||
|
||
/**
|
||
* The function startDateChanged catches the corresponding date-range-picker event
|
||
* @param startDate new startDate from date-range-picker
|
||
*/
|
||
public startDateChanged(startDate: any){
|
||
if(this.range.status == 'VALID' && this.range.controls.start.value && this.range.controls.end.value){ //event for Requesting new Records based on the Dates
|
||
this.projectStartDate = new Date(this.range.controls.start.value);
|
||
this.plantimeComponent.changeDateRange(this.projectStartDate, this.projectEndDate);
|
||
this.renderplanTime = true;
|
||
|
||
}
|
||
}
|
||
|
||
/**
|
||
* The function endDateChanged catches the corresponding date-range-picker event and validates the selected start- and enddate bacause the gantt chart needs a valid Date to be displayed
|
||
* @param endDate new endDate from date-range-picker
|
||
*/
|
||
public endDateChanged(endDate: any){
|
||
if(this.range.status == 'VALID' && this.range.controls.start.value && this.range.controls.end.value){ //event for Requesting new Records based on the Dates
|
||
this.projectEndDate = new Date(this.range.controls.end.value);
|
||
this.plantimeComponent.changeDateRange(this.projectStartDate, this.projectEndDate);
|
||
this.renderplanTime = true;
|
||
|
||
}
|
||
}
|
||
/**
|
||
* The function toolbarBtnClicked catches the corresponding syncfsuions event and executes the button logic when a button is clicked
|
||
* @param args
|
||
*/
|
||
public toolbarBtnClicked(args :any){
|
||
if(args.item.text === "Statusübergang" || args.item.text === "State Transition"){
|
||
let data = {changes: [], states: this.states};
|
||
for (const selectedRescourceId of this.selectedRescourceIds) {
|
||
for (const iterator of this.resources) {
|
||
if(iterator.resourceId == selectedRescourceId){
|
||
data.changes.push({resourceId: iterator.resourceId, changeNr: iterator.changeNr, currentState: iterator.state});
|
||
}
|
||
}
|
||
}
|
||
let dialogRef = StateDialogComponent;
|
||
this.matDialog.open(dialogRef,{data : data}).afterClosed().subscribe((res)=>{
|
||
console.log(res);
|
||
if(res == "Success"){
|
||
this.refreshData();
|
||
}
|
||
});
|
||
}
|
||
|
||
if(args.item.text === "Implementer Eintragen" || args.item.text === "Enter Implementer"){
|
||
let data = {changes: []};
|
||
for (const selectedRescourceId of this.selectedRescourceIds) {
|
||
for (const change of this.resources) {
|
||
if(change.resourceId == selectedRescourceId){
|
||
data.changes.push({resourceId: change.resourceId, pkgId: change.changeNr, supportGroupId: change.supportGroupId});
|
||
}
|
||
}
|
||
}
|
||
this.matDialog.open(ImplementerDialogComponent,{data : data});
|
||
}
|
||
|
||
if(args.item.text === "Genehmigen" || args.item.text === "Approve"){
|
||
for (const selectedRescourceId of this.selectedRescourceIds) {
|
||
for (const change of this.resources) {
|
||
if(change.resourceId == selectedRescourceId){
|
||
this.dataService.updateApproval(change, 1).then((res: any)=>{
|
||
if(res.status == 200){
|
||
this._snackBar.open("Genehmigung erfolgreich", 'Schließen', { horizontalPosition: this.horizontalPosition, verticalPosition: this.verticalPosition, panelClass: ['green-snackbar']});
|
||
}else{
|
||
this._snackBar.open(res.HttpErrorResponse.message, 'Schließen', {horizontalPosition: this.horizontalPosition, verticalPosition: this.verticalPosition, panelClass: ['red-snackbar']});
|
||
}
|
||
this.refreshData();
|
||
});
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if(args.item.text === "Zur Genehmigung" || args.item.text === "Permit"){
|
||
let data = {changes: [], states: this.states};
|
||
for (const selectedRescourceId of this.selectedRescourceIds) {
|
||
for (const iterator of this.resources) {
|
||
if(iterator.resourceId == selectedRescourceId){
|
||
data.changes.push({resourceId: iterator.resourceId, changeNr: iterator.changeNr, currentState: iterator.state});
|
||
}
|
||
}
|
||
}
|
||
let dialogRef = StateDialogComponent;
|
||
this.matDialog.open(dialogRef, {data : data}).afterClosed().subscribe((res)=>{
|
||
if(res.status == 200){
|
||
this.refreshData();
|
||
}
|
||
});
|
||
}
|
||
|
||
if(args.item.text === "Ablehnen" || args.item.text === "Reject"){
|
||
for (const selectedRescourceId of this.selectedRescourceIds) {
|
||
for (const change of this.resources) {
|
||
if(change.resourceId == selectedRescourceId){
|
||
this.dataService.updateApproval(change, 2).then((res: any)=>{
|
||
if(res.status == 200){
|
||
this._snackBar.open("Ablehnen erfolgreich", 'Schließen', {horizontalPosition: this.horizontalPosition,verticalPosition: this.verticalPosition, panelClass: ['green-snackbar']});
|
||
this.refreshData();
|
||
}else{
|
||
this._snackBar.open(res.HttpErrorResponse.message, 'Schließen', {horizontalPosition: this.horizontalPosition, verticalPosition: this.verticalPosition, panelClass: ['red-snackbar']});
|
||
}
|
||
});
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if(args.item.text === "stornieren" || args.item.text === "Cancel"){
|
||
for (const selectedRescourceId of this.selectedRescourceIds) {
|
||
for (const change of this.resources) {
|
||
if(change.resourceId == selectedRescourceId){
|
||
this.dataService.updateApproval(change, 3).then((res: any)=>{
|
||
if(res.status == 200){
|
||
this._snackBar.open("Stornieren erfolgreich", 'Schließen', {horizontalPosition: this.horizontalPosition, verticalPosition: this.verticalPosition, panelClass: ['mat-primary']});
|
||
this.refreshData();
|
||
}else{
|
||
this._snackBar.open(res.HttpErrorResponse.message, 'Schließen', {horizontalPosition: this.horizontalPosition, verticalPosition: this.verticalPosition, panelClass: ['mat-primary']});
|
||
}
|
||
});
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/**############################### Syncfusion Framework EVENTS /**###############################*/
|
||
|
||
/**
|
||
* The function queryTaskbarInfo catches the corresponding syncfsuions event and colors the respective diamond depending on the status
|
||
* @param args event arguments from the syncfusion gantt chart
|
||
*/
|
||
public queryTaskbarInfo(args: any) {
|
||
if (args.taskbarType == 'Milestone')
|
||
{
|
||
args.taskbarElement.children[1].classList.add('e-gantt-milestone-border');
|
||
}
|
||
|
||
if(args.data.taskData.isRes == false){
|
||
if(args.data.taskData.TaskID.includes("D2")){
|
||
args.milestoneBorder = "black";
|
||
//console.log(args.taskbarElement);
|
||
if (args.data.taskData.resources[0].state == 0 ) {
|
||
args.milestoneColor = "#f83200";
|
||
}
|
||
if (args.data.taskData.resources[0].state == 1 ) {
|
||
args.milestoneColor = "#f98700";
|
||
}
|
||
if (args.data.taskData.resources[0].state == 3 ) {
|
||
args.milestoneColor = "#f1b521";
|
||
}
|
||
if (args.data.taskData.resources[0].state == 6 ) {
|
||
args.milestoneColor = "#89c341";
|
||
}
|
||
if (args.data.taskData.resources[0].state >= 10 ) {
|
||
args.milestoneColor = "lightgrey";
|
||
}
|
||
}else{
|
||
if (args.data.taskData.TaskID.includes("D1")||args.data.taskData.TaskID.includes("D4")){
|
||
if(this.showDetails == false){
|
||
args.taskbarElement.innerHTML = "";
|
||
}else{
|
||
if(args.data.taskData.TaskID.includes("D1")){
|
||
args.milestoneColor = "#d4d4d4";
|
||
}
|
||
if(args.data.taskData.TaskID.includes("D4")){
|
||
args.milestoneColor = "#a1a1a1";
|
||
}
|
||
}
|
||
}
|
||
if (args.data.taskData.TaskID.includes("D3")){
|
||
args.milestoneColor = "#bababa";
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* The function taskbarEdited catches the corresponding syncfsuions event and cancels the user action if the isFixed flag of a task (Date) is set true.
|
||
* If the isFixed flag is false, it triggers the dataService to update the moved date.
|
||
* @param args event arguments from the syncfusion gantt chart.
|
||
*/
|
||
public taskbarEdited(args: any){
|
||
if(args.data.taskData.isFixed !== false ) {
|
||
args.cancel = true;
|
||
}else{
|
||
const found = this.allResources.find((resource) => {
|
||
return resource.resourceId == args.data.taskData.resources[0].resourceId;
|
||
});
|
||
this.dataService.updateDatePerChange(found);
|
||
this.plantimeComponent.fetchPlanTimes();
|
||
let elem = document.querySelector(
|
||
'#'+'ganttDefaultSum'+ 'GanttChart > div.e-chart-root-container > div'
|
||
);
|
||
elem.scrollLeft = this.planTimeScrollLeft;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* The function taskbarEditing catches the corresponding syncfsuions event and cancels the user action if the isFixed flag of a task (Date) is set true.
|
||
* @param args event arguments from the syncfusion gantt chart.
|
||
*/
|
||
public taskbarEditing(args: any) {
|
||
if(args.data.taskData.isFixed !== false ) {
|
||
args.cancel = true;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* The function taskbarEditing catches the corresponding syncfsuions event and executes a query operation to synchronize the scrollbars of the main gannt chart and the planTimeBart gantt chart.
|
||
* @param args event arguments from the syncfusion gantt chart.
|
||
*/
|
||
public actionComplete(args: any){
|
||
if (args.action === 'HorizontalScroll') {
|
||
let elem = document.querySelector(
|
||
'#'+'ganttDefaultSum'+ 'GanttChart > div.e-chart-root-container > div'
|
||
);
|
||
elem.scrollLeft = args.scrollLeft;
|
||
this.planTimeScrollLeft = args.scrollLeft;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* The function load catches the corresponding syncfsuions event and triggers the loading spinner to start while the gantt chart is refrehshing.
|
||
* @param args event arguments from the syncfusion gantt chart.
|
||
*/
|
||
public load(args: any) {
|
||
this.spin = true;
|
||
}
|
||
|
||
/**
|
||
* The function dataBound catches the corresponding syncfsuions event and stops the loading spinner.
|
||
* @param args event arguments from the syncfusion gantt chart.
|
||
*/
|
||
public dataBound(args: any) {
|
||
console.log(args);
|
||
this.spin = false;
|
||
if(this.sortEnabled && this.sortSelectorName){
|
||
this.selectSortedColumn(this.sortSelectorName);
|
||
}
|
||
|
||
|
||
// const headerDivs = document.querySelectorAll('.e-headercelldiv');
|
||
|
||
|
||
|
||
// // Add click event listener to each 'e-headercelldiv'
|
||
|
||
// headerDivs.forEach((div) => {
|
||
|
||
// div.addEventListener('click', function () {
|
||
|
||
// console.log('Element is clicked you can write your own custom function');
|
||
// console.log(this);
|
||
// // Remove 'selected' class from all 'e-headercell' elements
|
||
|
||
// document.querySelectorAll('.e-headercell').forEach((cell) => {
|
||
|
||
// cell.classList.remove('selected');
|
||
|
||
// });
|
||
|
||
|
||
// // Add 'selected' class to the parent 'e-headercell' of the clicked div
|
||
|
||
// this.closest('.e-headercell').classList.add('selected');
|
||
|
||
// });
|
||
|
||
// });
|
||
}
|
||
|
||
public selectSortedColumn(colName: string){
|
||
const headerDivs = document.querySelectorAll('.e-headercelldiv');
|
||
headerDivs.forEach((div) => {
|
||
console.log('############################################');
|
||
// console.log(div);
|
||
// Remove 'selected' class from all 'e-headercell' elements
|
||
|
||
// document.querySelectorAll('.e-headercell').forEach((cell) => {
|
||
// console.log(div.firstChild.textContent);
|
||
// console.log(colName);
|
||
if(div.firstChild.textContent == colName){
|
||
div.closest('.e-headercell').classList.add('selected');
|
||
console.log(div.closest('.e-headercell').children[1]);
|
||
console.log(this.sort.mode == 'asc');
|
||
if(this.sort.mode == 'asc'){
|
||
div.closest('.e-headercell').children[1].innerHTML = "<mat-icon style=\"font-family: 'Material Icons'; font-size: 15px; line-height: 1; \">arrow_downward</mat-icon>"
|
||
}else{
|
||
div.closest('.e-headercell').children[1].innerHTML = "<mat-icon style=\"font-family: 'Material Icons'; font-size: 15px; line-height: 1; \">arrow_upward</mat-icon>"
|
||
}
|
||
}else{
|
||
div.classList.remove('selected');
|
||
}
|
||
|
||
|
||
});
|
||
|
||
|
||
// Add 'selected' class to the parent 'e-headercell' of the clicked div
|
||
|
||
// this.closest('.e-headercell').classList.add('selected');
|
||
|
||
// });
|
||
// const col = document.querySelector(colName);
|
||
|
||
// console.log(col);
|
||
}
|
||
|
||
/**
|
||
* The function created catches the corresponding syncfsuions event and stops the internal loading spinner.
|
||
* @param args event arguments from the syncfusion gantt chart.
|
||
*/
|
||
public created(args: any) {
|
||
this.ganttDefault.hideSpinner();
|
||
this.ganttDefault.treeGrid.grid.hideSpinner();
|
||
}
|
||
|
||
/**
|
||
* The function onExpand catches the corresponding syncfsuions event and avoids a chart row from beeing expanded by the user.
|
||
* @param args event arguments from the syncfusion gantt chart.
|
||
*/
|
||
public onExpand(args: any){
|
||
args.cancel = true;
|
||
}
|
||
|
||
/**
|
||
* The function splitterResizing catches the corresponding syncfsuions event and stores the actual splitter postition to synchronize the splitters of the main gannt chart and the planTimeBart gantt chart.
|
||
* @param args event arguments from the syncfusion gantt chart.
|
||
*/
|
||
public splitterResizing(args) {
|
||
|
||
this.splitterSettings = {position: args.paneSize[0].toString() + 'px'};
|
||
}
|
||
|
||
/**
|
||
* The function actionBegin catches the corresponding syncfsuions event applies a sort by the selected column and refrehses the gantt chart or opens the Change Package direktly in Remedy if the user doubleclicks on a main date.
|
||
* @param args event arguments from the syncfusion gantt chart.
|
||
*/
|
||
public actionBegin(args: any) {
|
||
if(args.dialogModel){
|
||
args.cancel = true;
|
||
if(args.rowData.taskData.resources[0].state == 0){
|
||
window.open("https://itsm-dev.asfinag.at/arsys/forms/itsm-app-dev/SHR%3ALandingConsole/Default+Administrator+View/?mode=search&F304255500=ASF:WI_TAS_Paket&F1000000076=FormOpenNoAppList&F303647600=SearchTicketWithQual&F304255610='1000000182' =\""+args.rowData.taskData.resources[0].changeNr+"\"", "_blank");
|
||
}else{
|
||
window.open("https://itsm-dev.asfinag.at/arsys/forms/itsm-app-dev/SHR%3ALandingConsole/Default+Administrator+View/?mode=search&F304255500=CHG:Infrastructure Change&F1000000076=FormOpenNoAppList&F303647600=SearchTicketWithQual&F304255610='1000000182' =\""+args.rowData.taskData.resources[0].changeNr+"\"", "_blank");
|
||
}
|
||
}else{
|
||
console.log(args.target.firstChild.innerText);
|
||
if(args.requestType=='sorting'){
|
||
let colName = "";
|
||
let mode = "asc";
|
||
args.cancel = true;
|
||
|
||
switch (args.columnName) {
|
||
case 'TaskName':
|
||
colName = 'ResourceName';
|
||
break;
|
||
case 'stateName':
|
||
colName = 'State';
|
||
break;
|
||
case 'supportGroup':
|
||
colName = 'SupportGroup';
|
||
break;
|
||
case 'approvalStatus':
|
||
colName = 'ApprovalStatus';
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
if(colName != ''){
|
||
this.sortSelectorName = args.target.firstChild.innerText;
|
||
this.sortEnabled = true;
|
||
if(this.oldSort != null && this.oldSort.column == this.sort.column){
|
||
mode = 'dsc';
|
||
}
|
||
if(this.sort == null){
|
||
this.sort = {'column': colName, 'mode': mode}
|
||
this.oldSort = this.sort;
|
||
}else{
|
||
this.oldSort = this.sort;
|
||
this.sort = {'column': colName, 'mode': mode}
|
||
}
|
||
|
||
|
||
if(this.oldSort != null && this.oldSort.mode == 'dsc'){
|
||
this.sort = null;
|
||
this.oldSort = null;
|
||
this.sortEnabled = false;
|
||
this.sortSelectorName = null;
|
||
}
|
||
this.oldSort;
|
||
this.sort;
|
||
this.refreshData();
|
||
}else{
|
||
this.sortSelectorName = null;
|
||
args.cancel = true;
|
||
|
||
}
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
/**
|
||
* The function rowSelected catches the corresponding syncfsuions event and checks if all selected resources (changes) have the same status, then it displays the corresponding buttons
|
||
* @param args event arguments from the syncfusion gantt chart
|
||
*/
|
||
public rowSelected(args: any) {
|
||
this.approvalPending = false;
|
||
this.selectedrowindex = this.ganttDefault.selectionModule.getSelectedRowIndexes(); // get the selected row indexes.
|
||
this.selectedrecords = this.ganttDefault.selectionModule.getSelectedRecords(); // get the selected records.
|
||
this.selRecs=[];
|
||
if(this.selectedrowindex.length>this.resources.length-1){
|
||
for (const record of this.selectedrecords) {
|
||
if(record.taskData.isRes == true){
|
||
this.selRecs.push(record);
|
||
}
|
||
}
|
||
}else{
|
||
this.selRecs = this.selectedrecords;
|
||
}
|
||
let allStates: boolean = true;
|
||
let allPermit: boolean = true;
|
||
let allApprove: boolean = true;
|
||
let allReject: boolean = true;
|
||
let allCancel: boolean = true;
|
||
let allImplementer: boolean = true;
|
||
let allTransition: boolean = true;
|
||
this.selectedRescourceIds = [];
|
||
for (const change of this.selRecs) {
|
||
if(change.taskData.approvalStatus == 1){
|
||
this.approvalPending = true;
|
||
}
|
||
if(change.taskData.state == this.selRecs[0].taskData.state){
|
||
if(allStates){
|
||
allStates = true;
|
||
}
|
||
else{
|
||
allStates = false;
|
||
}
|
||
this.selectedRescourceIds.push(change.taskData.resourceId);
|
||
}else{
|
||
allStates = false;
|
||
}
|
||
if(change.taskData.flagPermit == true && allPermit == true){
|
||
allPermit = true;
|
||
}else{
|
||
allPermit = false;
|
||
}
|
||
if(change.taskData.flagApproval == true && allApprove == true){
|
||
allApprove = true;
|
||
}else{
|
||
allApprove = false;
|
||
}
|
||
if(change.taskData.flagReject == true && allReject == true){
|
||
allReject = true;
|
||
}else{
|
||
allReject = false;
|
||
}
|
||
if(change.taskData.flagCancel == true && allCancel == true){
|
||
allCancel = true;
|
||
}else{
|
||
allCancel = false;
|
||
}
|
||
if(change.taskData.implementerEdit == true && allImplementer == true){
|
||
allImplementer = true;
|
||
}else{
|
||
allImplementer = false;
|
||
}
|
||
if(change.taskData.state > 0 && allTransition == true){
|
||
allTransition = true;
|
||
}else{
|
||
allTransition = false;
|
||
}
|
||
}
|
||
|
||
if(allStates){
|
||
this.toolbar = [];
|
||
if(allTransition && !this.approvalPending){
|
||
this.toolbar.push({text:this.languageService.lMap.get("stateChange"), id: "6"});
|
||
}
|
||
if(allPermit){
|
||
this.toolbar.push({text: this.languageService.lMap.get("permit"), id: "5"});
|
||
}
|
||
if(allApprove){
|
||
this.toolbar.push({text: this.languageService.lMap.get("genehmigen"), id: "7"});
|
||
}
|
||
if(allReject){
|
||
this.toolbar.push({text: this.languageService.lMap.get("ablehnen"), id: "8"});
|
||
}
|
||
if(allCancel){
|
||
this.toolbar.push({text: this.languageService.lMap.get("stornieren"), id: "11"});
|
||
}
|
||
if(allImplementer){
|
||
this.toolbar.push({text: this.languageService.lMap.get("implementer"), id: "10"});
|
||
}
|
||
|
||
}else{
|
||
this.toolbar = [];
|
||
}
|
||
this.approvalPending = false;
|
||
this.selRecs = [];
|
||
this.selectedrecords = [];
|
||
this.selectedrowindex = [];
|
||
}
|
||
|
||
/**
|
||
* The function rowDeselected catches the corresponding syncfsuions event
|
||
* When a line is deselected, it is checked if all resource states are equal after deselecting a resource, if they are equal then the respective buttons are displayed
|
||
* @param args event arguments from the syncfusion gantt chart
|
||
*/
|
||
public rowDeselected(args: any){
|
||
this.selectedRescourceIds.forEach((element,index)=>{
|
||
if(element == args.data.taskData.resourceId) delete this.selectedRescourceIds[index]; //TODO: auf memoryLeak prüfen
|
||
});
|
||
|
||
this.selectedrowindex= this.ganttDefault.selectionModule.getSelectedRowIndexes(); // get the selected row indexes.
|
||
this.selectedrecords= this.ganttDefault.selectionModule.getSelectedRecords(); // get the selected records.
|
||
this.selRecs = [];
|
||
if(this.selectedrowindex.length>this.resources.length-1){
|
||
for (const record of this.selectedrecords) {
|
||
if(record.taskData.isRes == true){
|
||
this.selRecs.push(record);
|
||
}
|
||
}
|
||
}else{
|
||
this.selRecs = this.selectedrecords;
|
||
}
|
||
let allStates: boolean = true;
|
||
let allPermit: boolean = true;
|
||
let allApprove: boolean = true;
|
||
let allReject: boolean = true;
|
||
let allCancel: boolean = true;
|
||
let allImplementer: boolean = true;
|
||
let allTransition: boolean = true;
|
||
this.selectedRescourceIds = [];
|
||
for (const change of this.selRecs) {
|
||
if(change.taskData.state == this.selRecs[0].taskData.state){
|
||
if(change.taskData.approvalStatus == 1){
|
||
this.approvalPending = true;
|
||
}
|
||
if(allStates){
|
||
allStates = true;
|
||
}
|
||
this.selectedRescourceIds.push(change.taskData.resourceId);
|
||
}else{
|
||
allStates = false;
|
||
}
|
||
if(change.taskData.flagPermit == true && allPermit == true){
|
||
allPermit = true;
|
||
}else{
|
||
allPermit = false;
|
||
}
|
||
if(change.taskData.flagApproval == true && allApprove == true){
|
||
allApprove = true;
|
||
}else{
|
||
allApprove = false;
|
||
}
|
||
if(change.taskData.flagReject == true && allReject == true){
|
||
allReject = true;
|
||
}else{
|
||
allReject = false;
|
||
}
|
||
if(change.taskData.flagCancel == true && allCancel == true){
|
||
allCancel = true;
|
||
}else{
|
||
allCancel = false;
|
||
}
|
||
if(change.taskData.implementerEdit == true && allImplementer == true){
|
||
allImplementer = true;
|
||
}else{
|
||
allImplementer = false;
|
||
}
|
||
if(change.taskData.state > 0 && allTransition == true){
|
||
allTransition = true;
|
||
}else{
|
||
allTransition = false;
|
||
}
|
||
|
||
}
|
||
if(allStates){
|
||
this.toolbar = [];
|
||
if(allTransition&&!this.approvalPending){
|
||
this.toolbar.push({text:this.languageService.lMap.get("stateChange"), id: "6"});
|
||
}
|
||
if(allPermit){
|
||
this.toolbar.push({text: this.languageService.lMap.get("permit"), id: "5"});
|
||
}
|
||
if(allApprove){
|
||
this.toolbar.push({text: this.languageService.lMap.get("genehmigen"), id: "7"});
|
||
}
|
||
if(allReject){
|
||
this.toolbar.push({text: this.languageService.lMap.get("ablehnen"), id: "8"});
|
||
}
|
||
if(allCancel){
|
||
this.toolbar.push({text: this.languageService.lMap.get("stornieren"), id: "11"});
|
||
}
|
||
if(allImplementer){
|
||
this.toolbar.push({text: this.languageService.lMap.get("implementer"), id: "10"});
|
||
}
|
||
}else{
|
||
this.toolbar = [];
|
||
}
|
||
this.selRecs = [];
|
||
this.selectedrecords = [];
|
||
this.selectedrowindex = [];
|
||
this.approvalPending = false;
|
||
}
|
||
}
|