diff --git a/frontend/package.json b/frontend/package.json index f14e1e4..0788022 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -7,7 +7,7 @@ "build": "ng build", "watch": "ng build --watch --configuration development", "test": "ng test", - "compdoc": "npx compodoc -p tsconfig.app.json -s -w -r 9090" + "compodoc": "npx compodoc -p tsconfig.doc.json" }, "private": true, "dependencies": { diff --git a/frontend/src/app/app.component.ts b/frontend/src/app/app.component.ts index a211689..d49f78d 100644 --- a/frontend/src/app/app.component.ts +++ b/frontend/src/app/app.component.ts @@ -8,7 +8,9 @@ import { Component, ViewEncapsulation, OnInit, ViewChild } from '@angular/core'; }) - +/** +* The AppComponent is just a container for the NTTGanttComponent +*/ export class AppComponent { constructor() {} diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts index 24c7b6a..bf33ddb 100644 --- a/frontend/src/app/app.module.ts +++ b/frontend/src/app/app.module.ts @@ -26,7 +26,7 @@ import { ImplementerDialogComponent } from './implementer-dialog/implementer-dia import {MatExpansionModule} from '@angular/material/expansion'; import {MatInputModule} from '@angular/material/input'; import {MatCheckboxModule} from '@angular/material/checkbox'; -import { FilterComponentComponent } from './filter-component/filter-component.component'; + import {MatAutocompleteModule} from '@angular/material/autocomplete'; import { MultiselectAutocompleteComponent } from './multiselect-autocomplete/multiselect-autocomplete.component'; import {MatChipsModule} from '@angular/material/chips'; @@ -42,7 +42,6 @@ import { PlanTimeBarComponent } from './plan-time-bar/plan-time-bar.component'; NttGanttComponent, StateDialogComponent, ImplementerDialogComponent, - FilterComponentComponent, MultiselectAutocompleteComponent, FilterDialogComponent, PlanTimeBarComponent diff --git a/frontend/src/app/data.service.ts b/frontend/src/app/data.service.ts index 6bb2c3c..44d32e8 100644 --- a/frontend/src/app/data.service.ts +++ b/frontend/src/app/data.service.ts @@ -4,16 +4,14 @@ import { Injectable } from '@angular/core'; import { ResourceFields } from '@syncfusion/ej2-angular-gantt'; import { LanguageService } from './language.service'; - @Injectable({ providedIn: 'root' }) - /** - *The DataService manages the communication between Frontend and Backend, fetches Data from the Backend and maps it to the Frontend Data Structure. Additionally it updates data on the Backend. - * - */ +* The DataService manages the communication between Frontend and Backend, fetches Data from the Backend and maps it to the Frontend Data Structure. Additionally it updates data on the Backend. +* +*/ export class DataService { private states: any []; //Array of statuses and possible statuses, which is queried once at the beginning by backend and stored in dataservice private supportGroups: any []; @@ -21,11 +19,13 @@ export class DataService { private paketTypes: any []; private totalSize: number = null; public userSupportGroup: string; - //public selectedLanguage: string = 'DE'; + //public selectedLanguage: string = 'DE'; + /** - * This constructor builds the dataService and fetches the states from the backend - * @param http - */ + * This constructor builds the dataService and fetches the states from the backend + * @param languageService injection of the languageService + * @param http representation of the HttpClient + */ constructor(public languageService: LanguageService, private http: HttpClient) { this.fetchStates().then((res: any [])=>{ this.states = res; @@ -46,33 +46,78 @@ export class DataService { }); } -/** - * - * @returns an array of states and possible states per state - */ + /** + * the function getStates + * @returns an array of states and possible states per state + */ public getStates():any[]{ return this.states; } + /** + * the function getSupportGroups + * @returns an array of all supportGroups + */ public getSupportGroups():any[]{ return this.supportGroups; } + /** + * the function getContracts + * @returns an array of all contracts + */ public getContracts():any[]{ return this.contracts; } + /** + * the function getPaketTypes + * @returns an array of all paketTypes + */ public getPaketTypes():any[]{ return this.paketTypes; } + /** + * the function getTotalSize + * @returns the size of all changes, that are matched by the actual filters + * required for totalSize attribute of the paginator + */ public getTotalSize():number{ return this.totalSize; } + /** + * the function getUserSupportGroup + * @returns the supportGroup of the actual user + */ public getUserSupportGroup():string{ return this.userSupportGroup; } + + /** + * the function getStateIdByName translates the name of a state into the id + * @param stateName name of the state + * @returns id of the state + */ + public getStateIdByName(stateName: string): number { + for (let state of this.states) { + if(stateName == state.stateNameEN){ + return state.id; + } + } + return -1; + } + + /** + * the function getContractByName searches a contract by its uid and returns the name + * @param contractId uid to search the contract + * @returns the name of the corresponding contract + */ + public getContractName(contractId: string): string{ + return this.contracts.find((contract)=> {return contract.id == contractId;}).name; + } + /** * The function fetchStates fetches an array from the possible statuses per state * @returns promise for the fetched Status Array @@ -91,6 +136,10 @@ export class DataService { return promise; } + /** + * The function fetchSupportGroups fetches an array of all supportGroups + * @returns promise for the fetched supportGroups array + */ public async fetchSupportGroups(){ const promise = new Promise(resolve=>{ let res : any[] = []; @@ -105,6 +154,10 @@ export class DataService { return promise; } + /** + * The function fetchContracts fetches an array of all contracts + * @returns promise for the fetched contracts array + */ public async fetchContracts(){ const promise = new Promise(resolve=>{ let res : any[] = []; @@ -119,6 +172,10 @@ export class DataService { return promise; } + /** + * The function fetchPaketTypes fetches an array of all paketTypes + * @returns promise for the fetched paketTypes array + */ public async fetchPaketTypes(){ const promise = new Promise(resolve=>{ let res : any[] = []; @@ -133,6 +190,10 @@ export class DataService { return promise; } + /** + * The function fetchPaketTypes fetches the supportGroup of the current user + * @returns promise for the fetched current user supportGroup + */ public async fetchUserSupportGroup(){ const promise = new Promise(resolve=>{ let res : any = {}; @@ -146,76 +207,13 @@ export class DataService { return promise; } -/** - * The function updateDatePerChange sends the new date to the backend if the date was moved - * @param change the Change (the Resource) from which the date should be changed - */ - public async updateDatePerChange(change: any){ - // //console.log(change); - // let serializableResource = { resourceId: change.resourceId, d2: change.tasks[1].StartDate, changeNr: change.changeNr, state: change.state}; - // let strigifiedResource = JSON.stringify(serializableResource); - // let resJson = JSON.parse(strigifiedResource) as typeof strigifiedResource; - // // console.log(resJson); - // this.http.post('http://localhost:8080/api/updateChange', resJson).toPromise().then((value)=>{ - // console.log(value); - // }); - const promise = new Promise(resolve=>{ - let serializableResource = { resourceId: change.resourceId, d2: change.tasks[1].StartDate, changeNr: change.changeNr, state: change.state}; - let strigifiedResource = JSON.stringify(serializableResource); - let resJson = JSON.parse(strigifiedResource) as typeof strigifiedResource; - // console.log(dataJson); - this.http.post('http://localhost:8080/api/updateChange', resJson).subscribe((response:any)=>{ - resolve(response); - },(error:any)=>{ - resolve(error); - }); - }); - - return promise; - - - - } - -/** - * The function updateStatePerChange performs a status transition on the backend - * @param change The Change for which the status transition is to be performed - * @returns a Promise - */ - public async updateStatePerChange(change: any){ - const promise = new Promise(resolve=>{ - let obj = {changeNr : change.changeNr, currentState : change.currentState, nextState : change.nextState}; - let stringyfiedData = JSON.stringify(obj); - let dataJson = JSON.parse(stringyfiedData) as typeof stringyfiedData; - // console.log(dataJson); - this.http.post('http://localhost:8080/api/updateState', dataJson).subscribe((response:any)=>{ - resolve(response); - },(error:any)=>{ - resolve(error); - }); - }); - - return promise; - } - - public async updateImplementerPerChange(change: any){ - const promise = new Promise(resolve=>{ - // console.log(change); - let obj = {pkgId : change.resourceId, loginId : change.loginId}; - let stringyfiedData = JSON.stringify(obj); - let dataJson = JSON.parse(stringyfiedData) as typeof stringyfiedData; - // console.log(dataJson); - this.http.post('http://localhost:8080/api/updateImplementer', dataJson).subscribe((response:any)=>{ - resolve(response); - },(error:any)=>{ - console.log(error); - resolve(error); - }); - }) - - return promise; - } - + /** + * The function fetchPlanTimes fetches the plan times per week from the backend + * @param filters current applied filters for the planTime calculation + * @param renderStartDate startDate of the current gantt chart (first week rendered) + * @param renderEndtDate startDate of the current gantt chart (last week rendered) + * @returns a promise for the response + */ public async fetchPlanTimes(filters: any, renderStartDate: Date, renderEndtDate: Date){ const promise = new Promise(resolve=>{ let obj = {filter : filters.filter, renderStartDate : renderStartDate, renderEndDate: renderEndtDate }; @@ -234,6 +232,11 @@ export class DataService { return promise; } + /** + * The function fetchImplementers fetches an array of all implementers of the supportGoup from a specific change + * @param change change, for which the possible implementers should be fetched + * @returns promise for the fetched implementers array + */ public async fetchImplementers(change: any){ const promise = new Promise(resolve=>{ let obj = {entryId : change.resourceId, supportGroup : change.supportGroupId}; @@ -252,6 +255,73 @@ export class DataService { return promise; } + /** + * The function updateDatePerChange sends the new date to the backend if the date was moved + * @param change the Change (the Resource) from which the date should be changed + */ + public async updateDatePerChange(change: any){ + const promise = new Promise(resolve=>{ + let serializableResource = { resourceId: change.resourceId, d2: change.tasks[1].StartDate, changeNr: change.changeNr, state: change.state}; + let strigifiedResource = JSON.stringify(serializableResource); + let resJson = JSON.parse(strigifiedResource) as typeof strigifiedResource; + this.http.post('http://localhost:8080/api/updateChange', resJson).subscribe((response:any)=>{ + resolve(response); + },(error:any)=>{ + resolve(error); + }); + }); + return promise; + } + + /** + * The function updateStatePerChange performs a status transition on the backend + * @param change the change for which the status transition is to be performed + * @returns a aromise for the response + */ + public async updateStatePerChange(change: any){ + const promise = new Promise(resolve=>{ + let obj = {changeNr : change.changeNr, currentState : change.currentState, nextState : change.nextState}; + let stringyfiedData = JSON.stringify(obj); + let dataJson = JSON.parse(stringyfiedData) as typeof stringyfiedData; + // console.log(dataJson); + this.http.post('http://localhost:8080/api/updateState', dataJson).subscribe((response:any)=>{ + resolve(response); + },(error:any)=>{ + resolve(error); + }); + }); + + return promise; + } + + /** + * The function updateImplementerPerChange updates the implementer for a specific change on the backend + * @param data the change for which the implementer update is to be performed and the loginId of the implementer + * @returns a promise for the response + */ + public async updateImplementerPerChange(data: any){ + const promise = new Promise(resolve=>{ + // console.log(change); + let obj = {pkgId : data.resourceId, loginId : data.loginId}; + let stringyfiedData = JSON.stringify(obj); + let dataJson = JSON.parse(stringyfiedData) as typeof stringyfiedData; + // console.log(dataJson); + this.http.post('http://localhost:8080/api/updateImplementer', dataJson).subscribe((response:any)=>{ + resolve(response); + },(error:any)=>{ + console.log(error); + resolve(error); + }); + }) + + return promise; + } + + /** + * The function updateApproval updates the approvalStatus for a specific change on the backend + * @param change concerning change + * @returns a promise for the response + */ public async updateApproval(change: any, approvalAction){ const promise = new Promise(resolve=>{ let obj = {changeNr : change.changeNr, approvalAction: approvalAction}; @@ -272,12 +342,10 @@ export class DataService { /** - * The function fetchChanges fetches the changes from backend and maps them to a structure that the Gannt component can interpret - * @returns promise for the fetched Changes Array - */ + * The function fetchChanges fetches the changes from backend and maps them to a structure that the Gannt component can interpret + * @returns promise for the fetched Changes Array + */ public async fetchChanges(reqestParams: any = null){ - - // let filter = {'filterElement': [reqestParams]}; let stringyfiedData = JSON.stringify(reqestParams); let dataJson = JSON.parse(stringyfiedData) as typeof stringyfiedData; const promise = new Promise(resolve=>{ @@ -367,8 +435,12 @@ export class DataService { return promise; } - - validateImplementerEdit(state):boolean{ + /** + * The function validateImplementerEdit validates if a change is in a state where its implementer can be updated + * @param state state of the concerning change + * @returns true or false for a boolean flag + */ + private validateImplementerEdit(state):boolean{ if(state == 1 || state == 3 || state == 6){ return true; }else{ @@ -376,14 +448,25 @@ export class DataService { } } - validateCancel(state):boolean{ + /** + * The function validateCancel validates if a change is in a state where it can be canceld + * @param state state of the concerning change + * @returns true or false for a boolean flag + */ + private validateCancel(state):boolean{ if(state == 1){ return true }else{ return false } } - validatePermit(state): boolean{ + + /** + * The function validatePermit validates if a change is in a state where it can be permited + * @param state state of the concerning change + * @returns true or false for a boolean flag + */ + private validatePermit(state): boolean{ if(state == 0){ return true }else{ @@ -391,7 +474,12 @@ export class DataService { } } - validateApproval(approval):boolean{ + /** + * The function validatePermit validates if a change has an active approval + * @param state approvalString + * @returns true or false for a boolean flag + */ + private validateApproval(approval):boolean{ if(approval!=""){ return true; }else{ @@ -399,8 +487,12 @@ export class DataService { } } - - getStateNameById(stateNr): String { + /** + * The function getStateNameById searches the name of a status by its id, depending on the set language + * @param stateNr state number (uid) + * @returns string with the stateName + */ + public getStateNameById(stateNr): String { if(this.languageService.language == 'EN'){ for (let state of this.states) { if(stateNr == state.actualState){ @@ -417,20 +509,6 @@ export class DataService { } return ""; } - - getStateIdByName(stateName: string): number { - for (let state of this.states) { - if(stateName == state.stateNameEN){ - return state.id; - } - } - return -1; - } - - getContractName(contractId: string): string{ - return this.contracts.find((contract)=> {return contract.id == contractId;}).name; - } - } diff --git a/frontend/src/app/filter-component/filter-component.component.css b/frontend/src/app/filter-component/filter-component.component.css deleted file mode 100644 index d514949..0000000 --- a/frontend/src/app/filter-component/filter-component.component.css +++ /dev/null @@ -1,7 +0,0 @@ -.full-width { - width: 100%; -} -​ -.chip-list-wrapper { - min-height: 3em; -} diff --git a/frontend/src/app/filter-component/filter-component.component.html b/frontend/src/app/filter-component/filter-component.component.html deleted file mode 100644 index c5f5ad3..0000000 --- a/frontend/src/app/filter-component/filter-component.component.html +++ /dev/null @@ -1,8 +0,0 @@ -

{{name}}

- - - diff --git a/frontend/src/app/filter-component/filter-component.component.spec.ts b/frontend/src/app/filter-component/filter-component.component.spec.ts deleted file mode 100644 index f3f1871..0000000 --- a/frontend/src/app/filter-component/filter-component.component.spec.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { FilterComponentComponent } from './filter-component.component'; - -describe('FilterComponentComponent', () => { - let component: FilterComponentComponent; - let fixture: ComponentFixture; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ FilterComponentComponent ] - }) - .compileComponents(); - - fixture = TestBed.createComponent(FilterComponentComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/frontend/src/app/filter-component/filter-component.component.ts b/frontend/src/app/filter-component/filter-component.component.ts deleted file mode 100644 index aa7633b..0000000 --- a/frontend/src/app/filter-component/filter-component.component.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; - - -export interface filterItem { - item: string; - selected: boolean; -} - -@Component({ - selector: 'app-filter-component', - templateUrl: './filter-component.component.html', - styleUrls: ['./filter-component.component.css'] -}) - - - -export class FilterComponentComponent implements OnInit { -@Input() data: any[]=[]; -@Input() name: string = ""; -@Input() shortName: string = ""; -@Input() filterType: string = ""; -@Output() result = new EventEmitter(); - filterValue: any = { - options: [] - }; - - cardSelects = [ - - ] - - selectOptions: Array=[]; - - constructor(){ - - - } - ngOnInit(): void { - console.log(this.data); - for (const attr of this.data) { - this.selectOptions.push(attr.name); - } - } - - selectChange = (event: any) => { - const key: string = event.key; - this.filterValue[key] = [event.data]; - let returnData = []; - for (const attr of this.filterValue.output[0]) { - for (const att of this.data) { - if(attr.name == att.name){ - returnData.push(attr); - } - } - } - // this.result.emit({filterType: this.filterType, data: returnData}); - this.result.emit('Hallo'); - console.log(this.filterValue.output[0]); - }; - -} diff --git a/frontend/src/app/filter-dialog/filter-dialog.component.html b/frontend/src/app/filter-dialog/filter-dialog.component.html index a91de1e..fab1a3a 100644 --- a/frontend/src/app/filter-dialog/filter-dialog.component.html +++ b/frontend/src/app/filter-dialog/filter-dialog.component.html @@ -53,4 +53,4 @@

- + diff --git a/frontend/src/app/filter-dialog/filter-dialog.component.ts b/frontend/src/app/filter-dialog/filter-dialog.component.ts index 3615265..57d0744 100644 --- a/frontend/src/app/filter-dialog/filter-dialog.component.ts +++ b/frontend/src/app/filter-dialog/filter-dialog.component.ts @@ -4,6 +4,7 @@ import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; import { MatSnackBar } from '@angular/material/snack-bar'; import { DataService } from '../data.service'; import { MAT_DATE_FORMATS } from '@angular/material/core' + export interface FilterAttribute{ name: string, } @@ -29,42 +30,44 @@ export const MY_DATE_FORMATS = { ] }) +/** +* The ImplementerDialogComponent displays a dialog with all filter options +*/ export class FilterDialogComponent implements OnInit { + public supportGroups: string[] = []; + public paketTypes: string[] = []; + public states: string[] = []; + public contracts: string[] = []; + public userSupportGroup: string; - /** - * The constructor injects required Dependencies and sets default values for logic and ui - * @param dialogRef MatDialog Reference from Angular - * @param data contains an array of Changes which should be sent to the backend for a status transition - * @param dataService injects the dataService for data management and backend communication - */ + public criteria: string; + public filterStartDate: Date; + public filterEndDate: Date; - public supportGroups: string[] = []; - public paketTypes: string[] = []; - public states: string[] = []; - public contracts: string[] = []; - public userSupportGroup: string; + public supportGroupsFilter = []; + public paketTypesFilter = []; + public statesFilter = []; + public contractsFilter = []; + public textFilter = []; + public dateFilter = []; + public filterLabels: string[] = []; + public filterObj; - public criteria: string; - public filterStartDate: Date; - public filterEndDate: Date; + /** + * The constructor injects required Dependencies and sets default values for logic and ui + * @param languageService representation of the LanguageService + * @param dialogRef MatDialog Reference from Angular + * @param data contains an array of Changes which should be sent to the backend for a status transition + * @param dataService injects the dataService for data management and backend communication + */ + constructor(public languageService: LanguageService, public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: any, private dataService: DataService, private _snackBar: MatSnackBar) { + //dialogRef.beforeClosed().subscribe(() => dialogRef.close(this.dataToReturn)); + } - public supportGroupsFilter = []; - public paketTypesFilter = []; - public statesFilter = []; - public contractsFilter = []; - public textFilter = []; - public dateFilter = []; - public filterLabels: string[] = []; - - public filterObj; - - - - constructor(public languageService: LanguageService, public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: any, private dataService: DataService, private _snackBar: MatSnackBar) { - //dialogRef.beforeClosed().subscribe(() => dialogRef.close(this.dataToReturn)); - } - - ngOnInit(): void { + /** + * The function ngOnInit initialized the component by fetching all relevant data via the dataService + */ + ngOnInit(): void { this.dataService.fetchUserSupportGroup().then((res:any)=>{ this.userSupportGroup = res.name; }); @@ -88,23 +91,20 @@ export class FilterDialogComponent implements OnInit { for (const paketType of this.dataService.getPaketTypes()) { this.paketTypes.push(paketType.name); } - } + } - onResult(event: any) { + /** + * The function onResult gets the result (selection) from the multiselect-autocomplete-component, + * evaluates, which filter was selected and maps it to a list + * @param event selection event from the multiselect-autocomplete-component + */ + onResult(event: any) { console.log(event); switch (event.key) { case 'supportGroup': this.supportGroupsFilter = event.data; - // console.log(event.data); - // for (const sg of event.data) { - // if(this.dataService.getSupportGroups().find((item)=> {return item.name == sg;})){ - // this.supportGroupsFilter.push(this.dataService.getSupportGroups().find((item)=> {return item.name == sg;}).id); - // } - // console.log(this.supportGroupsFilter); - // } break; case 'state': - // this.statesFilter = event.data; if(this.languageService.language == 'DE'){ console.log(event.data); for (const state of event.data) { @@ -148,9 +148,12 @@ export class FilterDialogComponent implements OnInit { break; } - } + } - applyFilter(){ + /** + * The function mapFilter builds a filterElement out of all the selected filters, delivers it back and closes the dialog + */ + mapFilter(){ let filterElement = [] if(this.paketTypesFilter.length > 0){ filterElement.push({ @@ -160,8 +163,6 @@ export class FilterDialogComponent implements OnInit { }); } - - if(this.statesFilter.length > 0){ filterElement.push({ "column": "State", @@ -193,7 +194,6 @@ export class FilterDialogComponent implements OnInit { }); } - if(this.filterStartDate != null && this.filterEndDate != null){ filterElement.push({ "column": "D2", @@ -209,10 +209,9 @@ export class FilterDialogComponent implements OnInit {       "criteria": [this.criteria] }); } + let filter = {filterElement: filterElement}; console.log(filter); this.dialogRef.close(filter); - - - } + } } diff --git a/frontend/src/app/implementer-dialog/implementer-dialog.component.ts b/frontend/src/app/implementer-dialog/implementer-dialog.component.ts index 84153c2..06c9c7f 100644 --- a/frontend/src/app/implementer-dialog/implementer-dialog.component.ts +++ b/frontend/src/app/implementer-dialog/implementer-dialog.component.ts @@ -14,6 +14,10 @@ import { LanguageService } from '../language.service'; templateUrl: './implementer-dialog.component.html', styleUrls: ['./implementer-dialog.component.css'] }) + +/** +* The ImplementerDialogComponent displays a dialog to change the implementer of a change +*/ export class ImplementerDialogComponent implements OnInit { @@ -36,114 +40,101 @@ export class ImplementerDialogComponent implements OnInit { * @param data contains an array of Changes which should be sent to the backend for a status transition * @param dataService injects the dataService for data management and backend communication */ - constructor(public languageService: LanguageService, private dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: any,private dataService: DataService, private _snackBar: MatSnackBar) { - this.progress = 0; - this.bdiasbled = true; - this.diasbled = false; - this.selectedValue = -1; - this.possibleImplementers = []; - } - -/** -* The function ngOnInit checks in which actual State the selected changes are, then it provides a list that contains which statuses can be switched to in the current state -*/ - ngOnInit(): void { - console.log(this.data.changes[0]); - this.dataService.fetchImplementers(this.data.changes[0]).then((res: any)=>{ - this.implementers = res; - console.log(this.implementers); + constructor(public languageService: LanguageService, private dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: any,private dataService: DataService, private _snackBar: MatSnackBar) { + this.progress = 0; + this.bdiasbled = true; + this.diasbled = false; + this.selectedValue = -1; this.possibleImplementers = []; - if(this.implementers.length>0){ - for (const implementer of this.implementers) { - this.possibleImplementers.push({value: implementer.loginId, viewValue: implementer.memberName}); - } - }else{ - this.dialogRef.close(); - } - }).catch((error)=>{ - - }); - - // MOCK: -// this.implementers = [{name: "Manuel Tauber", loginId: "MT01"}, {name: "Julius Sula", loginId: "MT02"}, {name: "Said Gedik", loginId: "MT03"}]; -// console.log(this.implementers); -// this.possibleImplementers = []; -// if(this.implementers.length>0){ -// for (const implementer of this.implementers) { -// this.possibleImplementers.push({value: implementer.loginId, viewValue: implementer.name}); -// } -// }else{ -// this.dialogRef.close(); -// } } - /** + /** + * The function ngOnInit checks in which actual State the selected changes are, then it provides a list that contains which statuses can be switched to in the current state + */ + ngOnInit(): void { + console.log(this.data.changes[0]); + this.dataService.fetchImplementers(this.data.changes[0]).then((res: any)=>{ + this.implementers = res; + console.log(this.implementers); + this.possibleImplementers = []; + if(this.implementers.length>0){ + for (const implementer of this.implementers) { + this.possibleImplementers.push({value: implementer.loginId, viewValue: implementer.memberName}); + } + }else{ + this.dialogRef.close(); + } + }).catch((error)=>{ + + }); + } + + /** * The function enableButton is triggered by the selction event of a possible state by the user it anebles the execution button */ - enableButton():void{ - this.bdiasbled = false; - } + enableButton():void{ + this.bdiasbled = false; + } - /** + /** * The function updateState uses the dataService to execute a status transition on the backend. It sends the Changes to the backend one-by-one and calculates the percent-progress value for the progress bar. */ - updateImplementer(): void{ - let counter : number = 0; - if(this.selectedValue != -1){ - for (let change of this.data.changes){ - this.dataService.updateImplementerPerChange({resourceId: change.pkgId, loginId: this.selectedValue}).then((res: any)=>{ - this.diasbled = true; - this.bdiasbled = true; - console.log(res); - if(res.status == 200){ - counter++; - this.progress = (counter/this.data.changes.length)*100; - } - if(res.status == 500){ - let msg; - let action; - if(this.languageService.language == 'DE'){ - msg = 'Implementer Eintragung fehlgeschlagen'; - action ='Schließen'; - }else{ - msg = 'Implementer Update failed'; - action ='close'; + updateImplementer(): void{ + let counter : number = 0; + if(this.selectedValue != -1){ + for (let change of this.data.changes){ + this.dataService.updateImplementerPerChange({resourceId: change.pkgId, loginId: this.selectedValue}).then((res: any)=>{ + this.diasbled = true; + this.bdiasbled = true; + console.log(res); + if(res.status == 200){ + counter++; + this.progress = (counter/this.data.changes.length)*100; } - this._snackBar.open(msg+" : "+res.error.message, action, { - horizontalPosition: this.horizontalPosition, - verticalPosition: this.verticalPosition, - panelClass: ['mat-primary'] - }).onAction().subscribe(() => { - console.log('The snackbar action was triggered!'); - }); - this.dialogRef.close(); - //this.dialogRef.close(); - //counter++; - //this.progress = (counter/this.data.changes.length)*100; - } - - if(this.progress == 100){ - this.diasbled = false; - this.bdiasbled = true; - let msg; - let action; - if(this.languageService.language == 'DE'){ - msg = 'Implementer Eintragung erfolgreich'; - action ='Schließen'; - }else{ - msg = 'Implementer Update successful'; - action ='close'; + if(res.status == 500){ + let msg; + let action; + if(this.languageService.language == 'DE'){ + msg = 'Implementer Eintragung fehlgeschlagen'; + action ='Schließen'; + }else{ + msg = 'Implementer Update failed'; + action ='close'; + } + this._snackBar.open(msg+" : "+res.error.message, action, { + horizontalPosition: this.horizontalPosition, + verticalPosition: this.verticalPosition, + panelClass: ['mat-primary'] + }).onAction().subscribe(() => { + console.log('The snackbar action was triggered!'); + }); + this.dialogRef.close(); + //this.dialogRef.close(); + //counter++; + //this.progress = (counter/this.data.changes.length)*100; } - this._snackBar.open(msg, action, { - horizontalPosition: this.horizontalPosition, - verticalPosition: this.verticalPosition, - duration: 5000, - }); - this.dialogRef.close(); - } - }); - } - } - } + if(this.progress == 100){ + this.diasbled = false; + this.bdiasbled = true; + let msg; + let action; + if(this.languageService.language == 'DE'){ + msg = 'Implementer Eintragung erfolgreich'; + action ='Schließen'; + }else{ + msg = 'Implementer Update successful'; + action ='close'; + } + this._snackBar.open(msg, action, { + horizontalPosition: this.horizontalPosition, + verticalPosition: this.verticalPosition, + duration: 5000, + }); + this.dialogRef.close(); + } + }); + } + } + } } diff --git a/frontend/src/app/language.service.ts b/frontend/src/app/language.service.ts index d4d30a3..497c69d 100644 --- a/frontend/src/app/language.service.ts +++ b/frontend/src/app/language.service.ts @@ -3,6 +3,12 @@ import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root' }) + +/** +* The LanguageService manages the language (DE or EN) over all Components +* and returns and returns all textual attributes in the selected language +* By holding 2 languageMaps for german and english and one languageMap that can be set to the german or english map +*/ export class LanguageService { public language: string = 'DE'; @@ -17,6 +23,9 @@ export class LanguageService { public dePlanTimeResources: any[]; public enPlanTimeResources: any[]; + /** + * The constructor sets all the language values and does the default mapping + */ constructor() { this.deMap.set('detailButton', 'Details anzeigen'); this.enMap.set('detailButton', 'Show Details'); @@ -176,21 +185,31 @@ export class LanguageService { } } - public languageChange(args: any){ + /** + * The function languageChange set the language map to the german or english map depending on the selected language + * it is triggered by an language change from the NttGanttComponent + * @param args args with the selected language + */ + public languageChange(args: any){ if(this.language == 'DE'){ this.lMap = this.deMap; }else{ this.language = 'EN'; this.lMap = this.enMap; } - } - public getColumns(){ + } + + /** + * The function getColumns delivers the gannt chart columns for the NttGanttComponent in the selected language + * it is triggered by an language change from the NttGanttComponent + */ + public getColumns(){ if(this.language == 'DE'){ return this.deColumns; }else{ this.language = 'EN'; return this.enColumns; } - } } +} diff --git a/frontend/src/app/multiselect-autocomplete/multiselect-autocomplete.component.ts b/frontend/src/app/multiselect-autocomplete/multiselect-autocomplete.component.ts index f03b76b..52ef499 100644 --- a/frontend/src/app/multiselect-autocomplete/multiselect-autocomplete.component.ts +++ b/frontend/src/app/multiselect-autocomplete/multiselect-autocomplete.component.ts @@ -16,23 +16,27 @@ export interface ItemData { templateUrl: './multiselect-autocomplete.component.html', styleUrls: ['./multiselect-autocomplete.component.css'] }) + +/** +* The MultiselectAutocompleteComponent mixes a angular material multiselect and a angular material autocomplete +* it builds the base for many filter select option +*/ export class MultiselectAutocompleteComponent implements OnInit { @Output() result = new EventEmitter<{ key: string, data: Array }>(); - ​ @Input() placeholder: string = 'Select Data'; @Input() data: Array = []; @Input() key: string = ''; - ​ selectControl = new FormControl(); - ​ rawData: Array = []; selectData: Array = []; - ​ filteredData: Observable>; filterString: string = ''; + /** + * The constructor maps the default values + */ constructor() { this.filteredData = this.selectControl.valueChanges.pipe( startWith(''), @@ -41,7 +45,9 @@ export class MultiselectAutocompleteComponent implements OnInit { ); } - + /** + * The function ngOnInit imports the data (filter options) and maps it + */ ngOnInit(): void { this.data.forEach((item: string) => { this.rawData.push({ item, selected: false }); @@ -58,8 +64,10 @@ export class MultiselectAutocompleteComponent implements OnInit { } - - + /** + * The function filter filters the list with the select options + * @param filter text to search for + */ filter = (filter: string): Array => { this.filterString = filter; if (filter.length > 0) { @@ -70,27 +78,37 @@ export class MultiselectAutocompleteComponent implements OnInit { return this.rawData.slice(); } }; - ​ - displayFn = (): string => ''; + displayFn = (): string => ''; + /** + * The funtion optionClicked hanled the selection of a select option (filter option) + * @param event selection event + * @param data (filter)item data + */ optionClicked = (event: Event, data: ItemData): void => { event.stopPropagation(); this.toggleSelection(data); }; - + /** + * The function toggleSelection handles a click on a selection item + * if it is already selected it will be removed from the selection, if it is not yet selected it will be selected + * it builds the base for many filter select option + */ toggleSelection = (data: ItemData): void => { data.selected = !data.selected; - ​ if (data.selected === true) { this.selectData.push(data); } else { const i = this.selectData.findIndex(value => value.item === data.item); this.selectData.splice(i, 1); } - ​ this.selectControl.setValue(this.selectData); this.emitAdjustedData(); }; + /** + * The emitAdjustedData emits the selected options the the parent component + * its triggered when the selectbox is closed + */ emitAdjustedData = (): void => { const results: Array = [] @@ -100,6 +118,9 @@ export class MultiselectAutocompleteComponent implements OnInit { this.result.emit({ key: this.key, data: results }); }; + /** + * The removeChip removes a option from the selection list if the user presses the remove button on the chip list + */ removeChip = (data: ItemData): void => { this.toggleSelection(data); }; diff --git a/frontend/src/app/ntt-gantt/ntt-gantt.component.ts b/frontend/src/app/ntt-gantt/ntt-gantt.component.ts index b05075b..6a30d7c 100644 --- a/frontend/src/app/ntt-gantt/ntt-gantt.component.ts +++ b/frontend/src/app/ntt-gantt/ntt-gantt.component.ts @@ -35,6 +35,9 @@ export const MY_DATE_FORMATS = { { 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 ######################################################################*/ diff --git a/frontend/src/app/plan-time-bar/plan-time-bar.component.ts b/frontend/src/app/plan-time-bar/plan-time-bar.component.ts index bd98c9b..e11fa99 100644 --- a/frontend/src/app/plan-time-bar/plan-time-bar.component.ts +++ b/frontend/src/app/plan-time-bar/plan-time-bar.component.ts @@ -22,6 +22,12 @@ export const MY_DATE_FORMATS = { templateUrl: './plan-time-bar.component.html', styleUrls: ['./plan-time-bar.component.css'] }) + +/** +* The PlanTimeBarComponent displays a second gannt chart with the calculated planTime per week +* and must have the same renderStartDate and renderEndDate as the main gantt chart +*/ + export class PlanTimeBarComponent implements OnInit { @Input() inputData: Array = []; @Input() splitterSettings: object; @@ -46,8 +52,16 @@ export class PlanTimeBarComponent implements OnInit { public renderTimeGantt: boolean = false; public filterObj: any; + /** + * The constructor only injects the LanguageService and DataService + * @param languageService representation of the LanguageService + * @param dataService representation of the DataService + */ constructor(public languageService: LanguageService, public dataService: DataService) {} + /** + * The function ngOnInit initializes all parameters of the planTime gantt chart + */ ngOnInit(): void { this.splitterSettings = this.inputData[0]; this.projectStartDate = this.inputData[1]; @@ -80,6 +94,11 @@ export class PlanTimeBarComponent implements OnInit { }; } + /** + * The function fetchPlanTimes fetches the calculated Plantimes from the dataService, depending on applied filters. + * and triggers the (re)rendering of the planTime gantt chart + * @param filters current applied filters + */ public fetchPlanTimes(filter:any = null){ this.renderTimeGantt = false; this.data = []; @@ -111,6 +130,11 @@ export class PlanTimeBarComponent implements OnInit { }); } + /** + * The queryTaskbarInfo catches the corresponding syncfusion framework event + * and manipulates it for a correct representation + * @param args args from the syncfusion framework + */ public queryTaskbarInfo(args: any) { args.taskbarBgColor = "transparent"; args.taskbarBorderColor = "transparent"; @@ -126,6 +150,10 @@ export class PlanTimeBarComponent implements OnInit { } } + /** + * The changeLanguage executes a languageChange for the planTime gantt chart + * it is triggered by a language change from the NttGanttComponent + */ public changeLanguage(){ if(this.languageService.language == 'DE'){ this.resources = [{resourceId: 1, resourceName: 'Planzeit Summen pro Woche'}]; diff --git a/frontend/src/app/state-dialog/state-dialog.component.ts b/frontend/src/app/state-dialog/state-dialog.component.ts index ce09086..f118a9d 100644 --- a/frontend/src/app/state-dialog/state-dialog.component.ts +++ b/frontend/src/app/state-dialog/state-dialog.component.ts @@ -11,8 +11,8 @@ import { LanguageService } from '../language.service'; }) /** - * The StateDialogComponent enables the user to select an execute a status transition - */ +* The StateDialogComponent enables the user to select an execute a status transition +*/ export class StateDialogComponent implements OnInit { public possibleStates: any[] = [ @@ -27,7 +27,6 @@ export class StateDialogComponent implements OnInit { public labels: string[] = []; private states : any[]; - /** * The constructor injects required Dependencies and sets default values for logic and ui * @param dialogRef MatDialog Reference from Angular @@ -43,7 +42,7 @@ export class StateDialogComponent implements OnInit { this.possibleStates = []; } -/** + /** * The function ngOnInit checks in which actual State the selected changes are, then it provides a list that contains which statuses can be switched to in the current state */ ngOnInit(): void { @@ -73,15 +72,15 @@ export class StateDialogComponent implements OnInit { } /** - * The function enableButton is triggered by the selction event of a possible state by the user it anebles the execution button - */ + * The function enableButton is triggered by the selction event of a possible state by the user it anebles the execution button + */ enableButton():void{ this.bdiasbled = false; } /** - * The function updateState uses the dataService to execute a status transition on the backend. It sends the Changes to the backend one-by-one and calculates the percent-progress value for the progress bar. - */ + * The function updateState uses the dataService to execute a status transition on the backend. It sends the Changes to the backend one-by-one and calculates the percent-progress value for the progress bar. + */ updateState(): void{ let counter : number = 0; if(this.selectedValue != -1){ @@ -121,6 +120,11 @@ export class StateDialogComponent implements OnInit { } } } + + /** + * The function findStateName returns a state name by the state number (uid), depending on the selected language + * @param stateNr uid of the state + */ findStateName(stateNr): String { for (let state of this.states) { if(stateNr == state.actualState){ diff --git a/frontend/src/tsconfig.doc.json b/frontend/src/tsconfig.doc.json new file mode 100644 index 0000000..a2f03b8 --- /dev/null +++ b/frontend/src/tsconfig.doc.json @@ -0,0 +1,4 @@ +{ + "include": ["src/**/*.ts"], + "exclude": ["src/test.ts", "src/**/*.spec.ts", "src/app/file-to-exclude.ts"] +}