summaryrefslogtreecommitdiffstats
path: root/mod2/ui/src/app/msInstances/msInstances.component.ts
diff options
context:
space:
mode:
Diffstat (limited to 'mod2/ui/src/app/msInstances/msInstances.component.ts')
-rw-r--r--mod2/ui/src/app/msInstances/msInstances.component.ts511
1 files changed, 511 insertions, 0 deletions
diff --git a/mod2/ui/src/app/msInstances/msInstances.component.ts b/mod2/ui/src/app/msInstances/msInstances.component.ts
new file mode 100644
index 0000000..e011cb9
--- /dev/null
+++ b/mod2/ui/src/app/msInstances/msInstances.component.ts
@@ -0,0 +1,511 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # Licensed under the Apache License, Version 2.0 (the "License");
+ * # you may not use this file except in compliance with the License.
+ * # You may obtain a copy of the License at
+ * #
+ * # http://www.apache.org/licenses/LICENSE-2.0
+ * #
+ * # Unless required by applicable law or agreed to in writing, software
+ * # distributed under the License is distributed on an "AS IS" BASIS,
+ * # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * # See the License for the specific language governing permissions and
+ * # limitations under the License.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';
+import { MatTableDataSource } from '@angular/material/table';
+import { Table } from 'primeng/table';
+import { MessageService } from 'primeng/api';
+import { trigger, state, style, transition, animate } from '@angular/animations';
+import { MicroserviceInstanceService } from '../services/microservice-instance.service';
+import { DatePipe } from '@angular/common';
+import { DeploymentArtifactService } from '../services/deployment-artifact.service';
+import { CompSpecAddService } from '../services/comp-spec-add.service';
+import { BreadcrumbService } from '../services/breadcrumb.service';
+import { Router } from '@angular/router';
+import { Ng4LoadingSpinnerService } from 'ng4-loading-spinner';
+import { DownloadService } from '../services/download.service';
+
+@Component({
+ selector: 'app-msInstances',
+ templateUrl: './msInstances.component.html',
+ styleUrls: ['./msInstances.component.css'],
+ animations: [
+ trigger('rowExpansionTrigger', [
+ state('void', style({
+ transform: 'translateX(-10%)',
+ opacity: 0
+ })),
+ state('active', style({
+ transform: 'translateX(0)',
+ opacity: 1
+ })),
+ transition('* <=> *', animate('400ms cubic-bezier(0.86, 0, 0.07, 1)'))
+ ])
+ ],
+ providers: [DatePipe]
+})
+export class MsInstancesComponent implements OnInit {
+ @ViewChild(Table, { static: false }) dt: Table;
+ @ViewChild('myInput', { static: false }) myInputVariable: ElementRef;
+
+
+ /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
+ msInstances: msInstance[] = [];
+ expandedItems: Array<any> = new Array<any>();
+ dataSource = new MatTableDataSource<msInstance>(this.msInstances);
+ cols: any[] = [
+ { field: 'baseMsName', header: 'MS Name' },
+ { field: 'tag', header: 'MS Tag' },
+ { field: 'release', header: 'Release', width: '7%' },
+ { field: 'pstDueDate', header: 'PST Date', width: '9%' },
+ { field: 'pstDueIteration', header: 'PST Iteration', width: '6.5%' },
+ { field: 'eteDueDate', header: 'ETE Date', width: '9%' },
+ { field: 'eteDueIteration', header: 'ETE Iteration', width: '6.5%' },
+ { field: 'status', header: 'Status', width: '125px' }
+ ];
+ selectedMsInstances: msInstance[] = [];
+ columns: any[];
+ loadTable: boolean;
+ filteredRows: any;
+ downloadItems: { label: string; command: () => void; }[];
+ showAddChangeMsInstance: boolean;
+ currentRow: any;
+ msInstanceChange: string = "change";
+ generatedBPs: any[] = [];
+ canGenerateSelectedBPs: boolean = false;
+ generateSelectedBPsTooltip: string = '';
+
+ // Json to add CS (Component Spec) to DB, returned from child
+ csAddJson: any;
+
+ showCsAddDialog: boolean = false;
+
+ showViewCs: boolean =false;
+ msInstanceId: string = '';
+ errorList: string[];
+
+ constructor(private spinnerService: Ng4LoadingSpinnerService, private msInstanceApi: MicroserviceInstanceService,
+ private bpApis: DeploymentArtifactService, private addCsApi: CompSpecAddService, private messageService: MessageService,
+ private datePipe: DatePipe, private router: Router, private downloadService: DownloadService, private bread: BreadcrumbService) { }
+
+ ngOnInit() {
+
+ this.getAllInstances();
+
+ }
+
+ getAllInstances() {
+ this.spinnerService.show();
+ this.msInstances = [];
+ this.loadTable = false;
+
+ this.msInstanceApi.getAllMsInstances()
+ .subscribe((data: any[]) => {
+ this.fillTable(data)
+ })
+
+ this.columns = this.cols.map(col => ({ title: col.header, dataKey: col.field }));
+ }
+
+
+ // * * * * * Show the Dialog to Change an MS Instance (<app-ms-instance-add> tag in the html) * * * * *
+ showAddChangeDialog(rowData) {
+ this.msInstanceId = rowData['id']
+ this.showAddChangeMsInstance = true;
+ this.currentRow = rowData;
+ }
+
+ /* * * * Call API to Change an MS Instance * * * */
+ addChangeMsInstance(jsonFromChildDialog) {
+ if (jsonFromChildDialog === null) {
+ this.showAddChangeMsInstance = false;
+ } else {
+ this.msInstanceApi.addChangeMsInstance("CHANGE", this.msInstanceId, jsonFromChildDialog).subscribe(
+ (data) => {
+ this.updateCurrentRow(data);
+ this.messageService.add({ key: 'changeSuccess', severity: 'success', summary: 'Success', detail: "MS Instance Updated", life: 5000 });
+ this.showAddChangeMsInstance = false;
+ },
+ (errResponse) => {
+ if (errResponse.error.message) {
+ this.messageService.add({ key: 'instanceAddChangeError', severity: 'error', summary: 'Error', detail: errResponse.error.message, sticky: true });
+ } else {
+ this.messageService.add({ key: 'instanceAddChangeError', severity: 'error', summary: 'Error', detail: errResponse.error.status, sticky: true });
+ }
+ }
+ )
+ }
+ }
+
+ updateCurrentRow(responseData) {
+ const newRow = responseData;
+ this.currentRow['release'] = newRow['release'];
+ this.currentRow['metadata']['scrumLead'] = newRow['metadata']['scrumLead'];
+ this.currentRow['metadata']['scrumLeadId'] = newRow['metadata']['scrumLeadId'];
+ this.currentRow['metadata']['systemsEngineer'] = newRow['metadata']['systemsEngineer'];
+ this.currentRow['metadata']['systemsEngineerId'] = newRow['metadata']['systemsEngineerId'];
+ this.currentRow['metadata']['developer'] = newRow['metadata']['developer'];
+ this.currentRow['metadata']['developerId'] = newRow['metadata']['developerId'];
+ this.currentRow['pstDueDate'] = this.datePipe.transform(newRow['metadata']['pstDueDate'], 'yyyy-MM-dd');
+ this.currentRow['pstDueIteration'] = newRow['metadata']['pstDueIteration'];
+ this.currentRow['eteDueDate'] = this.datePipe.transform(newRow['metadata']['eteDueDate'], 'yyyy-MM-dd');
+ this.currentRow['eteDueIteration'] = newRow['metadata']['eteDueIteration'];
+ this.currentRow['metadata']['labels'] = newRow['metadata']['labels'];
+ this.currentRow['metadata']['notes'] = newRow['metadata']['notes'];
+ this.currentRow['metadata']['updatedBy'] = newRow['metadata']['updatedBy'];
+ this.currentRow['metadata']['updatedOn'] = this.datePipe.transform(newRow['metadata']['updatedOn'], 'MM-dd-yyyy HH:mm');
+ }
+
+ // * * * * * Show the Dialog to Add a CS (in the html) * * * * *
+ // * * * * * Store the MS Instance ID for the URL and the "current row" to update when a CS is saved * * * * *
+ showAddCSDialog(rowData) {
+ this.showCsAddDialog = true;
+ this.msInstanceId = rowData['id'];
+ this.currentRow = rowData;
+ }
+
+ // * * * * * Add a CS * * * * *
+ addNewCs(jsonFromChildDialog) {
+ let compSpecAddMessage = '';
+ if (jsonFromChildDialog) {
+ this.csAddJson = jsonFromChildDialog;
+ if((JSON.parse(this.csAddJson)).policyJson === null){
+ compSpecAddMessage = 'Component Spec Added';
+ } else {
+ console.log("here")
+ compSpecAddMessage = 'Component Spec and Policy added '
+ }
+
+ this.addCsApi.addCsToCatalog(this.msInstanceId, this.csAddJson).subscribe(
+ (response: any) => {
+ this.messageService.add({ key: 'compSpecAdded', severity: 'success', summary: 'Success', detail: compSpecAddMessage, life: 5000 });
+ this.showCsAddDialog = false;
+ this.currentRow['activeSpec'] = true;
+ },
+ errResponse => {
+ if (errResponse.error.errors) {
+ this.messageService.add({ key: 'errorOnCsAdd', severity: 'error', summary: errResponse.error.message, detail: errResponse.error.errors.join('\n'), sticky: true});
+ } else {
+ let summary = errResponse.error.status + " - " + errResponse.error.error;
+ this.messageService.add({ key: 'errorOnCsAdd', severity: 'error', summary: summary, detail: errResponse.error.message, sticky: true});
+ }
+ });
+ } else {
+ this.showCsAddDialog = false
+ };
+ }
+
+/* * * * View Component Specs
+msName: string;
+msRelease: string;
+ showViewCsDialog(data){
+ this.msInstanceId = data['id']
+ this.msName = data['name']
+ this.msRelease = data['release']
+ this.showViewCs = true;
+ }
+ csView(data){
+ if(data===null){
+ this.showViewCs = false
+ } else {
+ this.showViewCs = false
+ this.messageService.add({ key: 'csViewError', severity: 'error', summary: 'Error Message', detail: data.error.message, sticky: true });
+ }
+ }
+ * * * */
+
+ /* * * * Generate single blueprint * * * */
+ generateBlueprints(data){
+ this.bpApis.postBlueprint(data['id']).subscribe((response) => {
+ this.messageService.add({ key: 'bpGenMessage', severity: 'success', summary: 'Success Message', detail: 'Blueprint Generated', life: 5000 });
+ }, (errResponse) => {
+ this.messageService.add({ key: 'bpGenMessage', severity: 'error', summary: 'Error Message', detail: errResponse.error.message, life: 15000 });
+ })
+ }
+
+ /* * * * Check if generate selected blueprints button should be disabled and set tooltip message * * * */
+ checkCanGenerateBp() {
+ if (this.selectedMsInstances.length > 0) {
+
+ let noActiveSpecs: string[] = [];
+ let checkReleases: boolean = true;
+ let firstRelease = this.selectedMsInstances[0]['release'];
+ for (let elem of this.selectedMsInstances) {
+ if (elem.release !== firstRelease){
+ checkReleases = false
+ this.canGenerateSelectedBPs = false
+ this.generateSelectedBPsTooltip = 'Cannot Generate Blueprints For Different Releases'
+ break
+ }
+ if (elem.activeSpec === null) {
+ noActiveSpecs.push(elem.name)
+ this.generateSelectedBPsTooltip += elem.name
+ }
+ }
+
+ if (noActiveSpecs.length < 1 && checkReleases) {
+ this.canGenerateSelectedBPs = true
+ } else if (noActiveSpecs.length > 0 && checkReleases){
+ this.canGenerateSelectedBPs = false
+ this.generateSelectedBPsTooltip = 'No Active Specs For : '
+ let i: number = 1;
+ for (let elem of noActiveSpecs) {
+ if (i === noActiveSpecs.length) {
+ this.generateSelectedBPsTooltip += '{' + elem + '}'
+ } else {
+ this.generateSelectedBPsTooltip += '{' + elem + '}, '
+ }
+ i++
+ }
+ }
+ } else {
+ this.canGenerateSelectedBPs = false
+ this.generateSelectedBPsTooltip = "No Instances Selected"
+ }
+ }
+
+ /* * * * Generate multiple blueprint * * * */
+ successfulBpGens: number;
+ generateSelectedBlueprints(){
+ this.successfulBpGens = 0;
+ this.count = 0;
+ this.selectionLength = this.selectedMsInstances.length;
+
+ this.spinnerService.show();
+
+ (async () => {
+ for (let instance of this.selectedMsInstances) {
+ this.bpApis.postBlueprint(instance.id).subscribe((response) => {
+ this.bpGenSuccess()
+ }, (errResponse) => {
+ this.bpGenError(errResponse.error.message)
+ })
+ await timeout(1500);
+ }
+ })();
+
+ function timeout(ms) {
+ return new Promise(resolve => setTimeout(resolve, ms));
+ }
+
+ this.selectedMsInstances = []
+ }
+
+ /* * * * For BP Gen Successes * * * */
+ selectionLength: number;
+ count: number;
+ bpGenSuccess(){
+ this.successfulBpGens++;
+ this.count++;
+ if (this.count === this.selectionLength){
+ if(this.successfulBpGens > 0){
+ this.messageService.add({ key: 'bpGenMessage', severity: 'success', summary: 'Success Message', detail: 'Blueprints Generated', life: 5000 });
+ this.spinnerService.hide()
+ }
+ }
+ }
+
+ /* * * * For BP Gen Errors * * * */
+ bpGenError(err){
+ this.count++;
+ if (this.count === this.selectionLength) {
+ if (this.successfulBpGens > 0) {
+ this.messageService.add({ key: 'bpGenMessage', severity: 'success', summary: 'Success Message', detail: 'Blueprints Generated', life: 5000 });
+ this.spinnerService.hide()
+ }
+ }
+ this.messageService.add({ key: 'bpGenMessage', severity: 'error', summary: 'Error Message', detail: err, life: 15000 });
+ }
+
+ /* * * * View the Blueprints for the selected MS Instance * * * */
+ viewBlueprints(rowData) {
+ this.router.navigate(["blueprints"], {queryParams:{tag: rowData['tag'], release:rowData['release'] }});
+ this.bread.setBreadcrumbs("Blueprints", "add");
+ }
+
+ /* * * * View the Component Spec for the selected MS Instance * * * */
+ viewCompSpecs(rowData) {
+ this.router.navigate(["CompSpecs"], { queryParams: { instanceId: rowData['id'] }});
+ this.bread.setBreadcrumbs("Component Specs", "add");
+ }
+
+ /* * * * Stores filtered data in new array * * * */
+ onTableFiltered(values) {
+ if (values) { this.filteredRows = values; }
+ else { this.filteredRows = this.msInstances; }
+ }
+
+ /* * * * Export ms instance table to excel or csv * * * */
+ exportTable(exportTo) {
+ let downloadElements: any[] = []
+
+ //labels array not handled well by excel download so converted them to a single string
+ for(let row of this.filteredRows){
+ let labels;
+ let notes;
+ if(exportTo === "excel"){
+ if(row.metadata.labels !== undefined){
+ labels = row.metadata.labels.join(",")
+ }
+ } else {
+ labels = row.metadata.labels
+ }
+
+ if (row.metadata.notes !== null && row.metadata.notes !== undefined && row.metadata.notes !== '') {
+ notes = encodeURI(row.metadata.notes).replace(/%20/g, " ").replace(/%0A/g, "\\n")
+ }
+
+ downloadElements.push({
+ MS_Name: row.name,
+ MS_Tag: row.tag,
+ Release: row.release,
+ PST_Due_Date: row.pstDueDate,
+ PST_Due_Iteration: row.pstDueIteration,
+ ETE_Due_Date: row.eteDueDate,
+ ETE_Due_Iteration: row.eteDueIteration,
+ Status: row.status,
+ Created_By: row.metadata.createdBy,
+ Created_On: row.metadata.createdOn,
+ Updated_By: row.metadata.updatedBy,
+ Updated_On: row.metadata.updatedOn,
+ Scrum_Lead: row.metadata.scrumLead,
+ Scrum_Lead_Id: row.metadata.scrumLeadId,
+ Systems_Engineer: row.metadata.systemsEngineer,
+ Systems_Engineer_Id: row.metadata.systemsEngineerId,
+ Developer: row.metadata.developer,
+ Developer_Id: row.metadata.developerId,
+ Notes: notes,
+ Labels: labels
+ })
+ }
+
+ let csvHeaders = [];
+
+ if (exportTo === "csv") {
+ csvHeaders = [
+ "MS_Name",
+ "MS_Tag",
+ "Release",
+ "PST_Due_Date",
+ "PST_Due_Iteration",
+ "ETE_Due_Date",
+ "ETE_Due_Iteration",
+ "Status",
+ "Created_By",
+ "Created_On",
+ "Updated_By",
+ "Updated_On",
+ "Scrum_Lead",
+ "Scrum_Lead_Id",
+ "Systems_Engineer",
+ "Systems_Engineer_Id",
+ "Developer",
+ "Developer_Id",
+ "Notes",
+ "Labels"
+ ];
+ }
+
+ this.downloadService.exportTableData(exportTo, downloadElements, csvHeaders)
+ }
+
+ /* * * * Fill ms instance table * * * */
+ fillTable(data) {
+
+ for (let elem of data) {
+
+ /* * * Now storing as dates (not strings) on DB, so need to convert old data (mm-dd-yyyy and m-d-yyyy) * * */
+ let pstDueDate: any;
+ if (elem.metadata.pstDueDate && (elem.metadata.pstDueDate.length <= 11 &&
+ elem.metadata.pstDueDate.length > 7)) {
+ pstDueDate = new Date(elem.metadata.pstDueDate.replace(/-/g, '/')) // dash is invalid date format, FF fails
+ pstDueDate = this.datePipe.transform(pstDueDate, 'yyyy-MM-dd')
+ } else if (elem.metadata.pstDueDate) {
+ pstDueDate = this.datePipe.transform(elem.metadata.pstDueDate, 'yyyy-MM-dd')
+ } else {
+ pstDueDate = elem.metadata.pstDueDate
+ }
+
+ let eteDueDate: any;
+ if (elem.metadata.eteDueDate && (elem.metadata.eteDueDate.length <= 11 &&
+ elem.metadata.eteDueDate.length > 7)) {
+ eteDueDate = new Date(elem.metadata.eteDueDate.replace(/-/g, '/')) // dash is invalid date format, FF fails
+ eteDueDate = this.datePipe.transform(eteDueDate, 'yyyy-MM-dd')
+ } else if (elem.metadata.eteDueDate) {
+ eteDueDate = this.datePipe.transform(elem.metadata.eteDueDate, 'yyyy-MM-dd')
+ } else {
+ eteDueDate = elem.metadata.eteDueDate
+ }
+
+ var tempElem: msInstance = {
+ id: elem.id,
+ name: elem.name,
+ tag: elem.msInfo.tag,
+ release: elem.release,
+ version: elem.version,
+ status: elem.status,
+ baseMsId: elem.msInfo.id,
+ baseMsName: elem.msInfo.name,
+ metadata: {
+ scrumLead: elem.metadata.scrumLead,
+ scrumLeadId: elem.metadata.scrumLeadId,
+ systemsEngineer: elem.metadata.systemsEngineer,
+ systemsEngineerId: elem.metadata.systemsEngineerId,
+ developer: elem.metadata.developer,
+ developerId: elem.metadata.developerId,
+ createdBy: elem.metadata.createdBy,
+ createdOn: this.datePipe.transform(elem.metadata.createdOn, 'MM-dd-yyyy HH:mm'),
+ updatedBy: elem.metadata.updatedBy,
+ updatedOn: this.datePipe.transform(elem.metadata.updatedOn, 'MM-dd-yyyy HH:mm'),
+ notes: elem.metadata.notes,
+ labels: elem.metadata.labels,
+ },
+ pstDueDate: pstDueDate,
+ pstDueIteration: elem.metadata.pstDueIteration,
+ eteDueDate: eteDueDate,
+ eteDueIteration: elem.metadata.eteDueIteration,
+ activeSpec: elem.activeSpec
+ }
+ this.msInstances.push(tempElem)
+ }
+
+ this.filteredRows = this.msInstances
+ this.loadTable = true;
+ this.spinnerService.hide()
+ }
+}
+
+export interface msInstance{
+ id: string,
+ name: string,
+ tag: string,
+ release: string,
+ version: string,
+ status: string,
+ baseMsId: string,
+ baseMsName: string ,
+ metadata: {
+ scrumLead: string,
+ scrumLeadId: string,
+ systemsEngineer: string,
+ systemsEngineerId: string,
+ developer: string,
+ developerId: string,
+ createdBy: string,
+ createdOn: string,
+ updatedBy: string,
+ updatedOn: string,
+ notes: string,
+ labels: string[],
+ }
+ pstDueDate: string,
+ pstDueIteration: string,
+ eteDueDate: string,
+ eteDueIteration: string,
+ activeSpec: any
+} \ No newline at end of file