mirror of https://github.com/goharbor/harbor.git
204 lines
6.8 KiB
TypeScript
204 lines
6.8 KiB
TypeScript
// Copyright (c) 2017 VMware, Inc. 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.
|
|
import {debounceTime, distinctUntilChanged} from 'rxjs/operators';
|
|
import {
|
|
Component,
|
|
EventEmitter,
|
|
Output,
|
|
ViewChild,
|
|
OnInit,
|
|
OnDestroy,
|
|
Input,
|
|
OnChanges,
|
|
SimpleChanges
|
|
} from "@angular/core";
|
|
import { NgForm, Validators, AbstractControl } from "@angular/forms";
|
|
import { Subject } from "rxjs";
|
|
import { TranslateService } from "@ngx-translate/core";
|
|
import { MessageHandlerService } from "../../shared/message-handler/message-handler.service";
|
|
import { InlineAlertComponent } from "../../shared/inline-alert/inline-alert.component";
|
|
import { Project } from "../project";
|
|
import { QuotaUnits, QuotaUnlimited } from "../../../lib/entities/shared.const";
|
|
import { ProjectService, QuotaHardInterface } from "../../../lib/services";
|
|
import { clone, getByte, GetIntegerAndUnit, validateCountLimit, validateLimit } from "../../../lib/utils/utils";
|
|
|
|
|
|
@Component({
|
|
selector: "create-project",
|
|
templateUrl: "create-project.component.html",
|
|
styleUrls: ["create-project.scss"]
|
|
})
|
|
export class CreateProjectComponent implements OnInit, OnChanges, OnDestroy {
|
|
|
|
projectForm: NgForm;
|
|
|
|
@ViewChild("projectForm", {static: true})
|
|
currentForm: NgForm;
|
|
quotaUnits = QuotaUnits;
|
|
project: Project = new Project();
|
|
countLimit: number;
|
|
storageLimit: number;
|
|
storageLimitUnit: string = QuotaUnits[3].UNIT;
|
|
storageDefaultLimit: number;
|
|
storageDefaultLimitUnit: string;
|
|
countDefaultLimit: number;
|
|
initVal: Project = new Project();
|
|
|
|
createProjectOpened: boolean;
|
|
|
|
hasChanged: boolean;
|
|
isSubmitOnGoing = false;
|
|
|
|
staticBackdrop = true;
|
|
closable = false;
|
|
|
|
isNameValid = true;
|
|
nameTooltipText = "PROJECT.NAME_TOOLTIP";
|
|
checkOnGoing = false;
|
|
proNameChecker: Subject<string> = new Subject<string>();
|
|
|
|
@Output() create = new EventEmitter<boolean>();
|
|
@Input() quotaObj: QuotaHardInterface;
|
|
@Input() isSystemAdmin: boolean;
|
|
@ViewChild(InlineAlertComponent, {static: true})
|
|
inlineAlert: InlineAlertComponent;
|
|
|
|
constructor(private projectService: ProjectService,
|
|
private translateService: TranslateService,
|
|
private messageHandlerService: MessageHandlerService) { }
|
|
|
|
ngOnInit(): void {
|
|
this.proNameChecker.pipe(
|
|
debounceTime(300))
|
|
.subscribe((name: string) => {
|
|
let cont = this.currentForm.controls["create_project_name"];
|
|
if (cont) {
|
|
this.isNameValid = cont.valid;
|
|
if (this.isNameValid) {
|
|
// Check exiting from backend
|
|
this.checkOnGoing = true;
|
|
this.projectService
|
|
.checkProjectExists(cont.value)
|
|
.subscribe(() => {
|
|
// Project existing
|
|
this.isNameValid = false;
|
|
this.nameTooltipText = "PROJECT.NAME_ALREADY_EXISTS";
|
|
this.checkOnGoing = false;
|
|
}, error => {
|
|
this.checkOnGoing = false;
|
|
});
|
|
} else {
|
|
this.nameTooltipText = "PROJECT.NAME_TOOLTIP";
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
ngOnChanges(changes: SimpleChanges): void {
|
|
if (changes && changes["quotaObj"] && changes["quotaObj"].currentValue) {
|
|
this.countLimit = this.quotaObj.count_per_project;
|
|
this.storageLimit = GetIntegerAndUnit(this.quotaObj.storage_per_project, clone(QuotaUnits), 0, clone(QuotaUnits)).partNumberHard;
|
|
this.storageLimitUnit = this.storageLimit === QuotaUnlimited ? QuotaUnits[3].UNIT
|
|
: GetIntegerAndUnit(this.quotaObj.storage_per_project, clone(QuotaUnits), 0, clone(QuotaUnits)).partCharacterHard;
|
|
|
|
this.countDefaultLimit = this.countLimit;
|
|
this.storageDefaultLimit = this.storageLimit;
|
|
this.storageDefaultLimitUnit = this.storageLimitUnit;
|
|
if (this.isSystemAdmin) {
|
|
this.currentForm.form.controls['create_project_storage_limit'].setValidators(
|
|
[
|
|
Validators.required,
|
|
Validators.pattern('(^-1$)|(^([1-9]+)([0-9]+)*$)'),
|
|
validateLimit(this.currentForm.form.controls['create_project_storage_limit_unit'])
|
|
]);
|
|
this.currentForm.form.controls['create_project_count_limit'].setValidators(
|
|
[
|
|
Validators.required,
|
|
Validators.pattern('(^-1$)|(^([1-9]+)([0-9]+)*$)'),
|
|
validateCountLimit()
|
|
]);
|
|
}
|
|
this.currentForm.form.valueChanges
|
|
.pipe(distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b)))
|
|
.subscribe((data) => {
|
|
['create_project_storage_limit', 'create_project_storage_limit_unit', 'create_project_count_limit'].forEach(fieldName => {
|
|
if (this.currentForm.form.get(fieldName) && this.currentForm.form.get(fieldName).value !== null) {
|
|
this.currentForm.form.get(fieldName).updateValueAndValidity();
|
|
}
|
|
});
|
|
});
|
|
}
|
|
}
|
|
ngOnDestroy(): void {
|
|
this.proNameChecker.unsubscribe();
|
|
}
|
|
|
|
onSubmit() {
|
|
if (this.isSubmitOnGoing) {
|
|
return ;
|
|
}
|
|
this.isSubmitOnGoing = true;
|
|
const storageByte = +this.storageLimit === QuotaUnlimited ? this.storageLimit : getByte(+this.storageLimit, this.storageLimitUnit);
|
|
this.projectService
|
|
.createProject(this.project.name, this.project.metadata, +this.countLimit, +storageByte)
|
|
.subscribe(
|
|
status => {
|
|
this.isSubmitOnGoing = false;
|
|
|
|
this.create.emit(true);
|
|
this.messageHandlerService.showSuccess("PROJECT.CREATED_SUCCESS");
|
|
this.createProjectOpened = false;
|
|
},
|
|
error => {
|
|
this.isSubmitOnGoing = false;
|
|
this.inlineAlert.showInlineError(error);
|
|
});
|
|
}
|
|
|
|
onCancel() {
|
|
this.createProjectOpened = false;
|
|
}
|
|
|
|
newProject() {
|
|
this.project = new Project();
|
|
this.hasChanged = false;
|
|
this.isNameValid = true;
|
|
|
|
this.createProjectOpened = true;
|
|
this.inlineAlert.close();
|
|
|
|
this.countLimit = this.countDefaultLimit ;
|
|
this.storageLimit = this.storageDefaultLimit;
|
|
this.storageLimitUnit = this.storageDefaultLimitUnit;
|
|
}
|
|
|
|
public get isValid(): boolean {
|
|
return this.currentForm &&
|
|
this.currentForm.valid &&
|
|
!this.isSubmitOnGoing &&
|
|
this.isNameValid &&
|
|
!this.checkOnGoing;
|
|
}
|
|
|
|
// Handle the form validation
|
|
handleValidation(): void {
|
|
let cont = this.currentForm.controls["create_project_name"];
|
|
if (cont) {
|
|
this.proNameChecker.next(cont.value);
|
|
}
|
|
|
|
}
|
|
}
|
|
|