summaryrefslogtreecommitdiffstats
path: root/portal-FE-common/src/app/pages/widget-onboarding
diff options
context:
space:
mode:
Diffstat (limited to 'portal-FE-common/src/app/pages/widget-onboarding')
-rw-r--r--portal-FE-common/src/app/pages/widget-onboarding/widget-details-dialog/widget-details-dialog.component.html120
-rw-r--r--portal-FE-common/src/app/pages/widget-onboarding/widget-details-dialog/widget-details-dialog.component.scss82
-rw-r--r--portal-FE-common/src/app/pages/widget-onboarding/widget-details-dialog/widget-details-dialog.component.spec.ts63
-rw-r--r--portal-FE-common/src/app/pages/widget-onboarding/widget-details-dialog/widget-details-dialog.component.ts429
-rw-r--r--portal-FE-common/src/app/pages/widget-onboarding/widget-onboarding.component.html100
-rw-r--r--portal-FE-common/src/app/pages/widget-onboarding/widget-onboarding.component.scss62
-rw-r--r--portal-FE-common/src/app/pages/widget-onboarding/widget-onboarding.component.spec.ts62
-rw-r--r--portal-FE-common/src/app/pages/widget-onboarding/widget-onboarding.component.ts311
8 files changed, 1229 insertions, 0 deletions
diff --git a/portal-FE-common/src/app/pages/widget-onboarding/widget-details-dialog/widget-details-dialog.component.html b/portal-FE-common/src/app/pages/widget-onboarding/widget-details-dialog/widget-details-dialog.component.html
new file mode 100644
index 00000000..bd87e699
--- /dev/null
+++ b/portal-FE-common/src/app/pages/widget-onboarding/widget-details-dialog/widget-details-dialog.component.html
@@ -0,0 +1,120 @@
+<!--
+ ============LICENSE_START==========================================
+ ONAP Portal
+ ===================================================================
+ Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ ===================================================================
+
+ Unless otherwise specified, all software contained herein is licensed
+ under the Apache License, Version 2.0 (the "License");
+ you may not use this software 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.
+
+ Unless otherwise specified, all documentation contained herein is licensed
+ under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ you may not use this documentation except in compliance with the License.
+ You may obtain a copy of the License at
+
+ https://creativecommons.org/licenses/by/4.0/
+
+ Unless required by applicable law or agreed to in writing, documentation
+ 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============================================
+
+
+ -->
+
+<div class="container">
+ <!--Modal Headers-->
+ <div class="modal-header">
+ <h4 class="modal-title">Widget Details</h4>
+ <button type="button" class="close" aria-label="Close" (click)="activeModal.dismiss('Cross')">
+ <span aria-hidden="true">&times;</span>
+ </button>
+ </div>
+
+ <!--Modal Body goes here-->
+ <form id="widgets-details-form" name="widgetForm" [formGroup] = "uploadForm" (ngSubmit)="saveChanges()"
+ enctype="multipart/form-data" novalidate autocomplete="off">
+ <div class="modal-body">
+ <div class="widget-model-body">
+ <div class="item-label">Widget Name</div>
+ <input id="widgets-details-input-name" class="widget-name-field"
+ type="text" formControlName="widgetName" [(ngModel)]="widget.name"
+ ng-pattern="/^[\w -]*$/" maxlength="100"
+ ng-disabled="widgetOnboardingDetails.isEditMode" required />
+
+ <div class="item-label" style="padding-top: 20px">Widget Description</div>
+
+ <textarea b2b-reset b2b-reset-textarea class="widgets-details-input-desc"
+ formControlName="description" [(ngModel)]="widget.desc" type="text" maxlength="200">
+ </textarea>
+
+ <div class="table-dropdown">
+ <mat-form-field class="widget-service-select">
+ <mat-label> Service Endpoint </mat-label>
+ <mat-select name="widget-service-select" id="serviceEndPoint"
+ formControlName="serviceEndPoint" [(ngModel)]="widget.serviceURL" [disabled]="isEditMode">
+ <mat-option *ngFor="let rowData of availableMicroServices" [value]="rowData.id" >{{rowData.option}}</mat-option>
+ </mat-select>
+ </mat-form-field>
+ </div>
+
+ <div class="property-label checkbox-label" style="padding-top: 20px">
+ <mat-checkbox formControlName="allowAllUser" type="checkbox" [(ngModel)]="widget.allUser"
+ id="allow-all-user">
+ Allow all user access
+ </mat-checkbox>
+ </div>
+
+ <div [hidden]="widget.allUser">
+ <div class="table-dropdown">
+ <mat-form-field class="widget-applications-select">
+ <mat-label> Application Name </mat-label>
+ <mat-select multiple name="widget-application-select" id="application"
+ formControlName="applicationName" [(ngModel)]="widget.appName">
+ <mat-option *ngFor="let rowData of availableApps" [value]="rowData.id" >{{rowData.name}}</mat-option>
+ </mat-select>
+ </mat-form-field>
+ </div>
+ </div>
+
+ <div [hidden]="widget.allUser">
+ <div class="table-dropdown">
+ <mat-form-field class="widget-roles-select">
+ <mat-label> User Role Name </mat-label>
+ <mat-select multiple name="widget-role-select" id="roles"
+ formControlName="applicationRole" [(ngModel)]="widget.widgetRoles">
+ <mat-option *ngFor="let appRole of availableApps.roles" [value]="appRole.id" >{{appRole.name}}</mat-option>
+ </mat-select>
+ </mat-form-field>
+ </div>
+ </div>
+
+ <div class="item-label widget-upload">Upload Widget</div>
+ <div>
+ <input id="widget-onboarding-details-upload-file"
+ name="profile" type="file"
+ class="widget-onboarding-details-upload-file ht"
+ (change)="onFileSelect($event)"/>
+ </div>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <button type="submit" class="btn btn-primary"[disabled]="(isFileNotSelected && !isEditMode)">Save</button>
+ <button type="button" class="btn btn-primary" (click)="activeModal.close('Close')">Cancel</button>
+ </div>
+ </form>
+</div> \ No newline at end of file
diff --git a/portal-FE-common/src/app/pages/widget-onboarding/widget-details-dialog/widget-details-dialog.component.scss b/portal-FE-common/src/app/pages/widget-onboarding/widget-details-dialog/widget-details-dialog.component.scss
new file mode 100644
index 00000000..7f5b871e
--- /dev/null
+++ b/portal-FE-common/src/app/pages/widget-onboarding/widget-details-dialog/widget-details-dialog.component.scss
@@ -0,0 +1,82 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software 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.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * 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============================================
+ *
+ *
+ */
+
+::ng-deep .modal-dialog {
+ max-width: 700px;
+ width: 619px;
+ overflow-x: auto;
+ overflow-y: auto;
+}
+
+::ng-deep .widget-applications-select {
+ width: 34em;
+}
+
+::ng-deep .widget-roles-select {
+ width: 34em;
+ }
+
+::ng-deep .widget-service-select {
+ width: 34em;
+ }
+
+.widget-name-field{
+ width: 22em;
+ margin-top: 5px;
+}
+
+.widgets-details-input-desc {
+ overflow: auto;
+ resize: vertical;
+ width: 34em;
+ margin-top: 5px;
+}
+
+.widget-upload{
+ margin-top: 16px;
+}
+
+#applicationName{
+ width: 100%;
+ margin-top: 5px;
+}
+
+#serviceEndPoint{
+ width: 100%;
+ margin-top: 5px;
+} \ No newline at end of file
diff --git a/portal-FE-common/src/app/pages/widget-onboarding/widget-details-dialog/widget-details-dialog.component.spec.ts b/portal-FE-common/src/app/pages/widget-onboarding/widget-details-dialog/widget-details-dialog.component.spec.ts
new file mode 100644
index 00000000..411da1e9
--- /dev/null
+++ b/portal-FE-common/src/app/pages/widget-onboarding/widget-details-dialog/widget-details-dialog.component.spec.ts
@@ -0,0 +1,63 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software 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.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * 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 { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { WidgetDetailsDialogComponent } from './widget-details-dialog.component';
+
+describe('WidgetDetailsDialogComponent', () => {
+ let component: WidgetDetailsDialogComponent;
+ let fixture: ComponentFixture<WidgetDetailsDialogComponent>;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ WidgetDetailsDialogComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(WidgetDetailsDialogComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/portal-FE-common/src/app/pages/widget-onboarding/widget-details-dialog/widget-details-dialog.component.ts b/portal-FE-common/src/app/pages/widget-onboarding/widget-details-dialog/widget-details-dialog.component.ts
new file mode 100644
index 00000000..a6d6115f
--- /dev/null
+++ b/portal-FE-common/src/app/pages/widget-onboarding/widget-details-dialog/widget-details-dialog.component.ts
@@ -0,0 +1,429 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software 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.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * 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, Input, Output, EventEmitter} from '@angular/core';
+import { IWidget } from 'src/app/shared/model/widget-onboarding/widget';
+import { NgbActiveModal, NgbModal } from '@ng-bootstrap/ng-bootstrap';
+import { WidgetOnboardingService, MicroserviceService, AdminsService, ApplicationsService } from 'src/app/shared/services';
+import { FormBuilder, FormGroup, FormControl } from '@angular/forms';
+import { IMircroservies } from 'src/app/shared/model/microservice-onboarding/microservices';
+import { ConfirmationModalComponent } from 'src/app/modals/confirmation-modal/confirmation-modal.component';
+import { InformationModalComponent } from 'src/app/modals/information-modal/information-modal.component';
+
+@Component({
+ selector: 'app-widget-details-dialog',
+ templateUrl: './widget-details-dialog.component.html',
+ styleUrls: ['./widget-details-dialog.component.scss']
+})
+export class WidgetDetailsDialogComponent implements OnInit {
+ @Input() public widget: IWidget;
+ @Input() public availableMicroServices: Array<IMircroservies>;
+ @Input() public applicationList: Array<Object>;
+
+ @Output() passEntry: EventEmitter<any> = new EventEmitter();
+
+ widgetsList: any;
+ uploadForm: FormGroup;
+ result: any;
+ selected: any;
+ isEditMode: boolean = false;
+ hasSelectedApp: boolean = false;
+ availableApps = [];
+ availableRoles = [];
+ allRoleSelected: boolean = false;
+ appCounter = 0;
+ duplicatedName:boolean = true;
+ widgetFileTypeError:boolean = false;
+ isFileNotSelected:boolean = true;
+
+ constructor(public widgetOnboardingService: WidgetOnboardingService,
+ public microservice: MicroserviceService, public applicationsService: ApplicationsService,
+ public formBuilder: FormBuilder, public activeModal: NgbActiveModal,
+ public ngbModal: NgbModal, public adminsService: AdminsService) { }
+
+ ngOnInit() {
+ this.widget.allUser = true;
+ this.getOnboardingWidgets();
+ this.getAvailableApps();
+ this.duplicatedName = true;
+ this.allRoleSelected = false;
+ this.appCounter = 0;
+ this.uploadForm = this.formBuilder.group({
+ profile: [''],
+ widgetName:[''],
+ description:[''],
+ serviceEndPoint:[''],
+ allowAllUser:[''],
+ applicationName:[''],
+ applicationRole:['']
+ });
+
+ if(this.widget && this.widget.name){
+ this.isEditMode = true;
+ }
+ if(this.isEditMode && this.widget && this.widget.allowAllUser == "Y"){
+ this.widget.allUser = true;
+ }else if(this.isEditMode && this.widget && this.widget.allowAllUser == "N"){
+ this.widget.allUser = false;
+ }
+ if(this.widget && this.widget.serviceId != null){
+ this.widget.serviceURL = this.widget.serviceId;
+ }
+ }
+
+ //Add Or Update Widget.
+ saveChanges(){
+ if(this.widget.name == '' || this.widget.name == undefined){
+ this.openConfirmationModal("Error",'Widget Name is required.');
+ return;
+ }
+
+ if(!this.isEditMode){
+ this.updateWidgetName();
+ }
+
+ if(this.duplicatedName == false){
+ this.openConfirmationModal("Error",'Name not available - please choose different name.');
+ return;
+ }
+
+ if(this.widgetFileTypeError == true){
+ this.openConfirmationModal("Error",'File must be .zip');
+ return;
+ }
+
+ let widgetName = this.widget.name;
+ let description = this.widget.desc
+ let file_loc = widgetName + ".zip";
+ const formData = new FormData();
+ formData.append('file', this.uploadForm.get('profile').value);
+ //console.log("FormData >>>>::> ",formData.get('file'));
+
+ /*if((formData == undefined && !this.isEditMode) ||
+ (!this.widget.allUser && this.appCounter == 0) ||
+ this.widget.name == null ||
+ (!this.widget.allUser && !this.allRoleSelected)){
+ console.log("return from 2nd check");
+ return;
+ }*/
+
+ let selectedRoles = [];
+
+ if(!this.widget.allUser){
+ for(var i = 0; i < this.availableApps.length; i++){
+ if(this.availableApps[i].isSelected){
+ for(var n = 0; n < this.availableApps[i].roles.length; n++) {
+ if(this.availableApps[i].roles[n].isSelected){
+ var role = {
+ app: {appId: this.availableApps[i].id},
+ roleId: this.availableApps[i].roles[n].id,
+ roleName: this.availableApps[i].roles[n].name,
+ };
+ selectedRoles.push(role);
+ }
+ }
+ }
+ }
+ }
+
+ let allowAllUser = 0;
+ if(this.widget.allUser){
+ allowAllUser = 1;
+ }
+
+ let serviceId = null;
+ if(this.widget.serviceURL != null && this.widget.serviceURL != undefined){
+ serviceId = parseInt(this.widget.serviceURL);
+ }
+ var newWidget = {
+ name: widgetName,
+ desc: description,
+ widgetRoles: selectedRoles,
+ fileLocation: file_loc,
+ allowAllUser: allowAllUser,
+ serviceId: serviceId
+ };
+
+ if(this.isEditMode){
+ //console.log("widget in updateWidget :::: >>> ",newWidget);
+ if(formData && formData.get('file')){
+ this.widgetOnboardingService.updateWidgetWithFile(formData, this.widget.id, newWidget)
+ .subscribe( _data => {
+ this.result = 'updated';
+ this.passEntry.emit(this.result);
+ }, error => {
+ console.log(error);
+ this.openConfirmationModal("Error",'Could not update. Please retry.');
+ });
+ }else{
+ this.widgetOnboardingService.updateWidget(this.widget.id, newWidget)
+ .subscribe( _data => {
+ this.result = 'updated';
+ this.passEntry.emit(this.result);
+ }, error => {
+ this.openConfirmationModal("Error",'Could not update. Please retry.');
+ console.log(error);
+ });
+ }
+ }else{
+ //console.log("newWidget in createWidget :::: >>> ",newWidget);
+ this.widgetOnboardingService.createWidget(newWidget, formData)
+ .subscribe( _data => {
+ this.result = 'created';
+ this.passEntry.emit(this.result);
+ }, error => {
+ this.openConfirmationModal("Error",'Could not save. Please retry.');
+ console.log(error);
+ });
+ }
+ this.ngbModal.dismissAll();
+ }
+
+ onFileSelect(event) {
+ this.widgetFileTypeError = false;
+ this.isFileNotSelected = false;
+ if (event.target.files.length > 0) {
+ const file = event.target.files[0];
+ //console.log("onFileSelect called.. ",file);
+ var fileName = file.name;
+ var validFormats = ['zip'];
+ var ext = fileName.substring(fileName.lastIndexOf('.') + 1).toLowerCase();
+ if(validFormats.indexOf(ext) == -1){
+ this.widgetFileTypeError = true;
+ }
+ this.uploadForm.get('profile').setValue(file);
+ }
+ }
+
+ appUpdate(){
+ this.hasSelectedApp = false;
+ this.appCounter = 0;
+ for(var i = 0; i < this.availableApps.length; i++){
+ if(this.availableApps[i].isSelected){
+ this.appCounter++;
+ if(!this.hasSelectedApp)
+ this.hasSelectedApp = true;
+ }
+ if(this.availableApps[i].isSelected
+ && this.availableApps[i].roles.length == 0){
+ var index = i;
+ this.availableRoles = [];
+ this.adminsService.getRolesByApp(this.availableApps[i].id)
+ .subscribe( roles => {
+ if(roles && roles.length >0){
+ for(var i = 0; i < roles.length; i++){
+ this.availableRoles.push({
+ id: roles[i].id,
+ name: roles[i].name,
+ isSelected: false,
+ });
+ }
+ }
+ this.availableApps[index].roles = this.availableRoles;
+ }, error => {
+ console.log(error);
+ });
+ }
+ }
+ this.allRoleSelected = true;
+ this.checkRoleSelected();
+ }
+
+ roleUpdate(app){
+ this.allRoleSelected = true;
+ for(var i = 0; i < app.roles.length; i++){
+ if(app.roles[i].isSelected){
+ app.roleSelected = true;
+ this.checkRoleSelected();
+ return;
+ }
+ }
+ app.roleSelected = false;
+ this.checkRoleSelected();
+ }
+
+ checkRoleSelected(){
+ for(var i = 0; i < this.availableApps.length; i++){
+ if(this.availableApps[i].isSelected
+ && !this.availableApps[i].roleSelected){
+ this.allRoleSelected = false;
+ return;
+ }
+ }
+ }
+
+ getAppName = function(appId){
+ for(var i = 0; i < this.availableApps.length; i++){
+ if(this.availableApps[i].id == appId){
+ return this.availableApps[i].name;
+ }
+ }
+ }
+
+ updateWidgetName(){
+ for(var i = 0; i < this.widgetsList.length; i++){
+ if(this.widget.name && this.widget.name.toUpperCase() == this.widgetsList[i].name.toUpperCase()){
+ this.duplicatedName = false;
+ return;
+ }
+ }
+ this.duplicatedName = true;
+ }
+
+ getOnboardingWidgets(){
+ this.widgetOnboardingService.getManagedWidgets()
+ .subscribe(_data => {
+ this.result = _data
+ if(!(_data instanceof Array)){
+ return;
+ }
+ if (this.result == null || this.result == 'undefined') {
+ console.log('WidgetOnboardingService::getOnboardingWidgets Failed: Result or result.data is null');
+ }else {
+ this.widgetsList = _data;
+ }
+ }, error =>{
+ console.log(error);
+ });
+ }
+
+ getAvailableApps(){
+ if(this.isEditMode == false){
+ this.availableApps=[];
+ this.applicationsService.getAppsForSuperAdminAndAccountAdmin()
+ .subscribe(apps => {
+ this.availableApps=[];
+ for(var i=0;i<apps.length;i++) {
+ if (!apps[i].restrictedApp) {
+ this.availableApps.push({
+ id: apps[i].id,
+ name: apps[i].name,
+ roles: [],
+ roleSelected: false,
+ isSelected: false,
+ });
+ }
+ }
+ }, error =>{
+ console.log(error);
+ });
+ }else if(this.isEditMode == true){
+ if(this.widget.allowAllUser == "Y"){
+ this.widget.allUser = true;
+ }
+ this.applicationsService.getAppsForSuperAdminAndAccountAdmin()
+ .subscribe(apps => {
+ this.availableApps=[];
+ let selectedApps = {};
+ var availableApps = this.availableApps;
+ this.allRoleSelected = true;
+ for(var i=0; i < this.widget.widgetRoles.length; i++){
+ if(selectedApps[this.widget.widgetRoles[i].app.appId] != undefined)
+ selectedApps[this.widget.widgetRoles[i].app.appId] += this.widget.widgetRoles[i].roleId + ";" + this.widget.widgetRoles[i].roleName + ";";
+ else{
+ selectedApps[this.widget.widgetRoles[i].app.appId] = this.widget.widgetRoles[i].roleId + ";" + this.widget.widgetRoles[i].roleName + ";";
+ this.appCounter++;
+ }
+ }
+ apps.forEach(function(app, index){
+ availableApps.push({
+ id: app.id,
+ name: app.name,
+ roles: [],
+ roleSelected: false,
+ isSelected: false,
+ });
+ if(selectedApps[app.id] != undefined){
+ this.adminsService.getRolesByApp(app.id)
+ .subscribe(roles => {
+ var role = selectedApps[app.id].split(';');
+ var selectedRoles = [];
+ var n = 0;
+ while((n+1) < role.length){
+ selectedRoles.push({
+ id: role[n++],
+ name: role[n++],
+ isSelected: true,
+ });
+ }
+ for(var m = 0; m < roles.length; m++){
+ var hasSelected = true;
+ for(var n = 0; n < selectedRoles.length; n++){
+ if(selectedRoles[n].id == roles[m].id){
+ hasSelected = false;
+ break;
+ }
+ }
+ if(hasSelected){
+ selectedRoles.push({
+ id: roles[m].id,
+ name: roles[m].name,
+ isSelected: false,
+ });
+ }
+ }
+ availableApps[index].roleSelected = true;
+ availableApps[index].isSelected = true;
+ availableApps[index].roles = selectedRoles;
+ }, error =>{
+ console.log(error);
+ });
+ }
+ })
+
+ }, error =>{
+ console.log(error);
+ });
+ }
+ //console.log("this.availableApps :: ",this.availableApps);
+ }
+
+ openConfirmationModal(_title: string, _message: string) {
+ const modalInfoRef = this.ngbModal.open(ConfirmationModalComponent);
+ modalInfoRef.componentInstance.title = _title;
+ modalInfoRef.componentInstance.message = _message;
+ }
+
+ openInformationModal(_title: string, _message: string){
+ const modalInfoRef = this.ngbModal.open(InformationModalComponent);
+ modalInfoRef.componentInstance.title = _title;
+ modalInfoRef.componentInstance.message = _message;
+ return modalInfoRef;
+ }
+
+}
diff --git a/portal-FE-common/src/app/pages/widget-onboarding/widget-onboarding.component.html b/portal-FE-common/src/app/pages/widget-onboarding/widget-onboarding.component.html
new file mode 100644
index 00000000..43065545
--- /dev/null
+++ b/portal-FE-common/src/app/pages/widget-onboarding/widget-onboarding.component.html
@@ -0,0 +1,100 @@
+<!--
+ ============LICENSE_START==========================================
+ ONAP Portal
+ ===================================================================
+ Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ ===================================================================
+
+ Unless otherwise specified, all software contained herein is licensed
+ under the Apache License, Version 2.0 (the "License");
+ you may not use this software 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.
+
+ Unless otherwise specified, all documentation contained herein is licensed
+ under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ you may not use this documentation except in compliance with the License.
+ You may obtain a copy of the License at
+
+ https://creativecommons.org/licenses/by/4.0/
+
+ Unless required by applicable law or agreed to in writing, documentation
+ 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============================================
+
+ -->
+
+<div class="container">
+ <div class="ecomp-main-view-title">
+ <h1>Widget Onboarding</h1>
+ </div>
+
+ <div class="c-ecomp-abs-select default">
+ <div class="table-dropdown">
+ <mat-form-field class="widget-application-select">
+ <mat-label> Select Application </mat-label>
+ <mat-select name="widget-application-select" [(ngModel)]="filterByApp" #appId="ngModel" (ngModelChange)="applyAppFilter($event)">
+ <mat-option *ngFor="let rowData of applicationList" [value]="rowData">{{rowData.title}}</mat-option>
+ </mat-select>
+ </mat-form-field>
+
+ <mat-form-field>
+ <input matInput type="text" (keyup)="applyFilter($event.target.value)" placeholder="Search in entire table">
+ </mat-form-field>
+
+ <button type="button" class="btn btn-primary" (click)="openAddWigetModal('')">
+ <i class="icon ion-md-person-add"></i>Add Widget
+ </button>
+ </div>
+ </div>
+
+ <table mat-table [dataSource]="dataSource" matSort>
+ <!-- Wiget Name Column -->
+ <ng-container matColumnDef="widgetName">
+ <th id="col1" mat-header-cell *matHeaderCellDef> Widget Name </th>
+ <td (click)="openAddWigetModal(element)" id="rowheader_t1_{{i}}-widgetName"
+ mat-cell *matCellDef="let element; let i = index;"> {{element.name}}
+ </td>
+ </ng-container>
+
+ <!-- Application Name Column -->
+ <ng-container matColumnDef="application">
+ <th id="col2" mat-header-cell *matHeaderCellDef> Application </th>
+ <td (click)="openAddWigetModal(element)" id="rowheader_t1_{{i}}-application"
+ mat-cell *matCellDef="let element; let i=index;"> {{element.appContent}} </td>
+ </ng-container>
+
+ <!-- Download URL -->
+ <ng-container matColumnDef="download">
+ <th id="col3" mat-header-cell *matHeaderCellDef> Download </th>
+ <td id="rowheader_t1_{{$index}}-download" mat-cell *matCellDef="let element; let i=index;">
+ <i class="icon ion-md-download" (click)="downloadWidget(element)"></i>
+ </td>
+ </ng-container>
+
+ <!-- Delete Column -->
+ <ng-container matColumnDef="delete">
+ <th id="col4" mat-header-cell *matHeaderCellDef> Delete </th>
+ <td id="rowheader_t1_{{i}}" mat-cell *matCellDef="let element; let i=index;">
+ <span class="icon-trash" id="{{i}}-button-portal-admin-remove" (click)="removeWidget(element)">
+ <i class="icon ion-md-trash"></i>
+ </span>
+ </td>
+ </ng-container>
+
+ <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
+ <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
+ </table>
+ <mat-paginator [pageSizeOptions]="[10, 20]" showFirstLastButtons></mat-paginator>
+</div>
diff --git a/portal-FE-common/src/app/pages/widget-onboarding/widget-onboarding.component.scss b/portal-FE-common/src/app/pages/widget-onboarding/widget-onboarding.component.scss
new file mode 100644
index 00000000..b87b7abf
--- /dev/null
+++ b/portal-FE-common/src/app/pages/widget-onboarding/widget-onboarding.component.scss
@@ -0,0 +1,62 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software 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.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * 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============================================
+ *
+ *
+ */
+
+.container th{
+ padding-bottom: 15px;
+ font-weight: bold;
+}
+
+::ng-deep .mat-form-field-infix {
+ width: 200px;
+}
+
+::ng-deep .widget-application-select {
+ display: inline-block;
+ position: relative;
+ text-align: left;
+ margin-left: 10px;
+ margin-right: 110px;
+}
+
+.ion-md-download{
+ cursor: pointer;
+}
+
+.ion-md-trash{
+ cursor: pointer;
+} \ No newline at end of file
diff --git a/portal-FE-common/src/app/pages/widget-onboarding/widget-onboarding.component.spec.ts b/portal-FE-common/src/app/pages/widget-onboarding/widget-onboarding.component.spec.ts
new file mode 100644
index 00000000..2fd7ef27
--- /dev/null
+++ b/portal-FE-common/src/app/pages/widget-onboarding/widget-onboarding.component.spec.ts
@@ -0,0 +1,62 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software 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.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * 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 { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { WidgetOnboardingComponent } from './widget-onboarding.component';
+
+describe('WidgetOnboardingComponent', () => {
+ let component: WidgetOnboardingComponent;
+ let fixture: ComponentFixture<WidgetOnboardingComponent>;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ WidgetOnboardingComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(WidgetOnboardingComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/portal-FE-common/src/app/pages/widget-onboarding/widget-onboarding.component.ts b/portal-FE-common/src/app/pages/widget-onboarding/widget-onboarding.component.ts
new file mode 100644
index 00000000..d87791f6
--- /dev/null
+++ b/portal-FE-common/src/app/pages/widget-onboarding/widget-onboarding.component.ts
@@ -0,0 +1,311 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software 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.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * 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, Input, ChangeDetectionStrategy } from '@angular/core';
+import { MatTableDataSource } from '@angular/material';
+import { MatSort, MatPaginator } from '@angular/material';
+import { WidgetOnboardingService, MicroserviceService } from '../../shared/services/index';
+import { IMircroservies } from 'src/app/shared/model/microservice-onboarding/microservices';
+import { IWidget } from 'src/app/shared/model/widget-onboarding/widget';
+import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
+import { HttpClient } from '@angular/common/http';
+import { WidgetDetailsDialogComponent } from './widget-details-dialog/widget-details-dialog.component';
+import { ConfirmationModalComponent } from 'src/app/modals/confirmation-modal/confirmation-modal.component';
+import { InformationModalComponent } from 'src/app/modals/information-modal/information-modal.component';
+
+@Component({
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ selector: 'app-widget-onboarding',
+ templateUrl: './widget-onboarding.component.html',
+ styleUrls: ['./widget-onboarding.component.scss']
+})
+export class WidgetOnboardingComponent implements OnInit {
+
+ widgetsList: Array<IWidget> = [];
+ applicationList: Array<Object> = [];
+ availableMicroServices: Array<IMircroservies> = [];
+ displayedColumns: string[] = ['widgetName', 'application', 'download','delete'];
+ isCommError: boolean = false;
+ dataSource = new MatTableDataSource(this.widgetsList);
+ @ViewChild(MatSort) sort: MatSort;
+ @ViewChild(MatPaginator) paginator: MatPaginator;
+
+ isEditMode: boolean = false;
+ result: any;
+
+
+ constructor( public widgetOnboardingService: WidgetOnboardingService,
+ public microservice: MicroserviceService,public ngbModal: NgbModal) { }
+
+ ngOnInit() {
+ this.prepareApplicationRoleName();
+ this.getOnboardingWidgets();
+ this.populateAvailableApps();
+ this.getAvailableMicroServices();
+ }
+
+ getOnboardingWidgets(){
+ this.isCommError = false;
+ this.widgetOnboardingService.getManagedWidgets()
+ .subscribe(_data => {
+ this.result = _data
+ if(!(_data instanceof Array)){
+ this.isCommError = true;
+ return;
+ }
+ //console.log("getOnboardingWidgets Data :: ", _data);
+ if (this.result == null || this.result == 'undefined') {
+ console.log('WidgetOnboardingService::getOnboardingWidgets Failed: Result or result.data is null');
+ }else {
+ let reSortedWidget = _data.sort(this.getSortOrder("name"));
+ this.widgetsList = reSortedWidget;
+ this.prepareApplicationRoleName();
+ this.populateTableData(this.widgetsList);
+ }
+ }, error =>{
+ console.log(error);
+ });
+ }
+
+ //Refactor this into a directive
+ getSortOrder(prop){
+ return function(a, b) {
+ if (a[prop].toLowerCase() > b[prop].toLowerCase()) {
+ return 1;
+ } else if (a[prop].toLowerCase() < b[prop].toLowerCase()) {
+ return -1;
+ }
+ return 0;
+ }
+ }
+
+ removeWidget(widget: IWidget) {
+ let confirmationMsg = 'You are about to delete this Widget : ' + widget.name+ '. Click OK to continue.';
+ this.openInformationModal("Confirmation",confirmationMsg).result.then((result) => {
+ if (result === 'Ok') {
+ if(!widget || widget == null){
+ console.log('WidgetOnboardingCtrl::deleteService: No widget or ID... cannot delete');
+ return;
+ }
+
+ this.widgetsList.splice(this.widgetsList.indexOf(widget), 1);
+
+ this.widgetOnboardingService.deleteWidget(widget.id)
+ .subscribe( _data => {
+ this.result = _data;
+ this.openConfirmationModal("Success",'Widget deleted successfully');
+ }, error => {
+ console.log(error);
+ });
+
+ this.populateTableData(this.widgetsList);
+ }
+ }, (resut) => {
+ this.openConfirmationModal('Error', resut);
+ return;
+ })
+ }
+
+
+ openAddWigetModal(rowData:any){
+ //console.log("openAddWigetModal getting called...");
+ const modalRef = this.ngbModal.open(WidgetDetailsDialogComponent, { size: 'lg' });
+ modalRef.componentInstance.widget = rowData;
+ modalRef.componentInstance.availableMicroServices = this.availableMicroServices;
+ modalRef.componentInstance.applicationList = this.applicationList;
+ modalRef.componentInstance.widgetsList = this.widgetsList;
+ if(rowData != 'undefined' && rowData){
+ this.isEditMode = true;
+ }else{
+ modalRef.componentInstance.widget = {};
+ this.isEditMode = false;
+ }
+ modalRef.componentInstance.passEntry.subscribe((receivedEntry: any) => {
+ //console.log("receivedEntry >>> ",receivedEntry);
+ if(receivedEntry){
+ this.widgetsList = [];
+ this.getOnboardingWidgets();
+ }
+ });
+ }
+
+ applyFilter(filterValue: string) {
+ this.dataSource.filter = filterValue.trim().toLowerCase();
+ }
+
+ applyAppFilter(event) {
+ let filterByApp = event.title;
+ if(filterByApp == 'All Applications'){
+ this.getOnboardingWidgets();
+ }else{
+ this.dataSource.filter = filterByApp.trim().toLowerCase();
+ }
+ }
+
+ downloadWidget(widget){
+ this.widgetOnboardingService.downloadWidgetFile(widget.id)
+ .subscribe(res => {
+ var data = res;
+ //console.log("downloadWidgetFile response :: ",data);
+ var filename = widget.name + ".zip";
+ if (data == undefined || data == null){
+ this.openConfirmationModal("Could not download. Please retry.", '');
+ return;
+ }
+ var a = document.createElement('a');
+ var blob = new Blob([data], {type: 'application/octet-stream'});
+ var url = window.URL.createObjectURL(blob);
+ a.href = url;
+ a.download = filename;
+ document.body.appendChild(a);
+ a.click();
+
+ setTimeout(function(){
+ document.body.removeChild(a);
+ window.URL.revokeObjectURL(url);
+ }, 100);
+
+ }, error =>{
+ console.log(error);
+ this.openConfirmationModal("Could not download. Please retry.", error.message);
+ });
+ }
+
+
+ populateTableData(wigetList: Array<IWidget>){
+ this.dataSource = new MatTableDataSource(wigetList);
+ this.dataSource.sort = this.sort;
+ this.dataSource.paginator = this.paginator;
+ };
+
+ prepareApplicationRoleName(){
+ if(this.widgetsList && this.widgetsList.length > 0){
+ for(var i = 0; i < this.widgetsList.length; i++){
+ let set = new Set();
+ var info = "";
+ var appContent = [];
+ var appName = [];
+ if(this.widgetsList[i].widgetRoles && this.widgetsList[i].widgetRoles.length >0){
+ for(var n = 0; n < this.widgetsList[i].widgetRoles.length; n++){
+ if(this.widgetsList[i].widgetRoles[n].app)
+ set.add(this.widgetsList[i].widgetRoles[n].app.appName);
+ }
+ set.forEach(function (item) {
+ info = item.toString() + " - ";
+ for(var n = 0; n < this.widgetsList[i].widgetRoles.length; n++){
+ if(this.widgetsList[i].widgetRoles[n].app && item.toString() == this.widgetsList[i].widgetRoles[n].app.appName){
+ info += this.widgetsList[i].widgetRoles[n].roleName + "; ";
+ }
+ }
+ appContent.push(info);
+ appName.push(item.toString());
+ }.bind(this));
+ }
+ if(this.widgetsList[i].allowAllUser == "Y"){
+ info = "All Applications";
+ appContent.push("All Applications");
+ appName.push("All Applications");
+ }
+ this.widgetsList[i].appContent = appContent;
+ this.widgetsList[i].appName = appName;
+ }
+ }
+ }
+
+ populateAvailableApps(){
+ this.widgetOnboardingService.populateAvailableApps()
+ .subscribe( _data => {
+ this.applicationList.push({
+ index: 0,
+ title: 'All Applications',
+ value: ''
+ })
+ var reSortedApp = _data.sort(this.getSortOrder("name"));
+ var realAppIndex = 1;
+ for (let i = 1; i <= reSortedApp.length; i++) {
+ if (!reSortedApp[i-1].restrictedApp) {
+ if(_data[i - 1].name && _data[i - 1].name!=""){
+ this.applicationList.push({
+ index: realAppIndex,
+ title: _data[i - 1].name,
+ value: _data[i - 1].id
+ })
+ }
+ realAppIndex = realAppIndex + 1;
+ }
+ }
+ }, error => {
+ console.log(error);
+ });
+ }
+
+ getAvailableMicroServices = () =>{
+ this.availableMicroServices = [];
+ this.microservice.getServiceList()
+ .subscribe(_data => {
+ this.result = _data;
+ if (this.result == null || this.result == 'undefined') {
+ console.log('MicroserviceService::getAvailableMicroServices Failed: Result or result.data is null');
+ }else {
+ for(var i = 0; i < _data.length; i++){
+ this.availableMicroServices.push({
+ id: _data[i].id,
+ name: _data[i].name,
+ option: _data[i].name + ": " + _data[i].url
+ });
+ }
+ }
+ }, error =>{
+ console.log(error);
+ });
+ }
+
+ openConfirmationModal(_title: string, _message: string) {
+ const modalInfoRef = this.ngbModal.open(ConfirmationModalComponent);
+ modalInfoRef.componentInstance.title = _title;
+ modalInfoRef.componentInstance.message = _message;
+ }
+
+ openInformationModal(_title: string, _message: string){
+ const modalInfoRef = this.ngbModal.open(InformationModalComponent);
+ modalInfoRef.componentInstance.title = _title;
+ modalInfoRef.componentInstance.message = _message;
+ return modalInfoRef;
+ }
+
+}