| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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. |
| */ |
| |
| import { Component, OnInit, Input, Output, EventEmitter, ViewChild, ChangeDetectorRef } from '@angular/core'; |
| import { FormGroup, FormBuilder, Validators } from '@angular/forms'; |
| import { MatStepper } from '@angular/material/stepper'; |
| import { ToastrService } from 'ngx-toastr'; |
| import { Subscription } from 'rxjs'; |
| |
| import { ProjectService, RolesGroupsService, EndpointService, UserAccessKeyService } from '../../../core/services'; |
| import { ProjectDataService } from '../project-data.service'; |
| import { CheckUtils, FileUtils, PATTERNS } from '../../../core/util'; |
| import { Project } from '../project.component'; |
| import { DICTIONARY } from '../../../../dictionary/global.dictionary'; |
| |
| export interface GenerateKey { privateKey: string, publicKey: string }; |
| |
| @Component({ |
| selector: 'project-form', |
| templateUrl: './project-form.component.html', |
| styleUrls: ['./project-form.component.scss'] |
| }) |
| export class ProjectFormComponent implements OnInit { |
| |
| readonly DICTIONARY = DICTIONARY; |
| |
| public projectForm: FormGroup; |
| public groupsList: any = []; |
| public endpointsList: any = []; |
| public projectList: Project[] = []; |
| public accessKeyValid: boolean; |
| public keyLabel: string = ''; |
| public maxProjectNameLength: number = 10; |
| |
| @Input() item: any; |
| @Output() update: EventEmitter<{}> = new EventEmitter(); |
| @ViewChild('stepper', { static: true }) stepper: MatStepper; |
| |
| private subscriptions: Subscription = new Subscription(); |
| |
| constructor( |
| public toastr: ToastrService, |
| private _fb: FormBuilder, |
| private projectService: ProjectService, |
| private projectDataService: ProjectDataService, |
| private rolesService: RolesGroupsService, |
| private endpointService: EndpointService, |
| private userAccessKeyService: UserAccessKeyService, |
| private cd: ChangeDetectorRef |
| ) { } |
| |
| ngOnInit() { |
| this.initFormModel(); |
| this.getGroupsData(); |
| this.getEndpointsData(); |
| |
| this.subscriptions.add(this.projectDataService._projects.subscribe((value: Project[]) => { |
| if (value) this.projectList = value; |
| })); |
| if (this.item) { |
| this.editSpecificProject(this.item); |
| this.stepper.selectedIndex = 1; |
| } |
| } |
| |
| public confirm(data) { |
| if (this.item) { |
| this.projectService.updateProject(data).subscribe(() => { |
| this.toastr.success('Project updated successfully!', 'Success!'); |
| this.update.emit(); |
| }, error => this.toastr.error(error.message || 'Project update failed!', 'Oops!')); |
| } else { |
| this.projectService.createProject(data).subscribe(() => { |
| this.toastr.success('Project creation is processing!', 'Success!'); |
| this.projectDataService.updateProjects(); |
| this.update.emit(); |
| this.reset(); |
| }, error => this.toastr.error(error.message || 'Project creation failed!', 'Oops!')); |
| } |
| } |
| |
| public reset() { |
| this.stepper.reset(); |
| this.keyLabel = ''; |
| this.initFormModel(); |
| } |
| |
| public generateProjectTag($event) { |
| this.projectForm.controls.tag.setValue($event.target.value.toLowerCase()); |
| } |
| |
| public onFileChange($event) { |
| const reader = new FileReader(); |
| const files = $event.target.files; |
| |
| if (files && files.length) { |
| const [file] = $event.target.files; |
| reader.readAsBinaryString(file); |
| |
| reader.onload = () => { |
| this.projectForm.patchValue({ |
| key: reader.result |
| }); |
| |
| this.accessKeyValid = this.isValidKey(file.name); |
| this.keyLabel = this.getLabel(file); |
| $event.target.value = ''; |
| this.cd.markForCheck(); |
| }; |
| } |
| } |
| |
| public generateUserAccessKey() { |
| this.userAccessKeyService.generateAccessKey().subscribe((data: any) => { |
| const parsedData = JSON.parse(data.body); |
| const keyName = `${parsedData.username}.pem`; |
| FileUtils.downloadFile(data, parsedData.privateKey, keyName); |
| |
| this.projectForm.controls.key.setValue(parsedData.publicKey); |
| this.keyLabel = keyName; |
| this.accessKeyValid = true; |
| }); |
| } |
| |
| public selectOptions(list, key, select?) { |
| let filter = key === 'endpoints' ? list.map(el => el.name) : list; |
| this.projectForm.controls[key].setValue(select ? filter : []); |
| } |
| |
| |
| private initFormModel(): void { |
| this.projectForm = this._fb.group({ |
| 'key': ['', Validators.required], |
| 'name': ['', Validators.compose([Validators.required, Validators.pattern(PATTERNS.projectName), this.checkDuplication.bind(this), this.providerMaxLength.bind(this)])], |
| 'endpoints': [[], Validators.required], |
| 'tag': ['', Validators.compose([Validators.required, Validators.pattern(PATTERNS.projectName)])], |
| 'groups': [[], Validators.required], |
| 'shared_image_enabled': [false, Validators.required] |
| }); |
| } |
| |
| public editSpecificProject(item) { |
| const endpoints = item.endpoints.map((endpoint: any) => endpoint.name); |
| |
| this.projectForm = this._fb.group({ |
| 'key': [''], |
| 'name': [item.name, Validators.required], |
| 'endpoints': [endpoints], |
| 'tag': [item.tag, Validators.required], |
| 'groups': [item.groups, Validators.required], |
| 'shared_image_enabled': [item.sharedImageEnabled, Validators.required] |
| }); |
| } |
| |
| isDisabled(endpoint: any): boolean { |
| if (this.item) { |
| const endpoints = this.item.endpoints.map((item: any) => item.name); |
| return endpoints.includes(endpoint); |
| } |
| } |
| |
| private getLabel(file: File): string { |
| return file ? !this.accessKeyValid ? 'Public key is required.' : file.name : ''; |
| } |
| |
| private isValidKey(value): boolean { |
| return value.toLowerCase().endsWith('.pub'); |
| } |
| |
| private getGroupsData() { |
| this.rolesService.getGroupsData().subscribe( |
| (list: any) => this.groupsList = list.map(el => el.group), |
| error => this.toastr.error(error.message, 'Oops!')); |
| } |
| |
| private getEndpointsData() { |
| this.endpointService.getEndpointsData().subscribe( |
| list => this.endpointsList = list, |
| error => this.toastr.error(error.message, 'Oops!')); |
| } |
| |
| private checkDuplication(control) { |
| if (control.value) { |
| for (let index = 0; index < this.projectList.length; index++) { |
| if (CheckUtils.delimitersFiltering(control.value) === CheckUtils.delimitersFiltering(this.projectList[index].name)) |
| return { duplication: true }; |
| } |
| } |
| } |
| |
| private providerMaxLength(control) { |
| return control.value.length <= this.maxProjectNameLength ? null : { limit: true }; |
| } |
| } |