--- /dev/null
+# Copyright 2020 TATA ELXSI
+#
+# 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.
+#
+# Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+
+# Editor configuration, see https://editorconfig.org
+root = true
+
+[*]
+charset = utf-8
+indent_style = space
+indent_size = 2
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.md]
+max_line_length = off
+trim_trailing_whitespace = false
--- /dev/null
+# Copyright 2020 TATA ELXSI
+#
+# 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.
+#
+# Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+# See http://help.github.com/ignore-files/ for more about ignoring files.
+
+# compiled output
+/dist
+/tmp
+/out-tsc
+
+# dependencies
+/node_modules
+package-lock.json
+
+# profiling files
+chrome-profiler-events.json
+speed-measure-plugin.json
+
+# IDEs and editors
+/.idea
+.project
+.classpath
+.c9/
+*.launch
+.settings/
+*.sublime-workspace
+
+# IDE - VSCode
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+.history/*
+
+# misc
+/.sass-cache
+/connect.lock
+/coverage
+/libpeerconnection.log
+npm-debug.log
+yarn-error.log
+testem.log
+/typings
+
+# System Files
+.DS_Store
+Thumbs.db
-# Copyright 2020 ETSI
-#
# 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
# See the License for the specific language governing permissions and
# limitations under the License.
-FROM ubuntu:18.04
+# This Dockerfile is intented for devops and deb package generation
+#
+# Use Dockerfile.local for running osm/NBI in a docker container from source
+# Use Dockerfile.fromdeb for running osm/NBI in a docker container from last stable package
+
+
+FROM ubuntu:16.04
-RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get -y install git \
- make python3 debhelper python3-setuptools apt-utils
+RUN apt-get update && apt-get -y install git make libcurl4-gnutls-dev \
+ libgnutls-dev debhelper apt-utils dh-make
+
+
\ No newline at end of file
<!--
-Copyright 2020 ETSI
+Copyright 2020 TATA ELXSI
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
+ 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.
+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
+limitations under the License.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
-->
-# Project Title
-One Paragraph of project description goes here
+## Angular Based OSM NG UI
+This project focuses on the implementation of a web GUI to interact with the Northbound API of OSM.
+
+The project is based on ([Angular](https://angular.io/)), a One framework for Mobile & desktop, app-design framework and development platform for creating efficient and sophisticated single-page web apps.
+
+## Table of Contents
+
+* [Community](#community)
+* [Getting Started](#getting-started)
+* [Prerequisites](#prerequisites)
+* [Installation](#installation)
+* [Running the application](#running-the-application)
+* [Check the lint](#check-the-lint)
+* [Supported Browsers](#supported-browsers)
+* [Deployment](#deployment)
+* [Built With](#built-with)
+* [Contributing](#contributing)
+* [Versioning](#versioning)
+* [License](#license)
+
+## Community
+
+Contact [kumaran.m@tataelxsi.co.in](mailto:kumaran.m@tataelxsi.co.in), [rajesh.s@tataelxsi.co.in](mailto:rajesh.s@tataelxsi.co.in), [barath.r@tataelxsi.co.in](mailto:barath.r@tataelxsi.co.in) for architecture and design discussions, requests for help, features request and bug reports on NG UI.
## Getting Started
-These instructions will get you a copy of the project up and running on your local machine for development and testing purposes. See deployment for notes on how to deploy the project on a live system.
+Following instructions in the sections below will get you a copy of the project up and running on your local machine for development and testing purposes. See Deployment section for notes on how to deploy the project on a live system.
### Prerequisites
-What things you need to install the software and how to install them
+Angular Setup, Install, & Build Guide
-```
-Give examples
-```
+1. Install Node.js from [here](https://nodejs.org/en/download/)
+To check if nodejs is installed on your system, type below command. This will help you see the version of nodejs currently installed on your system.
+`node -version`
+After downloading Node.js, the node package manager (npm) should automatically be installed. Test it out by doing:
+`npm --version`
+2. Install Angluar CLI. [More details](https://cli.angular.io/) Angular can be installed Globally (or) Locally,
+Install Globally
+`npm install -g @angular/cli`
+Install Locally
+`npm install @angular/cli`
+After installation done you can check the version using below command. It will display version details of angular-cli
+`ng version`
-### Installing
+We are done with the installation of Angular
-A step by step series of examples that tell you how to get a development env running
+### Installation
-Say what the step will be
+Clone the NG UI from the repository
-```
-Give the example
-```
+`git clone "https://osm.etsi.org/gerrit/osm/NG-UI"`
-And repeat
+Install the packages
-```
-until finished
-```
+`cd NG-UI`
-End with an example of getting some data out of the system or using it for a little demo
+`npm install`
-## Running the tests
+### Running the application
-Explain how to run the automated tests for this system
+The following instructions is for running NG UI locally for development purpose,
+On the folder project
+
+Open `proxy.conf.json`
+
+Add the below code
+```typescript
+{
+ "/osm/*": {
+ "target": "https://OSM-NBI-IP:9999",
+ "secure": false,
+ "logLevel": "info"
+ }
+}
```
-Give an example
-```
+To run the application give the below command
+
+`npm run proxy`
+- To Run the NG-UI page Navigate to <http://localhost:4200/>
+
+## Check the lint
+
+To check the typescript lint run the below command
+
+`npm run lint`
+
+## Supported Browsers
+
+- Edge (42.17134.1098.0) and IE 11 (Windows)
+- Firefox (75.0)(Ubunutu)
+- Firefox (75.0)(Windows)
+- Chrome (81.0.4044.92) (Ubunutu)
+- Chrome (81.0.4044.122) (Windows)
## Deployment
-Add additional notes about how to deploy this on a live system
+To deploy the NG UI use the [Dockerfile](Dockerfile)
## Built With
-* [Python](www.python.org/) - The language used
+* [Angular Frame work](https://angular.io/) - The languages used are Javascript, Typescript, HTML, and SCSS
## Contributing
## License
This project is licensed under the Apache2 License - see the [LICENSE.md](LICENSE) file for details
-
--- /dev/null
+{
+ "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
+ "version": 1,
+ "newProjectRoot": "projects",
+ "projects": {
+ "osm": {
+ "root": "",
+ "sourceRoot": "src",
+ "projectType": "application",
+ "prefix": "app",
+ "schematics": {
+ "@schematics/angular:component": {
+ "styleext": "scss"
+ }
+ },
+ "architect": {
+ "build": {
+ "builder": "@angular-devkit/build-angular:browser",
+ "options": {
+ "outputPath": "dist/osm",
+ "index": "src/index.html",
+ "main": "src/main.ts",
+ "polyfills": "src/polyfills.ts",
+ "tsConfig": "src/tsconfig.app.json",
+ "assets": [
+ "src/favicon.ico",
+ "src/assets"
+ ],
+ "styles": [
+ "src/assets/scss/style.scss",
+ "node_modules/ol/ol.css",
+ "node_modules/@fortawesome/fontawesome-free/css/all.min.css"
+ ],
+ "scripts": [
+ "src/assets/js/tar.js"
+ ],
+ "es5BrowserSupport": true
+ },
+ "configurations": {
+ "production": {
+ "fileReplacements": [
+ {
+ "replace": "src/environments/environment.ts",
+ "with": "src/environments/environment.prod.ts"
+ }
+ ],
+ "optimization": true,
+ "outputHashing": "all",
+ "sourceMap": false,
+ "extractCss": true,
+ "namedChunks": false,
+ "aot": true,
+ "extractLicenses": true,
+ "vendorChunk": false,
+ "buildOptimizer": true,
+ "budgets": [
+ {
+ "type": "initial",
+ "maximumWarning": "2mb",
+ "maximumError": "5mb"
+ }
+ ]
+ }
+ }
+ },
+ "serve": {
+ "builder": "@angular-devkit/build-angular:dev-server",
+ "options": {
+ "browserTarget": "osm:build"
+ },
+ "configurations": {
+ "production": {
+ "browserTarget": "osm:build:production"
+ }
+ }
+ },
+ "extract-i18n": {
+ "builder": "@angular-devkit/build-angular:extract-i18n",
+ "options": {
+ "browserTarget": "osm:build"
+ }
+ },
+ "test": {
+ "builder": "@angular-devkit/build-angular:karma",
+ "options": {
+ "main": "src/test.ts",
+ "polyfills": "src/polyfills.ts",
+ "tsConfig": "src/tsconfig.spec.json",
+ "karmaConfig": "src/karma.conf.js",
+ "styles": [
+ "src/styles.css",
+ "node_modules/ol/ol.css"
+ ],
+ "scripts": [],
+ "assets": [
+ "src/favicon.ico",
+ "src/assets"
+ ]
+ }
+ },
+ "lint": {
+ "builder": "@angular-devkit/build-angular:tslint",
+ "options": {
+ "tsConfig": [
+ "src/tsconfig.app.json",
+ "src/tsconfig.spec.json"
+ ],
+ "exclude": [
+ "**/node_modules/**"
+ ]
+ }
+ }
+ }
+ },
+ "osm-e2e": {
+ "root": "e2e/",
+ "projectType": "application",
+ "prefix": "",
+ "architect": {
+ "e2e": {
+ "builder": "@angular-devkit/build-angular:protractor",
+ "options": {
+ "protractorConfig": "e2e/protractor.conf.js",
+ "devServerTarget": "osm:serve"
+ },
+ "configurations": {
+ "production": {
+ "devServerTarget": "osm:serve:production"
+ }
+ }
+ },
+ "lint": {
+ "builder": "@angular-devkit/build-angular:tslint",
+ "options": {
+ "tsConfig": "e2e/tsconfig.e2e.json",
+ "exclude": [
+ "**/node_modules/**"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "defaultProject": "osm"
+}
\ No newline at end of file
--- /dev/null
+# Copyright 2020 TATA ELXSI
+#
+# 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.
+#
+# Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+
+# This file is currently used by autoprefixer to adjust CSS to support the below specified browsers
+# For additional information regarding the format and rule options, please see:
+# https://github.com/browserslist/browserslist#queries
+#
+# For IE 9-11 support, please remove 'not' from the last line of the file and adjust as needed
+
+> 0.5%
+last 2 versions
+Firefox ESR
+not dead
+not IE 9-11
\ No newline at end of file
# under the License.
-PKG_DIRECTORIES="lib static template"
-PKG_FILES="LICENSE README.md"
+PKG_DIRECTORIES="nginx src"
+PKG_FILES="angular.json browserslist CONTRIBUTING.md package.json proxy.conf.json tsconfig.json tslint.json LICENSE README.md"
MDG_NAME=ngui
DEB_INSTALL=debian/osm-${MDG_NAME}.install
export DEBEMAIL="gerardo.garciadeblas@telefonica.com"
dh_make -y --indep --createorig --a -c apache
dpkg-buildpackage -uc -us -tc -rfakeroot
popd
-
-
--- /dev/null
+# Copyright 2020 TATA ELXSI
+#
+# 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.
+#
+# Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in), VIJAY NAG (vijaynag.bs@tataelxsi.co.in)
+
+FROM ubuntu:16.04
+# Installing node dependencies.
+RUN apt-get update && apt-get install -y curl xz-utils gnupg2 \
+ && apt-get update && apt-get install -y apt-transport-https \
+ && curl -s https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add - \
+ && echo "deb https://deb.nodesource.com/node_10.x xenial main" | tee -a /etc/apt/sources.list.d/nodesource.list \
+ && echo "deb-src https://deb.nodesource.com/node_10.x xenial main" | tee -a /etc/apt/sources.list.d/nodesource.list \
+ && apt-get update && apt-get install -y nodejs \
+ && apt-get install -y nginx
+
+# Preparing working environment.
+RUN mkdir -p /usr/src/osm-angularapp
+WORKDIR /usr/src/osm-angularapp
+
+# Installing dependencies.
+COPY ./package.json /usr/src/osm-angularapp/
+RUN npm install
+
+# Copy osm-angularapp source into image.
+COPY ./ /usr/src/osm-angularapp
+
+# Building app.
+RUN npm run build
+
+# Removing nginx default page.
+RUN rm -rf /usr/share/nginx/html/*
+
+# Copying nginx configuration.
+COPY nginx/nginx.conf /etc/nginx/sites-available/default
+RUN cp -r /usr/src/osm-angularapp/dist/osm/* /usr/share/nginx/html
+
+# Exposing ports.
+EXPOSE 80
+
+# Starting server.
+CMD ["nginx", "-g", "daemon off;"]
+
--- /dev/null
+# Copyright 2020 TATA ELXSI
+#
+# 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.
+#
+# Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+
+server {
+ listen 80;
+ server_name localhost;
+ root /usr/share/nginx/html;
+ index index.html index.htm;
+ client_max_body_size 15M;
+
+ location /osm {
+ proxy_pass https://nbi:9999;
+ proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
+ proxy_set_header Accept-Encoding "";
+ }
+
+ location / {
+ try_files $uri $uri/ /index.html;
+ }
+}
--- /dev/null
+{
+ "name": "osm",
+ "version": "1.0.2",
+ "scripts": {
+ "ng": "ng",
+ "start": "ng serve",
+ "build": "ng build --prod --aot",
+ "test": "ng test",
+ "lint": "tslint --type-check --project tsconfig.json -c tslint.json",
+ "e2e": "ng e2e",
+ "proxy": "ng serve --proxy-config proxy.conf.json"
+ },
+ "private": true,
+ "dependencies": {
+ "@akveo/ng2-completer": "^9.0.1",
+ "@angular/animations": "~9.1.0",
+ "@angular/cdk": "^7.3.7",
+ "@angular/common": "~9.1.0",
+ "@angular/compiler": "~9.1.0",
+ "@angular/core": "~9.1.0",
+ "@angular/flex-layout": "^9.0.0-beta.29",
+ "@angular/forms": "~9.1.0",
+ "@angular/localize": "^9.1.2",
+ "@angular/platform-browser": "~9.1.0",
+ "@angular/platform-browser-dynamic": "~9.1.0",
+ "@angular/router": "~9.1.0",
+ "@ctrl/ngx-codemirror": "^2.2.1",
+ "@fortawesome/fontawesome-free": "^5.13.0",
+ "@ng-bootstrap/ng-bootstrap": "^5.3.0",
+ "@ng-idle/core": "^8.0.0-beta.4",
+ "@ng-idle/keepalive": "^8.0.0-beta.4",
+ "@ng-select/ng-select": "^3.7.3",
+ "@ngx-translate/core": "^12.1.2",
+ "@ngx-translate/http-loader": "^4.0.0",
+ "@nomadreservations/ngx-codemirror": "^2.0.0",
+ "@types/d3": "^5.7.2",
+ "@types/js-yaml": "^3.12.1",
+ "@types/jsonpath": "^0.2.0",
+ "@types/ol": "^5.3.5",
+ "angular-notifier": "^6.0.1",
+ "bootstrap": "^4.4.1",
+ "chart.js": "^2.8.0",
+ "codemirror": "^5.51.0",
+ "core-js": "^2.5.4",
+ "d3": "^5.9.2",
+ "http-status-codes": "^1.3.2",
+ "js-untar": "^2.0.0",
+ "js-yaml": "^3.13.1",
+ "jsonpath": "^1.0.2",
+ "ng-sidebar": "^9.2.0",
+ "ng2-charts": "^3.0.0-beta.5",
+ "ng2-file-upload": "^1.3.0",
+ "ng2-smart-table": "^1.6.0",
+ "ol": "^5.3.3",
+ "pako": "^1.0.10",
+ "roboto-fontface": "^0.10.0",
+ "rxjs": "^6.5.4",
+ "rxjs-compat": "^6.5.5",
+ "stream": "0.0.2",
+ "text-encoding": "^0.7.0",
+ "tslib": "^1.11.1",
+ "web-animations-js": "^2.3.2",
+ "zone.js": "~0.10.3"
+ },
+ "devDependencies": {
+ "@angular-devkit/build-angular": "~0.901.0",
+ "@angular/cli": "~9.1.0",
+ "@angular/compiler-cli": "~9.1.0",
+ "@angular/language-service": "~9.1.0",
+ "@types/jasmine": "~2.8.8",
+ "@types/jasminewd2": "~2.0.3",
+ "@types/jquery": "^3.3.31",
+ "@types/node": "^8.10.59",
+ "codelyzer": "^5.0.1",
+ "jasmine-core": "~2.99.1",
+ "jasmine-spec-reporter": "~4.2.1",
+ "karma": "~3.1.1",
+ "karma-chrome-launcher": "~2.2.0",
+ "karma-coverage-istanbul-reporter": "~2.0.1",
+ "karma-jasmine": "~1.1.2",
+ "karma-jasmine-html-reporter": "^0.2.2",
+ "ng2-completer": "^3.0.3",
+ "node-sass": "^4.14.1",
+ "protractor": "~5.4.0",
+ "ts-node": "~7.0.0",
+ "tslint": "^5.11.0",
+ "tslint-html-report": "^2.0.3",
+ "tslint-microsoft-contrib": "^6.1.1",
+ "typescript": "~3.8.3"
+ }
+}
--- /dev/null
+{
+ "/osm/*": {
+ "target": "https://nbi:9999",
+ "secure": false,
+ "logLevel": "info"
+ }
+}
\ No newline at end of file
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<router-outlet> </router-outlet>
+<notifier-container></notifier-container>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+
+/**
+ * @file App Components
+ */
+import { Component, HostListener, Injector } from '@angular/core';
+import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
+import { DEFAULT_INTERRUPTSOURCES, Idle } from '@ng-idle/core';
+import { AuthenticationService } from 'AuthenticationService';
+import { DeviceCheckService } from 'DeviceCheckService';
+import { SharedService } from 'SharedService';
+import { isNullOrUndefined } from 'util';
+
+/**
+ * Creating component
+ * @Component takes AppComponent.html as template url
+ */
+@Component({
+ selector: 'app-root',
+ templateUrl: './AppComponent.html',
+ styleUrls: ['./AppComponent.scss']
+})
+/** Exporting a class @exports AppComponent */
+export class AppComponent {
+ /** To inject services @public */
+ public injector: Injector;
+ /** Instance for modal service @public */
+ public modalService: NgbModal;
+ /** Device Check service @private */
+ private deviceCheckService: DeviceCheckService;
+ /** Utilizes auth service for any auth operations @private */
+ private authService: AuthenticationService;
+ /** Handle idle time out service @private */
+ private idle: Idle;
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.idle = this.injector.get(Idle);
+ this.authService = this.injector.get(AuthenticationService);
+ this.modalService = this.injector.get(NgbModal);
+ this.deviceCheckService = this.injector.get(DeviceCheckService);
+ this.handleIdle();
+ this.sharedService = this.injector.get(SharedService);
+ }
+
+ /**
+ * Lifecyle Hooks the trigger before component is instantiate
+ */
+ public ngOnInit(): void {
+ this.sharedService.fetchOSMVersion();
+ }
+
+ /** To handle handleIdle @public */
+ public handleIdle(): void {
+ const idleTime: number = 1200;
+ const idleTimeOutWarning: number = 5;
+ // sets an idle timeout in seconds.
+ this.idle.setIdle(idleTime);
+ //sets a timeout period in seconds. after idleTime seconds of inactivity, the user will be considered timed out.
+ this.idle.setTimeout(idleTimeOutWarning);
+ // sets the default interrupts, in this case, things like clicks, scrolls, touches to the document
+ this.idle.setInterrupts(DEFAULT_INTERRUPTSOURCES);
+ this.idle.watch(true);
+ this.idleTimeOut();
+ }
+
+ /** Method to capture idle time out event @public */
+ public idleTimeOut(): void {
+ this.idle.onTimeout.subscribe(() => {
+ this.idle.stop();
+ if (localStorage.getItem('id_token') !== null) {
+ this.authService.logout();
+ }
+ });
+ }
+
+ /** Handling Window's Storage Hostlistener @public */
+ @HostListener('window:storage', ['$event'])
+ public handleLocalStorageEvent(evt: StorageEvent): void {
+ // On Token Change
+ if (evt.key === 'token_state' && !isNullOrUndefined(evt.key)) {
+ if (evt.oldValue !== evt.newValue) {
+ window.location.reload();
+ }
+ }
+ // On Langauges Change
+ if (evt.key === 'languageCode' && !isNullOrUndefined(evt.key)) {
+ if (evt.oldValue !== evt.newValue) {
+ window.location.reload();
+ }
+ }
+ }
+
+ /** Handling Window's POP State Hostlistener @public */
+ @HostListener('window:popstate', ['$event'])
+ public handleOnPOPState(evt: PopStateEvent): void {
+ this.modalService.dismissAll();
+ }
+
+ /** Handling Window's orientationchange Hostlistener @public */
+ @HostListener('window:resize', ['$event'])
+ public onResize(event: Event): void {
+ this.deviceCheckService.checkDeviceType();
+ }
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file Instance Module file
+ */
+import { CommonModule, LOCATION_INITIALIZED } from '@angular/common';
+import { HTTP_INTERCEPTORS, HttpClient, HttpClientModule } from '@angular/common/http';
+import { APP_INITIALIZER, Injector, NgModule } from '@angular/core';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { BrowserModule } from '@angular/platform-browser';
+import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
+import { RouterModule } from '@angular/router';
+import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateLoader, TranslateModule, TranslateService } from '@ngx-translate/core';
+import { TranslateHttpLoader } from '@ngx-translate/http-loader';
+import { NotifierModule, NotifierOptions } from 'angular-notifier';
+import { AuthInterceptorService } from 'AuthInterceptorService';
+import { HeaderComponent } from 'HeaderComponent';
+import { LayoutComponent } from 'LayoutComponent';
+import { Ng2SmartTableModule } from 'ng2-smart-table';
+import { RestService } from 'RestService';
+import { SidebarComponent } from 'SidebarComponent';
+import { AppComponent } from './AppComponent';
+
+import { appRoutes } from './approutes.module';
+
+import { DataService } from 'DataService';
+import { ProjectService } from 'ProjectService';
+import { SharedService } from 'SharedService';
+
+import { CodemirrorModule } from '@ctrl/ngx-codemirror';
+import { NgSelectModule } from '@ng-select/ng-select';
+
+import { NgIdleKeepaliveModule } from '@ng-idle/keepalive';
+import { AuthenticationService } from 'AuthenticationService';
+import { AuthGuardService } from 'AuthGuardService';
+import { BreadcrumbComponent } from 'BreadCrumb';
+import { ComposePackages } from 'ComposePackages';
+import { ConfirmationTopologyComponent } from 'ConfirmationTopology';
+import { DeleteComponent } from 'DeleteComponent';
+import { DeviceCheckService } from 'DeviceCheckService';
+import { GoToTopDirective } from 'GoToTopDirective';
+import { InstantiateNetSliceTemplateComponent } from 'InstantiateNetSliceTemplate';
+import { InstantiateNsComponent } from 'InstantiateNs';
+import { LoaderModule } from 'LoaderModule';
+import { LoginComponent } from 'LoginComponent';
+import { NetsliceInstancesActionComponent } from 'NetsliceInstancesActionComponent';
+import { NetslicePackagesActionComponent } from 'NetslicePackagesAction';
+import { NSInstancesActionComponent } from 'NSInstancesActionComponent';
+import { NsPackagesActionComponent } from 'NsPackagesAction';
+import { PageNotFoundComponent } from 'PageNotFound';
+import { PDUInstancesActionComponent } from 'PDUInstancesActionComponent';
+import { ProjectLinkComponent } from 'ProjectLinkComponent';
+import { ProjectsActionComponent } from 'ProjectsAction';
+import { SDNControllerActionComponent } from 'SDNControllerActionComponent';
+import { ShowInfoComponent } from 'ShowInfoComponent';
+import { SwitchProjectComponent } from 'SwitchProjectComponent';
+import { UsersActionComponent } from 'UsersActionComponent';
+import { UserSettingsComponent } from 'UserSettingsComponent';
+import { VimAccountsActionComponent } from 'VimAccountsAction';
+import { VNFInstancesActionComponent } from 'VNFInstancesActionComponent';
+import { VNFLinkComponent } from 'VNFLinkComponent';
+import { VNFPackagesActionComponent } from 'VNFPackagesAction';
+import { WIMAccountsActionComponent } from 'WIMAccountsAction';
+
+/**
+ * Custom angular notifier options
+ */
+const customNotifierOptions: NotifierOptions = {
+ position: { horizontal: { position: 'right' }, vertical: { position: 'top' } },
+ behaviour: { autoHide: 3000, onClick: 'hide', onMouseover: 'pauseAutoHide' }
+};
+
+/**
+ * An NgModule is a class adorned with the @NgModule decorator function.
+ * @NgModule takes a metadata object that tells Angular how to compile and run module code.
+ */
+@NgModule({
+ declarations: [
+ AppComponent,
+ LayoutComponent,
+ HeaderComponent,
+ SidebarComponent,
+ LoginComponent,
+ PageNotFoundComponent,
+ VNFPackagesActionComponent,
+ NsPackagesActionComponent,
+ NSInstancesActionComponent,
+ VNFInstancesActionComponent,
+ VNFLinkComponent,
+ NetsliceInstancesActionComponent,
+ BreadcrumbComponent,
+ DeleteComponent,
+ NetslicePackagesActionComponent,
+ UsersActionComponent,
+ VimAccountsActionComponent,
+ ProjectsActionComponent,
+ ProjectLinkComponent,
+ UserSettingsComponent,
+ ShowInfoComponent,
+ InstantiateNetSliceTemplateComponent,
+ InstantiateNsComponent,
+ ConfirmationTopologyComponent,
+ ComposePackages,
+ WIMAccountsActionComponent,
+ PDUInstancesActionComponent,
+ SDNControllerActionComponent,
+ SwitchProjectComponent,
+ GoToTopDirective
+ ],
+ imports: [
+ NotifierModule.withConfig(customNotifierOptions),
+ CommonModule,
+ BrowserModule,
+ BrowserAnimationsModule,
+ FormsModule,
+ ReactiveFormsModule.withConfig({ warnOnNgModelWithFormControl: 'never' }),
+ Ng2SmartTableModule,
+ CodemirrorModule,
+ NgSelectModule,
+ HttpClientModule,
+ TranslateModule.forRoot({
+ loader: {
+ provide: TranslateLoader,
+ useFactory: HttpLoaderFactory,
+ deps: [HttpClient]
+ }
+ }),
+ NgbModule,
+ NgSelectModule,
+ RouterModule.forRoot(appRoutes, { useHash: false }),
+ NgIdleKeepaliveModule.forRoot(),
+ LoaderModule
+ ],
+ providers: [
+ {
+ provide: APP_INITIALIZER,
+ useFactory: appInitializerFactory,
+ deps: [TranslateService, Injector],
+ multi: true
+ },
+ {
+ provide: HTTP_INTERCEPTORS,
+ useClass: AuthInterceptorService,
+ multi: true
+ },
+ RestService,
+ AuthenticationService,
+ AuthGuardService,
+ DataService,
+ ProjectService,
+ SharedService,
+ DeviceCheckService
+ ],
+ bootstrap: [AppComponent],
+ entryComponents: [
+ VNFPackagesActionComponent,
+ NsPackagesActionComponent,
+ NSInstancesActionComponent,
+ VNFInstancesActionComponent,
+ VNFLinkComponent,
+ NetsliceInstancesActionComponent,
+ BreadcrumbComponent,
+ DeleteComponent,
+ NetslicePackagesActionComponent,
+ UsersActionComponent,
+ VimAccountsActionComponent,
+ ProjectsActionComponent,
+ ProjectLinkComponent,
+ UserSettingsComponent,
+ ShowInfoComponent,
+ InstantiateNetSliceTemplateComponent,
+ InstantiateNsComponent,
+ ConfirmationTopologyComponent,
+ ComposePackages,
+ WIMAccountsActionComponent,
+ PDUInstancesActionComponent,
+ SDNControllerActionComponent,
+ SwitchProjectComponent
+ ]
+})
+
+/** Exporting a class @exports AppModule */
+export class AppModule {
+ /** Variables declared to avoid state-less class */
+ private appModule: string;
+}
+
+/**
+ * HttpLoaderFactory is for translate service of the application.
+ */
+// tslint:disable:function-name
+export function HttpLoaderFactory(http: HttpClient): TranslateHttpLoader {
+ const now: number = new Date().getTime();
+ return new TranslateHttpLoader(http, './assets/i18n/', '.json?locale=' + now);
+}
+/**
+ * HttpLoaderFactory is for translate service of the application.
+ */
+// tslint:disable:function-name
+export function appInitializerFactory(translate: TranslateService, injector: Injector): Object {
+ // tslint:disable-next-line: no-any
+ return async (): Promise<any> => {
+ await injector.get(LOCATION_INITIALIZED, Promise.resolve(null));
+ translate.setDefaultLang('en');
+ const languageCode: string = localStorage.getItem('languageCode');
+ if (languageCode !== null && languageCode !== undefined && languageCode !== '') {
+ await translate.use(languageCode).toPromise().catch(() => {
+ translate.setDefaultLang('en');
+ });
+ } else {
+ await translate.use('en').toPromise();
+ localStorage.setItem('languageCode', 'en');
+ }
+ };
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file Routing Module
+ */
+import { Routes } from '@angular/router';
+import { AuthGuardService } from 'AuthGuardService';
+import { LayoutComponent } from 'LayoutComponent';
+import { LoginComponent } from 'LoginComponent';
+import { PageNotFoundComponent } from 'PageNotFound';
+
+/** Exporting a function using Routes @exports AppRoutes */
+export const appRoutes: Routes = [
+ {
+ path: 'login',
+ component: LoginComponent
+ },
+ {
+ path: '',
+ component: LayoutComponent,
+ canActivate: [AuthGuardService],
+ children: [
+ {
+ path: '',
+ // tslint:disable-next-line: no-any
+ loadChildren: async (): Promise<any> => import('./dashboard/DashboardModule')
+ .then((m: typeof import('./dashboard/DashboardModule')) => m.DashboardModule),
+ canActivate: [AuthGuardService]
+ },
+ {
+ path: 'packages',
+ // tslint:disable-next-line: no-any
+ loadChildren: async (): Promise<any> => import('./packages/PackagesModule')
+ .then((m: typeof import('./packages/PackagesModule')) => m.PackagesModule),
+ canActivate: [AuthGuardService]
+ },
+ {
+ path: 'instances',
+ // tslint:disable-next-line: no-any
+ loadChildren: async (): Promise<any> => import('./instances/InstancesModule')
+ .then((m: typeof import('./instances/InstancesModule')) => m.InstancesModule),
+ canActivate: [AuthGuardService]
+ },
+ {
+ path: 'vim',
+ // tslint:disable-next-line: no-any
+ loadChildren: async (): Promise<any> => import('./vim-accounts/VimAccountsModule')
+ .then((m: typeof import('./vim-accounts/VimAccountsModule')) => m.VimAccountsModule),
+ canActivate: [AuthGuardService]
+ },
+ {
+ path: 'wim',
+ // tslint:disable-next-line: no-any
+ loadChildren: async (): Promise<any> => import('./wim-accounts/WIMAccountsModule')
+ .then((m: typeof import('./wim-accounts/WIMAccountsModule')) => m.WIMAccountsModule),
+ canActivate: [AuthGuardService]
+ },
+ {
+ path: 'sdn',
+ // tslint:disable-next-line: no-any
+ loadChildren: async (): Promise<any> => import('./sdn-controller/SDNControllerModule')
+ .then((m: typeof import('./sdn-controller/SDNControllerModule')) => m.SDNControllerModule),
+ canActivate: [AuthGuardService]
+ },
+ {
+ path: 'users',
+ // tslint:disable-next-line: no-any
+ loadChildren: async (): Promise<any> => import('./users/UsersModule')
+ .then((m: typeof import('./users/UsersModule')) => m.UsersModule),
+ canActivate: [AuthGuardService]
+ },
+ {
+ path: 'projects',
+ // tslint:disable-next-line: no-any
+ loadChildren: async (): Promise<any> => import('./projects/ProjectsModule')
+ .then((m: typeof import('./projects/ProjectsModule')) => m.ProjectsModule),
+ canActivate: [AuthGuardService]
+ },
+ {
+ path: 'roles',
+ // tslint:disable-next-line: no-any
+ loadChildren: async (): Promise<any> => import('./roles/RolesModule')
+ .then((m: typeof import('./roles/RolesModule')) => m.RolesModule),
+ canActivate: [AuthGuardService]
+ },
+ {
+ path: 'k8s',
+ // tslint:disable-next-line: no-any
+ loadChildren: async (): Promise<any> => import('./k8s/K8sModule')
+ .then((m: typeof import('./k8s/K8sModule')) => m.K8sModule),
+ canActivate: [AuthGuardService]
+ }
+ ]
+ },
+ {
+ path: '**',
+ component: PageNotFoundComponent
+ }
+];
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="row dashboard">
+ <div class="col-xs-9 col-sm-12 col-md-12 col-lg-9 col-xl-9 p-0">
+ <div class="row instances">
+ <div class="col-xs-8 col-sm-8 col-md-12 col-lg-8 col-xl-8">
+ <div class="custom-card card mb-3 text-center graph-section">
+ <div class="card-title">
+ <h6 class="font-weight-bold" *ngIf="nsRunningInstance.length">
+ {{'PAGE.DASHBOARD.UPTIME' | translate}} {{'PAGE.DASHBOARD.RUNNINGINSTANCES' | translate}}
+ </h6>
+ <h6 *ngIf="!nsRunningInstance.length">
+ <span> {{'PAGE.DASHBOARD.NOINSTANCES' | translate}}</span>
+ </h6>
+ <div [ngClass]="{'show-canvas':nsRunningInstance.length}" class="instances-canvas">
+ <canvas id="canvas"></canvas>
+ </div>
+ </div>
+ </div>
+ <app-loader [waitingMessage]="message" *ngIf="isCanvasLoadingResults"></app-loader>
+ </div>
+ <div class="col-xs-4 col-sm-4 col-md-12 col-lg-4 col-xl-4">
+ <div class="custom-card card card mb-3">
+ <div class="card-header custom-card-header">
+ {{'PAGE.DASHBOARD.FAILEDINSTANCES' | translate}}
+ </div>
+ <div class="card-body list-overflow failed-instances">
+ <ul class="list-group">
+ <li class="list-group-item text-left" *ngIf="!nsFailedInstances.length">
+ {{'PAGE.DASHBOARD.NOINSTANCES' | translate}}</li>
+ <li class="list-group-item text-left d-flex justify-content-between align-items-center"
+ *ngFor="let nsFailedInstance of nsFailedInstances">
+ <span class="text-truncate">{{nsFailedInstance.name}}</span>
+ <ng-template #popTitle>
+ <strong>{{nsFailedInstance.name}}</strong>
+ <button class="button-xs close" type="button" (click)="p.close()">
+ <i class="fas fa-times-circle text-danger"></i>
+ </button>
+ </ng-template>
+ <span class="badge badge-pill">
+ <i placement="left" container="body"
+ ngbPopover="{{'DETAILEDSTATUS' | translate}}: {{nsFailedInstance['detailed-status']}}"
+ triggers="manual" #p="ngbPopover" (click)="p.open()" [autoClose]="'outside'"
+ [popoverTitle]="popTitle"
+ class="fas fa-exclamation-circle text-danger float-left"></i></span>
+ </li>
+ </ul>
+ </div>
+ </div>
+ <app-loader [waitingMessage]="message" *ngIf="isCanvasLoadingResults"></app-loader>
+ </div>
+ </div>
+ <div class="row module-counts">
+ <div class="col-xs-4 col-sm-4 col-md-4 col-lg-4 col-xl-4 p-0">
+ <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 col-xl-12 mb-3">
+ <div class="status-card custom-card card-hover card aqua-card" routerLink="/packages/ns">
+ <i class="fas fa-box-open"></i>
+ <h3>{{ (nsdPackageCount)?nsdPackageCount:0 }}</h3>
+ <h6>{{'NSPACKAGES' | translate}}</h6>
+ <span class="link-icon">
+ <i class="fa fa-link" aria-hidden="true"></i>
+ </span>
+ </div>
+ </div>
+ <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 col-xl-12 mb-3">
+ <div class="status-card custom-card card-hover card aqua-card" routerLink="/instances/ns">
+ <i class="fas fa-sitemap"></i>
+ <h3>{{ (nsInstanceCount)?nsInstanceCount:0 }}</h3>
+ <h6>{{'NSINSTANCES' | translate}}</h6>
+ <span class="link-icon">
+ <i class="fa fa-link" aria-hidden="true"></i>
+ </span>
+ </div>
+ </div>
+ </div>
+ <div class="col-xs-4 col-sm-4 col-md-4 col-lg-4 col-xl-4 p-0">
+ <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 col-xl-12 mb-3">
+ <div class="status-card custom-card card-hover card purple-card" routerLink="/packages/vnf">
+ <i class="fas fa-box-open"></i>
+ <h3>{{ (vnfdPackageCount)?vnfdPackageCount:0 }}</h3>
+ <h6>{{'VNFPACKAGES' | translate}}</h6>
+ <span class="link-icon">
+ <i class="fa fa-link" aria-hidden="true"></i>
+ </span>
+ </div>
+ </div>
+ <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 col-xl-12 mb-3">
+ <div class="status-card custom-card card-hover card purple-card" routerLink="/instances/vnf">
+ <i class="fas fa-hdd"></i>
+ <h3>{{ (vnfInstanceCount)?vnfInstanceCount:0 }}</h3>
+ <h6>{{'VNFINSTANCES' | translate}}</h6>
+ <span class="link-icon">
+ <i class="fa fa-link" aria-hidden="true"></i>
+ </span>
+ </div>
+ </div>
+ </div>
+ <div class="col-xs-4 col-sm-4 col-md-4 col-lg-4 col-xl-4 p-0">
+ <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 col-xl-12 mb-3">
+ <div class="status-card custom-card card-hover card pink-card" routerLink="/vim/details">
+ <i class="fas fa-server"></i>
+ <h3>{{ (vimAccountCount)?vimAccountCount:0 }}</h3>
+ <h6>{{'VIMACCOUNTS' | translate}}</h6>
+ <span class="link-icon">
+ <i class="fa fa-link" aria-hidden="true"></i>
+ </span>
+ </div>
+ </div>
+ <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 col-xl-12 mb-3">
+ <div class="status-card custom-card card-hover card pink-card" routerLink="/sdn/details">
+ <i class="fas fa-globe"></i>
+ <h3>{{ (sdnControllerCount)?sdnControllerCount:0 }}</h3>
+ <h6>{{'SDNCONTROLLER' | translate}}</h6>
+ <span class="link-icon">
+ <i class="fa fa-link" aria-hidden="true"></i>
+ </span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="col-xs-3 col-sm-12 col-md-12 col-lg-3 col-xl-3 p-0">
+ <div class="custom-card">
+ <div class="card-header p-0 custom-card-header">
+ <a routerLink="/projects">
+ {{'ALL' | translate}} {{'PAGE.DASHBOARD.PROJECTS' | translate}}
+ <span
+ class="badge badge-primary badge-pill bg-white text-body font-weight-bold">{{allProjectList.length}}</span>
+ </a>
+ </div>
+ <div class="card-body list-overflow project-list">
+ <ul class="list-group">
+ <li class="list-group-item text-left d-flex justify-content-between align-items-center selectProject"
+ *ngFor='let list of allProjectList'>
+ {{list.projectName}}
+ <span class="badge badge-pill" *ngFor='let listcheck of projectList' placement="top"
+ container="body"
+ ngbTooltip="{{ (list.projectName === (selectedProject | async) ? 'CURRENTPROJECT' : 'SWITCHPROJECT') | translate}}">
+ <i *ngIf="list.projectName === (selectedProject | async) && listcheck.project === list.project"
+ [ngClass]="list.projectName === (selectedProject | async) ? 'activeProjectLink' : ''"
+ class="fas fa-check-circle text-success"></i>
+ <i *ngIf="list.projectName !== (selectedProject | async) && listcheck.project === list.project"
+ (click)="this.projectService.switchProjectModal(list)"
+ class="fas fa-exchange-alt text-danger selectProjectLink"></i>
+ </span>
+ </li>
+ </ul>
+ </div>
+ <app-loader [waitingMessage]="message" *ngIf="isProjectsLoadingResults"></app-loader>
+ </div>
+ </div>
+</div>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+ @import "../../assets/scss/mixins/mixin";
+ @import "../../assets/scss/variable";
+ $min-height-set: 200px;
+ .dashboard {
+ .custom-card {
+ word-wrap: break-word;
+ @include box-shadow(0px, 1px, 15px, 0px, rgba(69, 90, 100, 0.1));
+ @include transition(all, 0.2s, null, null);
+ @include roundedCorners(5);
+ @include border(all, 1, solid, rgba(238, 238, 238, 0.75));
+ color: $white;
+ &.card-hover {
+ @include transition(all, 0.25s, ease, null);
+ &:hover {
+ -moz-transform: translateY(-4px) scale(1.01);
+ -ms-transform: translateY(-4px) scale(1.01);
+ -o-transform: translateY(-4px) scale(1.01);
+ transform: translateY(-4px) scale(1.01);
+ }
+ }
+ &.pink-card {
+ @include background(
+ linear-gradient(to left top, #d81b60, #e0306d, #e7407a, #ee4f87, #f55c94),
+ null,
+ null,
+ null,
+ null
+ );
+ }
+ &.purple-card {
+ @include background(
+ linear-gradient(to left top, #605ca8, #736ebb, #8681ce, #9994e2, #aca7f6),
+ null,
+ null,
+ null,
+ null
+ );
+ }
+ &.aqua-card {
+ @include background(
+ linear-gradient(to left top, #00c0ef, #00cdf5, #00dafa, #00e6fd, #0af3ff),
+ null,
+ null,
+ null,
+ null
+ );
+ }
+ .custom-card-header {
+ @include background(null, $primary, null, null, null);
+ @include roundedTop(5);
+ a {
+ color: $white;
+ @include flexbox(flex, space-between, null, null, center, null);
+ @include padding-value(12, 20, 12, 20);
+ }
+ }
+ .card-body {
+ @include padding-value(5, 5, 5, 10);
+ &.list-overflow {
+ overflow-y: scroll;
+ .list-group {
+ .list-group-item {
+ cursor: default;
+ @include border(all, 0, solid, $black-coral);
+ @include border(bottom, 1, solid, rgba(0, 0, 0, 0.125));
+ @include padding-value(10, 0, 10, 0);
+ @include margin-value(0, 0, 0, 0);
+ color: $gray-600;
+ i {
+ cursor: pointer;
+ @include font(null, 14px, null);
+ &.activeProjectLink {
+ cursor: default;
+ }
+ }
+ &:last-child {
+ @include border(bottom, 0, solid, rgba(0, 0, 0, 0.125));
+ }
+ }
+ }
+ &.failed-instances {
+ max-height: $min-height-set;
+ }
+ &.project-list {
+ max-height: 65vh;
+ }
+ }
+ }
+ }
+ .instances {
+ .graph-section {
+ min-height: $min-height-set;
+ @include flexbox(null, center, null, null, null, null);
+ @include padding-value(10, 10, 10, 10);
+ .card-title {
+ color: $gray-600;
+ }
+ .instances-canvas {
+ @include flexbox(none !important, null, null, null, null, null);
+ &.show-canvas {
+ @include flexbox(block !important, null, null, null, null, null);
+ }
+ #canvas{
+ @include wh-value(100%, $min-height-set);
+ }
+ }
+ }
+ }
+ .module-counts {
+ .status-card {
+ overflow: hidden;
+ @include wh-value(null, 130px);
+ @include roundedCorners(4);
+ @include box-shadow(0px, 5px, 20px, 2px, $transparent-dark-bg);
+ cursor: pointer;
+ @include flexbox(null, null, null, null, center, null);
+ @include padding-value(20, 20, 20, 20);
+ @include border(all, 0, solid, $gray-80);
+ i {
+ @include font(null, 2rem, null);
+ @include margin-value(0, 0, 8, 0);
+ }
+ h6 {
+ @include font(null, 0.8rem, null);
+ }
+ &:hover .link-icon {
+ @include position_value(null, null, -60px, null, null);
+ }
+ .link-icon {
+ @include background(null, rgba(255, 255, 255, 0.5), null, null, null);
+ @include position_value(absolute, 0px, -130px, null, null);
+ @include wh-value(130px, 130px);
+ @include font(null, 30px, null);
+ @include padding-value(40, 20, 40, 20);
+ @include roundedCornersPercentage(50%);
+ @include transition(all, 0.3s, ease-in-out, null);
+ i {
+ @include font(null, 1.875rem, null);
+ }
+ }
+ }
+ }
+ }
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @file Dashboard Component
+ */
+import { Component, Injector, OnInit } from '@angular/core';
+import { TranslateService } from '@ngx-translate/core';
+import { AuthenticationService } from 'AuthenticationService';
+import { Chart } from 'chart.js';
+import { ERRORDATA } from 'CommonModel';
+import { environment } from 'environment';
+import { NSDDetails } from 'NSDModel';
+import { NSInstanceDetails } from 'NSInstanceModel';
+import { ProjectData, ProjectDetails } from 'ProjectModel';
+import { ProjectService } from 'ProjectService';
+import { RestService } from 'RestService';
+import { Observable, Subscription } from 'rxjs';
+import { SDNControllerModel } from 'SDNControllerModel';
+import { SharedService } from 'SharedService';
+import { ProjectRoleMappings, UserDetail } from 'UserModel';
+import { VimAccountDetails } from 'VimAccountModel';
+import { VNFDDetails } from 'VNFDModel';
+import { VNFInstanceDetails } from 'VNFInstanceModel';
+
+/**
+ * Creating component
+ * @Component takes DashboardComponent.html as template url
+ */
+@Component({
+ styleUrls: ['./DashboardComponent.scss'],
+ templateUrl: './DashboardComponent.html'
+})
+
+/**
+ * This file created during the angular project creation
+ */
+
+/** Exporting a class @exports DashboardComponent */
+export class DashboardComponent implements OnInit {
+ /** Invoke service injectors @public */
+ public injector: Injector;
+
+ /** handle translate @public */
+ public translateService: TranslateService;
+
+ /** Observable holds logined value @public */
+ public username$: Observable<string>;
+
+ /** Variables holds admin is logged or not @public */
+ public isAdmin: boolean;
+
+ /** List of NS failed Instances @public */
+ public nsFailedInstances: {}[] = [];
+
+ /** Setting up count for vnfdPackages @public */
+ public vnfdPackageCount: number;
+
+ /** Setting up count for nsdPackage @public */
+ public nsdPackageCount: number;
+
+ /** Setting up count for nsInstance @public */
+ public nsInstanceCount: number;
+
+ /** Setting up count for vnfInstance @public */
+ public vnfInstanceCount: number;
+
+ /** Setting up count for vimAccount @public */
+ public vimAccountCount: number;
+
+ /** Setting up count for sdnController @public */
+ public sdnControllerCount: number;
+
+ /** Variables holds current project details @public */
+ public currentProjectDetails: {};
+
+ /** Array holds all the projects @public */
+ public projectList: {}[] = [];
+
+ /** Array holds all the projects @public */
+ public allProjectList: {}[] = [];
+
+ /** Variables holds the selected project @public */
+ public selectedProject: Observable<string>;
+
+ /** Check the Instances loading results @public */
+ public isCanvasLoadingResults: boolean = true;
+
+ /** Check the Projects loading results @public */
+ public isProjectsLoadingResults: boolean = true;
+
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+
+ /** List of NS Success Instances @private */
+ public nsRunningInstance: string[] = [];
+
+ /** Utilizes rest service for any CRUD operations @private */
+ private restService: RestService;
+
+ /** Utilizes auth service for any auth operations @private */
+ private authService: AuthenticationService;
+
+ /** Used to subscribe vnfdPackage @private */
+ private vnfdPackageCountSub: Subscription;
+
+ /** Used to subscribe nsdPackage @private */
+ private nsdPackageCountSub: Subscription;
+
+ /** Used to subscribe nsInstance @private */
+ private nsInstanceCountSub: Subscription;
+
+ /** Used to subscribe vnfInstance @private */
+ private vnfInstanceCountSub: Subscription;
+
+ /** Used to subscribe vimAccount @private */
+ private vimAccountCountSub: Subscription;
+
+ /** Used to subscribe sdnController @private */
+ private sdnControllerCountSub: Subscription;
+
+ /** No of Hours of NS Success Instances @private */
+ private noOfHours: number[] = [];
+
+ /** collects charts objects @private */
+ private charts: object = [];
+
+ /** Contains all methods related to projects @private */
+ private projectService: ProjectService;
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ /** Contains NS Instance Details */
+ private nsInstancesDataArr: {}[];
+
+ /** Container created time array @private */
+ private createdTimes: string[] = [];
+
+ /** Contains slice limit const @private */
+ private sliceLimit: number = 10;
+
+ /** Contians hour converter @private */
+ private hourConverter: number = 3600;
+
+ /** Contians color code for chart @private */
+ private chartColorPink: string = '#e4397c';
+
+ /** Contians color code for chart @private */
+ private chartColorPurple: string = '#605ca8';
+
+ /** Contians color code for chart @private */
+ private chartColorCyan: string = '#00c0ef';
+
+ /** Contians color code for chart @private */
+ private chartColorBlue: string = '#054C8C';
+
+ /** Contians color code for chart @private */
+ private chartColorYellow: string = '#ffce56';
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.restService = this.injector.get(RestService);
+ this.authService = this.injector.get(AuthenticationService);
+ this.projectService = this.injector.get(ProjectService);
+ this.sharedService = this.injector.get(SharedService);
+ this.translateService = this.injector.get(TranslateService);
+ }
+
+ /**
+ * Lifecyle Hooks the trigger before component is instantiate
+ */
+ public ngOnInit(): void {
+ this.username$ = this.authService.username;
+ this.isAdmin = (localStorage.getItem('isAdmin') === 'true') ? true : false;
+ this.selectedProject = this.authService.ProjectName;
+ this.checkAdminPrivilege();
+ this.getUserAccessedProjects();
+ this.getAllProjects();
+ this.getVnfdPackageCount();
+ this.getNsdPackageCount();
+ this.getNsInstanceCount();
+ this.getVnfInstanceCount();
+ this.getVimAccountCount();
+ this.getSDNControllerCount();
+ }
+
+ /** Get all the projects @public */
+ public getUserAccessedProjects(): void {
+ this.projectService.getUserProjects().subscribe((projects: UserDetail) => {
+ const projectList: {}[] = projects.project_role_mappings;
+ this.projectList = projectList.filter(
+ (thing: ProjectRoleMappings, i: number, arr: []) => arr
+ .findIndex((t: ProjectRoleMappings) => t.project_name === thing.project_name) === i
+ );
+ }, (error: Error) => {
+ // TODO: Handle failure
+ });
+ }
+
+ /** Fetching all the Project in dashboard @public */
+ public getAllProjects(): void {
+ this.isProjectsLoadingResults = true;
+ this.restService.getResource(environment.PROJECTS_URL).subscribe((projectsData: ProjectDetails[]) => {
+ this.allProjectList = [];
+ projectsData.forEach((projectData: ProjectDetails) => {
+ const projectDataObj: ProjectData = this.generateProjectData(projectData);
+ this.allProjectList.push(projectDataObj);
+ });
+ this.isProjectsLoadingResults = false;
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'get');
+ this.isProjectsLoadingResults = false;
+ });
+ }
+
+ /** Generate Projects object from loop and return for the datasource @public */
+ public generateProjectData(projectData: ProjectDetails): ProjectData {
+ return {
+ projectName: projectData.name,
+ modificationDate: this.sharedService.convertEpochTime(projectData._admin.modified),
+ creationDate: this.sharedService.convertEpochTime(projectData._admin.created),
+ id: projectData._id,
+ project: projectData._id
+ };
+ }
+
+ /** Function to check admin privilege @public */
+ public checkAdminPrivilege(): void {
+ if (!this.isAdmin) {
+ this.projectService.getCurrentProjectDetails().subscribe((projectDetails: {}) => {
+ this.currentProjectDetails = projectDetails;
+ }, (error: Error) => {
+ // TODO: Handle failure
+ });
+ }
+ }
+
+ /** Get VNFD Package details @public */
+ public getVnfdPackageCount(): void {
+ this.vnfdPackageCountSub = this.restService.getResource(environment.VNFPACKAGESCONTENT_URL)
+ .subscribe((vnfdPackageData: VNFDDetails[]) => {
+ this.vnfdPackageCount = vnfdPackageData.length;
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'get');
+ });
+ }
+
+ /** Get NSD Package details @public */
+ public getNsdPackageCount(): void {
+ this.nsdPackageCountSub = this.restService.getResource(environment.NSDESCRIPTORSCONTENT_URL)
+ .subscribe((nsdPackageData: NSDDetails[]) => {
+ this.nsdPackageCount = nsdPackageData.length;
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'get');
+ });
+ }
+
+ /** Get NS Instance details @public */
+ public getNsInstanceCount(): void {
+ this.isCanvasLoadingResults = true;
+ this.nsInstanceCountSub = this.restService.getResource(environment.NSDINSTANCES_URL)
+ .subscribe((nsInstancesData: NSInstanceDetails[]) => {
+ this.nsInstancesDataArr = nsInstancesData;
+ this.nsInstanceCount = nsInstancesData.length;
+ this.nsInstanceChart();
+ this.isCanvasLoadingResults = false;
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'get');
+ this.isCanvasLoadingResults = false;
+ });
+ }
+
+ /** Get NS Instance chart details @public */
+ public nsInstanceChart(): void {
+ this.nsInstancesDataArr.forEach((nsdInstanceData: NSDDetails) => {
+ const operationalStatus: string = nsdInstanceData['operational-status'];
+ const configStatus: string = nsdInstanceData['config-status'];
+ if (operationalStatus === 'failed' || configStatus === 'failed') {
+ this.nsFailedInstances.push(nsdInstanceData);
+ } else if (operationalStatus === 'running' && configStatus === 'configured') {
+ this.nsRunningInstance.push(nsdInstanceData.name);
+ this.createdTimes.push(((nsdInstanceData._admin.created).toString()).slice(0, this.sliceLimit));
+ }
+ });
+ const now: Date = new Date();
+ const currentTime: number = Number((now.getTime().toString().slice(0, this.sliceLimit)));
+ this.createdTimes.forEach((createdTime: string) => {
+ this.noOfHours.push((Math.round((currentTime - Number(createdTime)) / this.hourConverter)));
+ });
+ this.drawNsChart();
+ }
+
+ /** Prepare and sketch NS instance chart */
+ public drawNsChart(): void {
+ this.charts = new Chart('canvas', {
+ type: 'bar',
+ data: {
+ labels: this.nsRunningInstance,
+ datasets: [{
+ data: this.noOfHours,
+ label: this.translateService.instant('NOOFHOURS'),
+ borderColor: [this.chartColorPurple, this.chartColorPink, this.chartColorCyan,
+ this.chartColorBlue, this.chartColorYellow],
+ fill: false,
+ backgroundColor: [this.chartColorPurple, this.chartColorPink, this.chartColorCyan,
+ this.chartColorBlue, this.chartColorYellow]
+ }]
+ },
+ options: {
+ legend: { display: false },
+ scales: {
+ xAxes: [{
+ display: true,
+ ticks: {
+ // tslint:disable-next-line: no-any
+ callback: (label: any, index: number, labels: string): string => {
+ const length: number = 20;
+ const ending: string = '...';
+ if (label.length > length) {
+ return label.substring(0, length - ending.length) + ending;
+ } else {
+ return label;
+ }
+ }
+ },
+ scaleLabel: {
+ display: true,
+ labelString: this.translateService.instant('INSTANCES')
+ }
+ }],
+ yAxes: [{
+ ticks: {
+ beginAtZero: true
+ },
+ display: true,
+ scaleLabel: {
+ display: true,
+ labelString: this.translateService.instant('NOOFHOURS')
+ }
+ }]
+ }
+ }
+ });
+ }
+
+ /** Get VNFD instance details @public */
+ public getVnfInstanceCount(): void {
+ this.vnfInstanceCountSub = this.restService.getResource(environment.NSDINSTANCES_URL)
+ .subscribe((vnfInstanceData: VNFInstanceDetails[]) => {
+ this.vnfInstanceCount = vnfInstanceData.length;
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'get');
+ });
+ }
+
+ /** Get VIM account details @public */
+ public getVimAccountCount(): void {
+ this.vimAccountCountSub = this.restService.getResource(environment.VIMACCOUNTS_URL)
+ .subscribe((vimAccountData: VimAccountDetails[]) => {
+ this.vimAccountCount = vimAccountData.length;
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'get');
+ });
+ }
+
+ /** Get SDN Controller Count @public */
+ public getSDNControllerCount(): void {
+ this.sdnControllerCountSub = this.restService.getResource(environment.SDNCONTROLLER_URL)
+ .subscribe((sdnControllerData: SDNControllerModel[]) => {
+ this.sdnControllerCount = sdnControllerData.length;
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'get');
+ });
+ }
+
+ /**
+ * Lifecyle Hooks the trigger before component is deleted
+ */
+ public ngOnDestroy(): void {
+ this.vnfdPackageCountSub.unsubscribe();
+ this.nsdPackageCountSub.unsubscribe();
+ this.nsInstanceCountSub.unsubscribe();
+ this.vnfInstanceCountSub.unsubscribe();
+ this.vimAccountCountSub.unsubscribe();
+ this.sdnControllerCountSub.unsubscribe();
+ }
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+
+/**
+ * @file Dashboard Module
+ */
+import { CommonModule } from '@angular/common';
+import { HttpClientModule } from '@angular/common/http';
+import { NgModule } from '@angular/core';
+import { FlexLayoutModule } from '@angular/flex-layout';
+import { FormsModule } from '@angular/forms';
+import { RouterModule, Routes } from '@angular/router';
+import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateModule } from '@ngx-translate/core';
+import { DashboardComponent } from 'DashboardComponent';
+import { LoaderModule } from 'LoaderModule';
+import { ChartsModule } from 'ng2-charts';
+
+/** To halndle project information */
+const projectInfo: {} = { title: '{project}', url: '/' };
+
+/** const values for dashboard Routes */
+const routes: Routes = [
+ {
+ path: '',
+ data: {
+ breadcrumb: [{ title: 'PAGE.DASHBOARD.DASHBOARD', url: '/' }, { title: 'PAGE.DASHBOARD.PROJECTS', url: '/projects' },
+ projectInfo]
+ },
+ component: DashboardComponent
+ }
+];
+/**
+ * An NgModule is a class adorned with the @NgModule decorator function.
+ * @NgModule takes a metadata object that tells Angular how to compile and run module code.
+ */
+@NgModule({
+ imports: [FormsModule, CommonModule, HttpClientModule, FlexLayoutModule, TranslateModule,
+ ChartsModule, RouterModule.forChild(routes), NgbModule, LoaderModule],
+ declarations: [DashboardComponent]
+})
+/** Exporting a class @exports DashboardModule */
+export class DashboardModule {
+ /** Variables declared to avoid state-less class */
+ private dashboardModule: string;
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<router-outlet></router-outlet>
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @file Instance components
+ */
+import { Component, Injector } from '@angular/core';
+import { Router, RouterEvent } from '@angular/router';
+/**
+ * Creating component
+ * @Component takes InstancesComponent.html as template url
+ */
+@Component({
+ selector: 'app-instances',
+ templateUrl: './InstancesComponent.html',
+ styleUrls: ['./InstancesComponent.scss']
+})
+/** Exporting a class @exports InstancesComponent */
+export class InstancesComponent {
+ /** Invoke service injectors @public */
+ public injector: Injector;
+
+ /** Holds teh instance of AuthService class of type AuthService @private */
+ private router: Router;
+
+ // creates packages component
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.router = this.injector.get(Router);
+ this.router.events.subscribe((event: RouterEvent) => {
+ this.redirectToList(event.url);
+ });
+ }
+
+ /** Return to list NS Package List */
+ public redirectToList(getURL: string): void {
+ if (getURL === '/instances') {
+ this.router.navigate(['/instances/ns']).catch();
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @file Instance module
+ */
+import { CommonModule } from '@angular/common';
+import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
+import { FlexLayoutModule } from '@angular/flex-layout';
+import { FormsModule } from '@angular/forms';
+import { ReactiveFormsModule } from '@angular/forms';
+import { RouterModule, Routes } from '@angular/router';
+import { CodemirrorModule } from '@ctrl/ngx-codemirror';
+import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
+import { NgSelectModule } from '@ng-select/ng-select';
+import { TranslateModule } from '@ngx-translate/core';
+import { AddPDUInstancesComponent } from 'AddPDUInstancesComponent';
+import { DataService } from 'DataService';
+import { HistoryOperationsComponent } from 'HistoryOperationsComponent';
+import { InstancesComponent } from 'InstancesComponent';
+import { LoaderModule } from 'LoaderModule';
+import { NetsliceInstancesComponent } from 'NetsliceInstancesComponent';
+import { SidebarModule } from 'ng-sidebar';
+import { Ng2SmartTableModule } from 'ng2-smart-table';
+import { NSInstancesComponent } from 'NSInstancesComponent';
+import { NSPrimitiveComponent } from 'NSPrimitiveComponent';
+import { NSTopologyComponent } from 'NSTopologyComponent';
+import { PagePerRowModule } from 'PagePerRowModule';
+import { PageReloadModule } from 'PageReloadModule';
+import { PDUInstancesComponent } from 'PDUInstancesComponent';
+import { VNFInstancesComponent } from 'VNFInstancesComponent';
+
+/** To halndle project information */
+const projectInfo: {} = { title: '{project}', url: '/' };
+
+/** Exporting a function using Routes @exports routes */
+const routes: Routes = [
+ {
+ path: '',
+ component: InstancesComponent,
+ children: [
+ {
+ path: 'ns',
+ data: {
+ breadcrumb: [{ title: 'PAGE.DASHBOARD.DASHBOARD', url: '/' }, { title: 'PAGE.DASHBOARD.PROJECTS', url: '/projects' },
+ projectInfo, { title: 'NSINSTANCES', url: null }]
+ },
+ component: NSInstancesComponent
+ },
+ {
+ path: 'vnf',
+ data: {
+ breadcrumb: [{ title: 'PAGE.DASHBOARD.DASHBOARD', url: '/' }, { title: 'PAGE.DASHBOARD.PROJECTS', url: '/projects' },
+ projectInfo, { title: 'VNFINSTANCES', url: null }]
+ },
+ component: VNFInstancesComponent
+ },
+ {
+ path: 'pdu',
+ data: {
+ breadcrumb: [{ title: 'PAGE.DASHBOARD.DASHBOARD', url: '/' }, { title: 'PAGE.DASHBOARD.PROJECTS', url: '/projects' },
+ projectInfo, { title: 'PDUINSTANCES', url: null }]
+ },
+ component: PDUInstancesComponent
+ },
+ {
+ path: 'netslice',
+ data: {
+ breadcrumb: [{ title: 'PAGE.DASHBOARD.DASHBOARD', url: '/' }, { title: 'PAGE.DASHBOARD.PROJECTS', url: '/projects' },
+ projectInfo, { title: 'PAGE.DASHBOARD.NETSLICEINSTANCE', url: null }]
+ },
+ component: NetsliceInstancesComponent
+ },
+ {
+ path: ':type/history-operations/:id',
+ data: {
+ breadcrumb: [{ title: 'PAGE.DASHBOARD.DASHBOARD', url: '/' }, { title: 'PAGE.DASHBOARD.PROJECTS', url: '/projects' },
+ projectInfo, { title: '{type}', url: '/instances/{type}' }, { title: '{id}', url: null }]
+ },
+ component: HistoryOperationsComponent
+ },
+ {
+ path: 'ns/:id',
+ data: {
+ breadcrumb: [{ title: 'PAGE.DASHBOARD.DASHBOARD', url: '/' }, { title: 'PAGE.DASHBOARD.PROJECTS', url: '/projects' },
+ projectInfo, { title: 'NSINSTANCES', url: '/instances/ns' }, { title: '{id}', url: null }]
+ },
+ component: NSTopologyComponent
+ }
+ ]
+ }
+];
+
+/**
+ * An NgModule is a class adorned with the @NgModule decorator function.
+ * @NgModule takes a metadata object that tells Angular how to compile and run module code.
+ */
+@NgModule({
+ imports: [ReactiveFormsModule.withConfig({ warnOnNgModelWithFormControl: 'never' }), FormsModule, TranslateModule,
+ CodemirrorModule, CommonModule, Ng2SmartTableModule, FlexLayoutModule, RouterModule.forChild(routes), NgbModule,
+ NgSelectModule, PagePerRowModule, LoaderModule, SidebarModule.forRoot(), PageReloadModule],
+ declarations: [InstancesComponent, NSInstancesComponent, VNFInstancesComponent, PDUInstancesComponent, AddPDUInstancesComponent,
+ NetsliceInstancesComponent, HistoryOperationsComponent, NSTopologyComponent, NSPrimitiveComponent],
+ schemas: [CUSTOM_ELEMENTS_SCHEMA],
+ providers: [DataService],
+ entryComponents: [NSPrimitiveComponent, AddPDUInstancesComponent]
+})
+/** Exporting a class @exports InstancesModule */
+export class InstancesModule {
+ /** Resolves state-less class */
+ private instancesModule: string;
+ /**
+ * Lifecyle Hooks the trigger before component is instantiate
+ */
+ public ngOnInit(): void {
+ this.instancesModule = '';
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="row d-flex flex-row justify-content-between">
+ <div class="d-flex align-items-center header-style">{{'PAGE.DASHBOARD.NETSLICEINSTANCE' | translate}}</div>
+ <span class="button">
+ <button class="btn btn-primary" type="button" placement="top" container="body"
+ ngbTooltip="{{'PAGE.NETSLICEINSTANCE.CREATENETSLICEINSTANCE' | translate}}" (click)="instantiateNetSlice()">
+ <i class="fa fa-paper-plane" aria-hidden="true"></i>
+ {{'PAGE.NETSLICEINSTANCE.CREATENETSLICEINSTANCE' | translate}}
+ </button>
+ </span>
+</div>
+<div class="row mt-2 mb-0 list-utilites-actions">
+ <div class="col-auto mr-auto">
+ <nav class="custom-items-config">
+ <span><i class="fas fa-clock text-warning"></i>{{operationalStateFirstStep}}</span>
+ <span><i class="fas fa-check-circle text-success"></i>{{operationalStateSecondStep}} /
+ {{configStateSecondStep}}</span>
+ <span><i class="fas fa-times-circle text-danger"></i>{{operationalStateThirdStep}}</span>
+ </nav>
+ </div>
+ <page-per-row class="mr-2" (pagePerRow)="onChange($event)"></page-per-row>
+ <page-reload></page-reload>
+</div>
+<div class="smarttable-style bg-white mt-1">
+ <ng2-smart-table [ngClass]="checkDataClass" [settings]="settings" [source]="dataSource" (userRowSelect)="onUserRowSelect($event)">
+ </ng2-smart-table>
+</div>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @file Netslice Instance Component
+ */
+import { Component, Injector, OnInit } from '@angular/core';
+import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateService } from '@ngx-translate/core';
+import { CONFIGCONSTANT, ERRORDATA, MODALCLOSERESPONSEDATA } from 'CommonModel';
+import { DataService } from 'DataService';
+import { environment } from 'environment';
+import { InstantiateNetSliceTemplateComponent } from 'InstantiateNetSliceTemplate';
+import { NetsliceInstancesActionComponent } from 'NetsliceInstancesActionComponent';
+import { NSTInstanceData, NSTInstanceDetails } from 'NetworkSliceModel';
+import { LocalDataSource } from 'ng2-smart-table';
+import { RestService } from 'RestService';
+import { Subscription } from 'rxjs';
+import { SharedService } from 'SharedService';
+
+/**
+ * Creating component
+ * @Component takes NetsliceInstancesComponent.html as template url
+ */
+@Component({
+ templateUrl: './NetsliceInstancesComponent.html',
+ styleUrls: ['./NetsliceInstancesComponent.scss']
+})
+
+/** Exporting a class @exports NetsliceInstancesComponent */
+export class NetsliceInstancesComponent implements OnInit {
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** handle translate @public */
+ public translateService: TranslateService;
+
+ /** Columns list of the smart table @public */
+ public columnLists: object = {};
+
+ /** Settings for smarttable to populate the table with columns @public */
+ public settings: object = {};
+
+ /** Datasource instance inititated @public */
+ public dataSource: LocalDataSource = new LocalDataSource();
+
+ /** Datasource table Data for the NST @public */
+ public nstInstanceData: NSTInstanceData[] = [];
+
+ /** Check the loading results @public */
+ public isLoadingResults: boolean = true;
+
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+
+ /** Class for empty and present data @public */
+ public checkDataClass: string;
+
+ /** operational State init data @public */
+ public operationalStateFirstStep: string = CONFIGCONSTANT.operationalStateFirstStep;
+
+ /** operational State running data @public */
+ public operationalStateSecondStep: string = CONFIGCONSTANT.operationalStateSecondStep;
+
+ /** operational State failed data @public */
+ public operationalStateThirdStep: string = CONFIGCONSTANT.operationalStateThirdStep;
+
+ /** Config State init data @public */
+ public configStateFirstStep: string = CONFIGCONSTANT.configStateFirstStep;
+
+ /** Config State init data @public */
+ public configStateSecondStep: string = CONFIGCONSTANT.configStateSecondStep;
+
+ /** Config State init data @public */
+ public configStateThirdStep: string = CONFIGCONSTANT.configStateThirdStep;
+
+ /** config status assign @public */
+ public configStatusCheck: string;
+
+ /** To consume REST API calls @private */
+ private dataService: DataService;
+
+ /** Utilizes rest service for any CRUD operations @public */
+ private restService: RestService;
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ /** Instance of the modal service @private */
+ private modalService: NgbModal;
+
+ /** Instance of subscriptions @private */
+ private generateDataSub: Subscription;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.restService = this.injector.get(RestService);
+ this.translateService = this.injector.get(TranslateService);
+ this.sharedService = this.injector.get(SharedService);
+ this.modalService = this.injector.get(NgbModal);
+ this.dataService = this.injector.get(DataService);
+ }
+
+ /**
+ * Lifecyle Hooks the trigger before component is instantiate
+ */
+ public ngOnInit(): void {
+ this.generateTableColumn();
+ this.generateTableSettings();
+ this.generateData();
+ this.generateDataSub = this.sharedService.dataEvent.subscribe(() => { this.generateData(); });
+ }
+
+ /** smart table listing manipulation @private */
+ public onChange(perPageValue: number): void {
+ this.dataSource.setPaging(1, perPageValue, true);
+ }
+
+ /** smart table listing manipulation @private */
+ public onUserRowSelect(event: MessageEvent): void {
+ Object.assign(event.data, { page: 'net-slice-instance' });
+ this.dataService.changeMessage(event.data);
+ }
+
+ /** Instantiate Net Slice using modalservice @public */
+ public instantiateNetSlice(): void {
+ const modalRef: NgbModalRef = this.modalService.open(InstantiateNetSliceTemplateComponent, { backdrop: 'static' });
+ modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
+ if (result) {
+ this.generateData();
+ }
+ }).catch();
+ }
+
+ /** Generate smart table row title and filters @public */
+ public generateTableSettings(): void {
+ this.settings = {
+ columns: this.columnLists,
+ actions: { add: false, edit: false, delete: false, position: 'right' },
+ attr: this.sharedService.tableClassConfig(),
+ pager: this.sharedService.paginationPagerConfig(),
+ noDataMessage: this.translateService.instant('NODATAMSG')
+ };
+ }
+
+ /** Generate smart table row title and filters @public */
+ public generateTableColumn(): void {
+ this.columnLists = {
+ name: { title: this.translateService.instant('NAME'), width: '15%', sortDirection: 'asc' },
+ identifier: { title: this.translateService.instant('IDENTIFIER'), width: '15%' },
+ NstName: { title: this.translateService.instant('NSTNAME'), width: '15%' },
+ OperationalStatus: {
+ type: 'html',
+ title: this.translateService.instant('OPERATIONALSTATUS'),
+ width: '15%',
+ filter: {
+ type: 'list',
+ config: {
+ selectText: 'Select',
+ list: [
+ { value: this.operationalStateFirstStep, title: this.operationalStateFirstStep },
+ { value: this.operationalStateSecondStep, title: this.operationalStateSecondStep },
+ { value: this.operationalStateThirdStep, title: this.operationalStateThirdStep }
+ ]
+ }
+ },
+ valuePrepareFunction: (cell: NSTInstanceData, row: NSTInstanceData): string => {
+ if (row.OperationalStatus === this.operationalStateFirstStep) {
+ return `<span class="icon-label" title="${row.OperationalStatus}">
+ <i class="fas fa-clock text-warning"></i>
+ </span>`;
+ } else if (row.OperationalStatus === this.operationalStateSecondStep) {
+ return `<span class="icon-label" title="${row.OperationalStatus}">
+ <i class="fas fa-check-circle text-success"></i>
+ </span>`;
+ } else if (row.OperationalStatus === this.operationalStateThirdStep) {
+ return `<span class="icon-label" title="${row.OperationalStatus}">
+ <i class="fas fa-times-circle text-danger"></i>
+ </span>`;
+ } else {
+ return `<span>${row.OperationalStatus}</span>`;
+ }
+ }
+ },
+ ConfigStatus: {
+ type: 'html',
+ title: this.translateService.instant('CONFIGSTATUS'),
+ width: '15%',
+ filter: {
+ type: 'list',
+ config: {
+ selectText: 'Select',
+ list: [
+ { value: this.configStateFirstStep, title: this.configStateFirstStep },
+ { value: this.configStateSecondStep, title: this.configStateSecondStep },
+ { value: this.configStateThirdStep, title: this.configStateThirdStep }
+ ]
+ }
+ },
+ valuePrepareFunction: (cell: NSTInstanceData, row: NSTInstanceData): string => {
+ if (row.ConfigStatus === this.configStateFirstStep) {
+ return `<span class="icon-label" title="${row.ConfigStatus}">
+ <i class="fas fa-clock text-warning"></i>
+ </span>`;
+ } else if (row.ConfigStatus === this.configStateSecondStep) {
+ return `<span class="icon-label" title="${row.ConfigStatus}">
+ <i class="fas fa-check-circle text-success"></i>
+ </span>`;
+ } else if (row.ConfigStatus === this.configStateThirdStep) {
+ return `<span class="icon-label" title="${row.ConfigStatus}">
+ <i class="fas fa-times-circle text-danger"></i>
+ </span>`;
+ } else {
+ return `<span>${row.ConfigStatus}</span>`;
+ }
+ }
+ },
+ DetailedStatus: { title: this.translateService.instant('DETAILEDSTATUS'), width: '15%' },
+ Actions: {
+ name: 'Action', width: '10%', filter: false, sort: false, title: this.translateService.instant('ACTIONS'), type: 'custom',
+ valuePrepareFunction: (cell: NSTInstanceData, row: NSTInstanceData): NSTInstanceData => row,
+ renderComponent: NetsliceInstancesActionComponent
+ }
+ };
+ }
+
+ /** generateData initiate the net-slice-instance list @public */
+ public generateData(): void {
+ this.isLoadingResults = true;
+ this.restService.getResource(environment.NETWORKSLICEINSTANCESCONTENT_URL)
+ .subscribe((netSliceInstancesData: NSTInstanceDetails[]) => {
+ this.nstInstanceData = [];
+ netSliceInstancesData.forEach((netSliceInstanceData: NSTInstanceDetails) => {
+ if (netSliceInstanceData['config-status'] !== undefined) {
+ this.configStatusCheck = netSliceInstanceData['config-status'];
+ } else {
+ this.configStatusCheck = netSliceInstanceData['operational-status'];
+ }
+ const netSliceDataObj: NSTInstanceData = {
+ name: netSliceInstanceData.name,
+ identifier: netSliceInstanceData.id,
+ NstName: netSliceInstanceData['nst-ref'],
+ OperationalStatus: netSliceInstanceData['operational-status'],
+ ConfigStatus: this.configStatusCheck,
+ DetailedStatus: netSliceInstanceData['detailed-status']
+ };
+ this.nstInstanceData.push(netSliceDataObj);
+ });
+ if (this.nstInstanceData.length > 0) {
+ this.checkDataClass = 'dataTables_present';
+ } else {
+ this.checkDataClass = 'dataTables_empty';
+ }
+ this.dataSource.load(this.nstInstanceData).then((data: {}) => {
+ this.isLoadingResults = false;
+ }).catch();
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'get');
+ this.isLoadingResults = false;
+ });
+ }
+
+ /**
+ * Lifecyle hook which get trigger on component destruction
+ */
+ public ngOnDestroy(): void {
+ this.generateDataSub.unsubscribe();
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="row d-flex flex-row justify-content-between">
+ <div class="d-flex align-items-center header-style">{{'HISTORYOFOPERATIONS' | translate}}</div>
+</div>
+<div class="row mt-2 mb-0 list-utilites-actions">
+ <div class="col-auto mr-auto">
+ <nav class="custom-items-config">
+ <span><i class="fas fa-clock text-warning"></i>{{historyStateFirstStep}}</span>
+ <span><i class="fas fa-check-circle text-success"></i>{{historyStateSecondStep}}</span>
+ <span><i class="fas fa-times-circle text-danger"></i>{{historyStateThirdStep}}</span>
+ </nav>
+ </div>
+ <page-per-row class="mr-2" (pagePerRow)="onChange($event)"></page-per-row>
+ <page-reload></page-reload>
+</div>
+<div class="smarttable-style bg-white mt-1">
+ <ng2-smart-table [ngClass]="checkDataClass" [settings]="settings" [source]="dataSource" (userRowSelect)="onUserRowSelect($event)" (custom)="showInformation($event)">
+ </ng2-smart-table>
+</div>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @file NS History Of Operations Component
+ */
+import { Component, Injector, OnInit } from '@angular/core';
+import { ActivatedRoute } from '@angular/router';
+import { Router } from '@angular/router';
+import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateService } from '@ngx-translate/core';
+import { CONFIGCONSTANT, ERRORDATA } from 'CommonModel';
+import { DataService } from 'DataService';
+import { environment } from 'environment';
+import * as HttpStatus from 'http-status-codes';
+import { LocalDataSource } from 'ng2-smart-table';
+import { NSDInstanceData } from 'NSInstanceModel';
+import { RestService } from 'RestService';
+import { Subscription } from 'rxjs';
+import { SharedService } from 'SharedService';
+import { ShowInfoComponent } from 'ShowInfoComponent';
+
+/**
+ * Creating component
+ * @Component takes HistoryOperationsComponent.html as template url
+ */
+@Component({
+ templateUrl: './HistoryOperationsComponent.html',
+ styleUrls: ['./HistoryOperationsComponent.scss']
+})
+/** Exporting a class @exports HistoryOperationsComponent */
+export class HistoryOperationsComponent implements OnInit {
+ /** Injector to invoke other services @public */
+ public injector: Injector;
+
+ /** NS Instance array @public */
+ public nsAndnstInstanceData: object[] = [];
+
+ /** Datasource instance @public */
+ public dataSource: LocalDataSource = new LocalDataSource();
+
+ /** Instance component are stored in settings @public */
+ public settings: {} = {};
+
+ /** Contains objects for smart table title and filter settings @public */
+ public columnList: {} = {};
+
+ /** Variable handles the page name @public */
+ public page: string;
+
+ /** Variable handles the title name @public */
+ public titleName: string;
+
+ /** Check the loading results @public */
+ public isLoadingResults: boolean = true;
+
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+
+ /** Class for empty and present data @public */
+ public checkDataClass: string;
+
+ /** History State init data @public */
+ public historyStateFirstStep: string = CONFIGCONSTANT.historyStateFirstStep;
+
+ /** History State running data @public */
+ public historyStateSecondStep: string = CONFIGCONSTANT.historyStateSecondStep;
+
+ /** History State failed data @public */
+ public historyStateThirdStep: string = CONFIGCONSTANT.historyStateThirdStep;
+
+ /** dataService to pass the data from one component to another @private */
+ private dataService: DataService;
+
+ /** Utilizes rest service for any CRUD operations @private */
+ private restService: RestService;
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ /** Holds teh instance of AuthService class of type AuthService @private */
+ private activatedRoute: ActivatedRoute;
+
+ /** Instance of the modal service @private */
+ private modalService: NgbModal;
+
+ /** variables contains paramsID @private */
+ private paramsID: string;
+
+ /** variables contains paramsID @private */
+ private paramsType: string;
+
+ /** variables conatins URL of the History operations @public */
+ private historyURL: string;
+
+ /** Contains tranlsate instance @private */
+ private translateService: TranslateService;
+
+ /** Instance of subscriptions @private */
+ private generateDataSub: Subscription;
+
+ /** Service holds the router information @private */
+ private router: Router;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.restService = this.injector.get(RestService);
+ this.dataService = this.injector.get(DataService);
+ this.sharedService = this.injector.get(SharedService);
+ this.activatedRoute = this.injector.get(ActivatedRoute);
+ this.modalService = this.injector.get(NgbModal);
+ this.translateService = this.injector.get(TranslateService);
+ this.router = this.injector.get(Router);
+ }
+
+ /** Lifecyle Hooks the trigger before component is instantiate @public */
+ public ngOnInit(): void {
+ // tslint:disable-next-line:no-backbone-get-set-outside-model
+ this.paramsID = this.activatedRoute.snapshot.paramMap.get('id');
+ // tslint:disable-next-line:no-backbone-get-set-outside-model
+ this.paramsType = this.activatedRoute.snapshot.paramMap.get('type');
+ if (this.paramsType === 'ns') {
+ this.historyURL = environment.NSHISTORYOPERATIONS_URL + '/?nsInstanceId=' + this.paramsID;
+ this.page = 'ns-history-operation';
+ this.titleName = 'INSTANCEDETAILS';
+ } else if (this.paramsType === 'netslice') {
+ this.historyURL = environment.NSTHISTORYOPERATIONS_URL + '/?netsliceInstanceId=' + this.paramsID;
+ this.page = 'nst-history-operation';
+ this.titleName = 'INSTANCEDETAILS';
+ }
+ this.generateTableColumn();
+ this.generateTableSettings();
+ this.generateData();
+ this.generateDataSub = this.sharedService.dataEvent.subscribe(() => { this.generateData(); });
+ }
+
+ /** Generate smart table row title and filters @public */
+ public generateTableSettings(): void {
+ this.settings = {
+ columns: this.columnList,
+ actions: {
+ add: false, edit: false, delete: false, position: 'right',
+ custom: [{
+ name: 'showInformation', title: '<i class="fas fa-info" title=" ' + this.translateService.instant('INFO') + ' "></i>'}]
+ },
+ attr: this.sharedService.tableClassConfig(),
+ pager: this.sharedService.paginationPagerConfig(),
+ noDataMessage: this.translateService.instant('NODATAMSG')
+ };
+ }
+
+ /** Generate smart table row title and filters @public */
+ public generateTableColumn(): void {
+ this.columnList = {
+ id: { title: this.translateService.instant('ID'), width: '30%' },
+ type: { title: this.translateService.instant('TYPE'), width: '20%' },
+ state: {
+ type: 'html', title: this.translateService.instant('OPERATIONSTATE'), width: '15%',
+ filter: {
+ type: 'list',
+ config: {
+ selectText: 'Select',
+ list: [
+ { value: this.historyStateFirstStep, title: this.historyStateFirstStep },
+ { value: this.historyStateSecondStep, title: this.historyStateSecondStep },
+ { value: this.historyStateThirdStep, title: this.historyStateThirdStep }
+ ]
+ }
+ },
+ valuePrepareFunction: (cell: NSDInstanceData, row: NSDInstanceData): string => {
+ if (row.state === this.historyStateFirstStep) {
+ return `<span class="icon-label" title="${row.state}">
+ <i class="fas fa-clock text-warning"></i>
+ </span>`;
+ } else if (row.state === this.historyStateSecondStep) {
+ return `<span class="icon-label" title="${row.state}">
+ <i class="fas fa-check-circle text-success"></i>
+ </span>`;
+ } else if (row.state === this.historyStateThirdStep) {
+ return `<span class="icon-label" title="${row.state}">
+ <i class="fas fa-times-circle text-danger"></i>
+ </span>`;
+ } else {
+ return `<span>${row.state}</span>`;
+ }
+ }
+ },
+ startTime: { title: this.translateService.instant('STARTTIME'), width: '15%' },
+ statusEnteredTime: { title: this.translateService.instant('STATUSENTEREDTIME'), width: '15%' }
+ };
+ }
+
+ /** smart table listing manipulation @public */
+ public onUserRowSelect(event: MessageEvent): void {
+ this.dataService.changeMessage(event.data);
+ }
+ /** smart table listing manipulation @public */
+ public onChange(perPageValue: number): void {
+ this.dataSource.setPaging(1, perPageValue, true);
+ }
+ /** show information methods modal with ns history info */
+ public showInformation(event: MessageEvent): void {
+ this.modalService.open(ShowInfoComponent, { backdrop: 'static' }).componentInstance.params = {
+ id: event.data.id,
+ page: this.page,
+ titleName: this.titleName
+ };
+ }
+
+ /**
+ * Lifecyle hook which get trigger on component destruction
+ */
+ public ngOnDestroy(): void {
+ this.generateDataSub.unsubscribe();
+ }
+
+ /** generateData initiate the ns-instance list @private */
+ private generateData(): void {
+ this.isLoadingResults = true;
+ this.restService.getResource(this.historyURL).subscribe((nsdInstancesData: {}[]) => {
+ this.nsAndnstInstanceData = [];
+ nsdInstancesData.forEach((nsdAndnstInstanceData: NSDInstanceData) => {
+ const nsAndnstDataObj: {} = {
+ id: nsdAndnstInstanceData.id,
+ type: nsdAndnstInstanceData.lcmOperationType,
+ state: nsdAndnstInstanceData.operationState,
+ startTime: this.sharedService.convertEpochTime(nsdAndnstInstanceData.startTime),
+ statusEnteredTime: this.sharedService.convertEpochTime(nsdAndnstInstanceData.statusEnteredTime)
+ };
+ this.nsAndnstInstanceData.push(nsAndnstDataObj);
+ });
+
+ if (this.nsAndnstInstanceData.length > 0) {
+ this.checkDataClass = 'dataTables_present';
+ } else {
+ this.checkDataClass = 'dataTables_empty';
+ }
+ this.dataSource.load(this.nsAndnstInstanceData).then((data: {}) => {
+ //empty block
+ }).catch();
+ this.isLoadingResults = false;
+ }, (error: ERRORDATA) => {
+ this.isLoadingResults = false;
+ if (error.error.status === HttpStatus.NOT_FOUND || error.error.status === HttpStatus.UNAUTHORIZED) {
+ this.router.navigateByUrl('404', { skipLocationChange: true }).catch();
+ } else {
+ this.restService.handleError(error, 'get');
+ }
+ });
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="row d-flex flex-row justify-content-between">
+ <div class="d-flex align-items-center header-style">{{'NSINSTANCES' | translate}}</div>
+ <span class="button">
+ <button class="btn btn-primary" type="button" placement="top" container="body" ngbTooltip="{{'PAGE.NSINSTANCE.NEWNSINSTANCE' | translate}}"
+ (click)="instantiateNS()">
+ <i class="fa fa-paper-plane" aria-hidden="true"></i> {{'PAGE.NSINSTANCE.NEWNSINSTANCE' | translate}}
+ </button>
+ </span>
+</div>
+<div class="row mt-2 mb-0 list-utilites-actions">
+ <div class="col-auto mr-auto">
+ <nav class="custom-items-config">
+ <span><i class="fas fa-clock text-warning"></i>{{operationalStateFirstStep}}</span>
+ <span><i class="fas fa-check-circle text-success"></i>{{operationalStateSecondStep}} /
+ {{configStateSecondStep}}</span>
+ <span><i class="fas fa-times-circle text-danger"></i>{{operationalStateThirdStep}}</span>
+ </nav>
+ </div>
+ <page-per-row class="mr-2" (pagePerRow)="onChange($event)"></page-per-row>
+ <page-reload></page-reload>
+</div>
+<div class="smarttable-style bg-white mt-1">
+ <ng2-smart-table [ngClass]="checkDataClass" [settings]="settings" [source]="dataSource" (userRowSelect)="onUserRowSelect($event)">
+ </ng2-smart-table>
+</div>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @file NS Instance Component
+ */
+import { Component, Injector, OnInit } from '@angular/core';
+import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateService } from '@ngx-translate/core';
+import { CONFIGCONSTANT, ERRORDATA, MODALCLOSERESPONSEDATA } from 'CommonModel';
+import { DataService } from 'DataService';
+import { environment } from 'environment';
+import { InstantiateNsComponent } from 'InstantiateNs';
+import { LocalDataSource } from 'ng2-smart-table';
+import { NSDInstanceData, NSInstanceDetails } from 'NSInstanceModel';
+import { NSInstancesActionComponent } from 'NSInstancesActionComponent';
+import { RestService } from 'RestService';
+import { Subscription } from 'rxjs';
+import { SharedService } from 'SharedService';
+
+/**
+ * Creating component
+ * @Component takes NSInstancesComponent.html as template url
+ */
+@Component({
+ templateUrl: './NSInstancesComponent.html',
+ styleUrls: ['./NSInstancesComponent.scss']
+})
+/** Exporting a class @exports NSInstancesComponent */
+export class NSInstancesComponent implements OnInit {
+ /** Injector to invoke other services @public */
+ public injector: Injector;
+
+ /** NS Instance array @public */
+ public nsInstanceData: object[] = [];
+
+ /** Datasource instance @public */
+ public dataSource: LocalDataSource = new LocalDataSource();
+
+ /** SelectedRows array @public */
+ public selectedRows: object[] = [];
+
+ /** Selected list array @public */
+ public selectList: object[] = [];
+
+ /** Instance component are stored in settings @public */
+ public settings: {} = {};
+
+ /** Contains objects for menu settings @public */
+ public columnList: {} = {};
+
+ /** Check the loading results @public */
+ public isLoadingResults: boolean = true;
+
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+
+ /** Class for empty and present data @public */
+ public checkDataClass: string;
+
+ /** operational State init data @public */
+ public operationalStateFirstStep: string = CONFIGCONSTANT.operationalStateFirstStep;
+
+ /** operational State running data @public */
+ public operationalStateSecondStep: string = CONFIGCONSTANT.operationalStateSecondStep;
+
+ /** operational State failed data @public */
+ public operationalStateThirdStep: string = CONFIGCONSTANT.operationalStateThirdStep;
+
+ /** Config State init data @public */
+ public configStateFirstStep: string = CONFIGCONSTANT.configStateFirstStep;
+
+ /** Config State init data @public */
+ public configStateSecondStep: string = CONFIGCONSTANT.configStateSecondStep;
+
+ /** Config State init data @public */
+ public configStateThirdStep: string = CONFIGCONSTANT.configStateThirdStep;
+
+ /** Instance of the modal service @private */
+ private modalService: NgbModal;
+
+ /** dataService to pass the data from one component to another @private */
+ private dataService: DataService;
+
+ /** Utilizes rest service for any CRUD operations @private */
+ private restService: RestService;
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ /** Contains tranlsate instance @private */
+ private translateService: TranslateService;
+
+ /** Instance of subscriptions @private */
+ private generateDataSub: Subscription;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.restService = this.injector.get(RestService);
+ this.dataService = this.injector.get(DataService);
+ this.sharedService = this.injector.get(SharedService);
+ this.translateService = this.injector.get(TranslateService);
+ this.modalService = this.injector.get(NgbModal);
+ }
+
+ /**
+ * Lifecyle Hooks the trigger before component is instantiate
+ */
+ public ngOnInit(): void {
+ this.generateTableColumn();
+ this.generateTableSettings();
+ this.generateData();
+ this.generateDataSub = this.sharedService.dataEvent.subscribe(() => { this.generateData(); });
+ }
+
+ /** Generate smart table row title and filters @public */
+ public generateTableSettings(): void {
+ this.settings = {
+ columns: this.columnList,
+ actions: { add: false, edit: false, delete: false, position: 'right' },
+ attr: this.sharedService.tableClassConfig(),
+ pager: this.sharedService.paginationPagerConfig(),
+ noDataMessage: this.translateService.instant('NODATAMSG')
+ };
+ }
+
+ /** Generate smart table row title and filters @public */
+ public generateTableColumn(): void {
+ this.columnList = {
+ name: { title: this.translateService.instant('NAME'), width: '15%', sortDirection: 'asc' },
+ identifier: { title: this.translateService.instant('IDENTIFIER'), width: '20%' },
+ NsdName: { title: this.translateService.instant('NSDNAME'), width: '15%' },
+ OperationalStatus: {
+ title: this.translateService.instant('OPERATIONALSTATUS'), width: '10%', type: 'html',
+ filter: {
+ type: 'list',
+ config: {
+ selectText: 'Select',
+ list: [
+ { value: this.operationalStateFirstStep, title: this.operationalStateFirstStep },
+ { value: this.operationalStateSecondStep, title: this.operationalStateSecondStep },
+ { value: this.operationalStateThirdStep, title: this.operationalStateThirdStep }
+ ]
+ }
+ },
+ valuePrepareFunction: (cell: NSDInstanceData, row: NSDInstanceData): string => {
+ if (row.OperationalStatus === this.operationalStateFirstStep) {
+ return `<span class="icon-label" title="${row.OperationalStatus}">
+ <i class="fas fa-clock text-warning"></i>
+ </span>`;
+ } else if (row.OperationalStatus === this.operationalStateSecondStep) {
+ return `<span class="icon-label" title="${row.OperationalStatus}">
+ <i class="fas fa-check-circle text-success"></i>
+ </span>`;
+ } else if (row.OperationalStatus === this.operationalStateThirdStep) {
+ return `<span class="icon-label" title="${row.OperationalStatus}">
+ <i class="fas fa-times-circle text-danger"></i>
+ </span>`;
+ } else {
+ return `<span>${row.OperationalStatus}</span>`;
+ }
+ }
+ },
+ ConfigStatus: {
+ title: this.translateService.instant('CONFIGSTATUS'), width: '10%', type: 'html',
+ filter: {
+ type: 'list',
+ config: {
+ selectText: 'Select',
+ list: [
+ { value: this.configStateFirstStep, title: this.configStateFirstStep },
+ { value: this.configStateSecondStep, title: this.configStateSecondStep },
+ { value: this.configStateThirdStep, title: this.configStateThirdStep }
+ ]
+ }
+ },
+ valuePrepareFunction: (cell: NSDInstanceData, row: NSDInstanceData): string => {
+ if (row.ConfigStatus === this.configStateFirstStep) {
+ return `<span class="icon-label" title="${row.ConfigStatus}">
+ <i class="fas fa-clock text-warning"></i>
+ </span>`;
+ } else if (row.ConfigStatus === this.configStateSecondStep) {
+ return `<span class="icon-label" title="${row.ConfigStatus}">
+ <i class="fas fa-check-circle text-success"></i>
+ </span>`;
+ } else if (row.ConfigStatus === this.configStateThirdStep) {
+ return `<span class="icon-label" title="${row.ConfigStatus}">
+ <i class="fas fa-times-circle text-danger"></i>
+ </span>`;
+ } else {
+ return `<span>${row.ConfigStatus}</span>`;
+ }
+ }
+ },
+ DetailedStatus: { title: this.translateService.instant('DETAILEDSTATUS'), width: '15%' },
+ Actions: {
+ name: 'Action', width: '15%', filter: false, sort: false, type: 'custom',
+ title: this.translateService.instant('ACTIONS'),
+ valuePrepareFunction: (cell: NSDInstanceData, row: NSDInstanceData): NSDInstanceData => row,
+ renderComponent: NSInstancesActionComponent
+ }
+ };
+ }
+
+ /** generateData initiate the ns-instance list @public */
+ public generateData(): void {
+ this.isLoadingResults = true;
+ this.restService.getResource(environment.NSDINSTANCES_URL).subscribe((nsdInstancesData: NSInstanceDetails[]) => {
+ this.nsInstanceData = [];
+ nsdInstancesData.forEach((nsdInstanceData: NSInstanceDetails) => {
+ const nsDataObj: NSDInstanceData = {
+ name: nsdInstanceData.name,
+ identifier: nsdInstanceData.id,
+ NsdName: nsdInstanceData['nsd-name-ref'],
+ OperationalStatus: nsdInstanceData['operational-status'],
+ ConfigStatus: nsdInstanceData['config-status'],
+ DetailedStatus: nsdInstanceData['detailed-status'],
+ memberIndex: nsdInstanceData.nsd['constituent-vnfd'],
+ nsConfig: nsdInstanceData.nsd['ns-configuration']
+ };
+ this.nsInstanceData.push(nsDataObj);
+ });
+ if (this.nsInstanceData.length > 0) {
+ this.checkDataClass = 'dataTables_present';
+ } else {
+ this.checkDataClass = 'dataTables_empty';
+ }
+ this.dataSource.load(this.nsInstanceData).then((data: {}) => {
+ this.isLoadingResults = false;
+ }).catch();
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'get');
+ this.isLoadingResults = false;
+ });
+ }
+
+ /** smart table listing manipulation @public */
+ public onChange(perPageValue: number): void {
+ this.dataSource.setPaging(1, perPageValue, true);
+ }
+
+ /** smart table listing manipulation @public */
+ public onUserRowSelect(event: MessageEvent): void {
+ Object.assign(event.data, { page: 'ns-instance' });
+ this.dataService.changeMessage(event.data);
+ }
+
+ /** Instantiate NS using modalservice @public */
+ public instantiateNS(): void {
+ const modalRef: NgbModalRef = this.modalService.open(InstantiateNsComponent, { backdrop: 'static' });
+ modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
+ if (result) {
+ this.generateData();
+ }
+ }).catch();
+ }
+
+ /**
+ * Lifecyle hook which get trigger on component destruction
+ */
+ public ngOnDestroy(): void {
+ this.generateDataSub.unsubscribe();
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="modal-header">
+ <h4 class="modal-title" id="modal-basic-title">{{'PERFORMACTION' | translate}}</h4>
+ <button class="button-xs" type="button" class="close" aria-label="Close" (click)="activeModal.close()">
+ <i class="fas fa-times-circle text-danger"></i>
+ </button>
+</div>
+<form [formGroup]="primitiveForm" (ngSubmit)="execNSPrimitive()">
+ <div class="modal-body">
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label">{{'PRIMITIVETYPE' | translate}}*</label>
+ <div class="col-sm-8">
+ <ng-select (change)="primitiveTypeChange($event)" [clearable]="false"
+ placeholder="{{'SELECT' | translate}}" [items]="primitiveTypeList" bindLabel="title"
+ bindValue="value" [(ngModel)]="primitiveType" id="primitiveType"
+ [ngModelOptions]="{standalone: true}"></ng-select>
+ </div>
+ </div>
+ <div class="form-group row">
+ <ng-container *ngIf="primitiveType == 'VNF_Primitive'">
+ <label class="col-sm-4 col-form-label">VNF {{'MEMBERINDEX' | translate}}*</label>
+ <div class="col-sm-3">
+ <ng-select (change)="indexChange($event)" [clearable]="false" placeholder="{{'SELECT' | translate}}"
+ [items]="params.memberIndex" bindLabel="member-vnf-index" bindValue="member-vnf-index"
+ formControlName="vnf_member_index" id="vnf_member_index"
+ [ngClass]="{ 'is-invalid': submitted && f.vnf_member_index.errors }"></ng-select>
+ </div>
+ </ng-container>
+ <label [ngClass]="{ 'col-sm-4': primitiveType != 'VNF_Primitive', 'col-sm-2': primitiveType == 'VNF_Primitive' }" class="col-form-label">
+ {{'PAGE.NSPRIMITIVE.PRIMITIVE' | translate}}*</label>
+ <div [ngClass]="{ 'col-sm-8': primitiveType != 'VNF_Primitive', 'col-sm-3': primitiveType == 'VNF_Primitive' }" class="col-sm-3">
+ <ng-select (change)="primitiveChange($event)" [clearable]="false" placeholder="{{'SELECT' | translate}}"
+ [items]="primitiveList" bindLabel="name" bindValue="name" formControlName="primitive" id="primitive"
+ [ngClass]="{ 'is-invalid': submitted && f.primitive.errors }"></ng-select>
+ </div>
+ </div>
+ <ng-container *ngIf="primitiveParameter.length > 0">
+ <div class="form-group row p-2 bg-light text-white justify-content-end">
+ <div class="col-5">
+ <button type="button" class="btn btn-primary" (click)="createPrimitiveParams()">
+ <i class="fas fa-plus-circle"></i>
+ {{'PAGE.NSPRIMITIVE.ADDPRIMITIVEPARAMS' | translate}}</button>
+ </div>
+ </div>
+ <div formArrayName="primitive_params" *ngFor="let params of getControls(); let i = index;">
+ <div class="form-group row" [formGroupName]="i">
+ <label class="col-sm-2 col-form-label">{{'NAME' | translate}}:</label>
+ <div class="col-sm-3">
+ <ng-select placeholder="{{'SELECT' | translate}}" [clearable]="false"
+ [items]="primitiveParameter" bindLabel="name" bindValue="name"
+ formControlName="primitive_params_name" id="parameter{{i}}"
+ [ngClass]="{ 'is-invalid': submitted && params.controls.primitive_params_name.errors }">
+ </ng-select>
+ </div>
+ <div class="col-sm-1"></div>
+ <label class="col-sm-2 col-form-label">{{'VALUE' | translate}}:</label>
+ <div class="col-sm-3">
+ <input type="text" class="form-control" formControlName="primitive_params_value"
+ [ngClass]="{ 'is-invalid': submitted && params.controls.primitive_params_value.errors }">
+ </div>
+ <div class="col-sm-1" [hidden]="i==0">
+ <button type="button" class="btn btn-sm btn-danger remove-mapping"
+ (click)="removePrimitiveParams(i)">
+ <i class="fas fa-times-circle"></i>
+ </button>
+ </div>
+ </div>
+ </div>
+ </ng-container>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-danger" (click)="activeModal.close()">{{'CANCEL' | translate}}</button>
+ <button type="submit" class="btn btn-primary">{{'EXECUTE' | translate}}</button>
+ </div>
+</form>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+@import '../../../assets/scss/mixins/mixin';
+@import '../../../assets/scss/variable';
+
+.primitive-params-head {
+ @include padding-value(10, 10, 10, 10);
+ line-height: 2em;
+ .btn-params {
+ @include border(all, 1, solid, $white);
+ }
+}
+
+.remove-params {
+ display: flex;
+ align-items: center;
+ font-size: 20px;
+ cursor: pointer;
+}
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @file NS Instance Primitive Component
+ */
+import { Component, Injector, Input, OnInit } from '@angular/core';
+import { AbstractControl, FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms';
+import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateService } from '@ngx-translate/core';
+import { NotifierService } from 'angular-notifier';
+import { APIURLHEADER, ERRORDATA, URLPARAMS } from 'CommonModel';
+import { DataService } from 'DataService';
+import { environment } from 'environment';
+import { NSData } from 'NSDModel';
+import { NSPrimitiveParams } from 'NSInstanceModel';
+import { RestService } from 'RestService';
+import { SharedService } from 'SharedService';
+import { isNullOrUndefined } from 'util';
+
+/**
+ * Creating component
+ * @Component takes NSPrimitiveComponent.html as template url
+ */
+@Component({
+ templateUrl: './NSPrimitiveComponent.html',
+ styleUrls: ['./NSPrimitiveComponent.scss']
+})
+/** Exporting a class @exports NSPrimitiveComponent */
+export class NSPrimitiveComponent implements OnInit {
+ /** Form valid on submit trigger @public */
+ public submitted: boolean = false;
+
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** Instance for active modal service @public */
+ public activeModal: NgbActiveModal;
+
+ /** FormGroup instance added to the form @ html @public */
+ public primitiveForm: FormGroup;
+
+ /** Primitive params array @public */
+ public primitiveParams: FormArray;
+
+ /** Variable set for twoway binding @public */
+ public nsdId: string;
+
+ /** Check the loading results @public */
+ public isLoadingResults: boolean = false;
+
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+
+ /** Contains list of primitive parameter @public */
+ public primitiveParameter: {}[] = [];
+
+ /** Input contains component objects @public */
+ @Input() public params: URLPARAMS;
+
+ /** Contains list of primitive actions @public */
+ public primitiveList: {}[];
+
+ /** Contains objects that is used to hold types of primitive @public */
+ public primitiveTypeList: {}[] = [];
+
+ /** Model value used to hold selected primitive type @public */
+ public primitiveType: string;
+
+ /** FormBuilder instance added to the formBuilder @private */
+ private formBuilder: FormBuilder;
+
+ /** Utilizes rest service for any CRUD operations @private */
+ private restService: RestService;
+
+ /** packages data service collections @private */
+ private dataService: DataService;
+
+ /** Contains tranlsate instance @private */
+ private translateService: TranslateService;
+
+ /** Notifier service to popup notification @private */
+ private notifierService: NotifierService;
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ /** Contains objects that is used to convert key/value pair @private */
+ private objectPrimitiveParams: {} = {};
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.restService = this.injector.get(RestService);
+ this.dataService = this.injector.get(DataService);
+ this.translateService = this.injector.get(TranslateService);
+ this.notifierService = this.injector.get(NotifierService);
+ this.sharedService = this.injector.get(SharedService);
+ this.activeModal = this.injector.get(NgbActiveModal);
+ this.formBuilder = this.injector.get(FormBuilder);
+ this.primitiveTypeList = [{ title: this.translateService.instant('VNFPRIMITIVE'), value: 'VNF_Primitive' }];
+ this.primitiveType = 'VNF_Primitive';
+ }
+
+ /**
+ * Lifecyle Hooks the trigger before component is instantiate
+ */
+ public ngOnInit(): void {
+ /** Setting up initial value for NSD */
+ this.dataService.currentMessage.subscribe((event: NSData) => {
+ if (event.identifier !== undefined || event.identifier !== '' || event.identifier !== null) {
+ this.nsdId = event.identifier;
+ }
+ });
+ if (!isNullOrUndefined(this.params.nsConfig)) {
+ this.primitiveTypeList.push({ title: this.translateService.instant('NSPRIMITIVE'), value: 'NS_Primitive' });
+ }
+ this.initializeForm();
+ }
+
+ /** convenience getter for easy access to form fields */
+ get f(): FormGroup['controls'] { return this.primitiveForm.controls; }
+
+ /** initialize Forms @public */
+ public initializeForm(): void {
+ this.primitiveForm = this.formBuilder.group({
+ primitive: [null, [Validators.required]],
+ vnf_member_index: [null, [Validators.required]],
+ primitive_params: this.formBuilder.array([this.primitiveParamsBuilder()])
+ });
+ }
+
+ /** Generate primitive params @public */
+ public primitiveParamsBuilder(): FormGroup {
+ return this.formBuilder.group({
+ primitive_params_name: [null, [Validators.required]],
+ primitive_params_value: ['', [Validators.required]]
+ });
+ }
+
+ /** Handle FormArray Controls @public */
+ public getControls(): AbstractControl[] {
+ return (this.getFormControl('primitive_params') as FormArray).controls;
+ }
+
+ /** Push all primitive params on user's action @public */
+ public createPrimitiveParams(): void {
+ this.primitiveParams = this.getFormControl('primitive_params') as FormArray;
+ this.primitiveParams.push(this.primitiveParamsBuilder());
+ }
+
+ /** Remove primitive params on user's action @public */
+ public removePrimitiveParams(index: number): void {
+ this.primitiveParams.removeAt(index);
+ }
+
+ /** Execute NS Primitive @public */
+ public execNSPrimitive(): void {
+ this.submitted = true;
+ this.objectPrimitiveParams = {};
+ this.sharedService.cleanForm(this.primitiveForm);
+ if (this.primitiveForm.invalid) { return; } // Proceed, onces form is valid
+ this.primitiveForm.value.primitive_params.forEach((params: NSPrimitiveParams) => {
+ if (params.primitive_params_name !== null && params.primitive_params_value !== '') {
+ this.objectPrimitiveParams[params.primitive_params_name] = params.primitive_params_value;
+ }
+ });
+ //Prepare primitive params
+ const primitiveParamsPayLoads: {} = {
+ primitive: this.primitiveForm.value.primitive,
+ primitive_params: this.objectPrimitiveParams
+ };
+ if (this.primitiveType === 'VNF_Primitive') {
+ // tslint:disable-next-line: no-string-literal
+ primitiveParamsPayLoads['vnf_member_index'] = this.primitiveForm.value.vnf_member_index;
+ }
+ const apiURLHeader: APIURLHEADER = {
+ url: environment.NSDINSTANCES_URL + '/' + this.nsdId + '/action'
+ };
+ this.isLoadingResults = true;
+ this.restService.postResource(apiURLHeader, primitiveParamsPayLoads).subscribe((result: {}) => {
+ this.activeModal.dismiss();
+ this.notifierService.notify('success', this.translateService.instant('PAGE.NSPRIMITIVE.EXECUTEDSUCCESSFULLY'));
+ this.isLoadingResults = false;
+ }, (error: ERRORDATA) => {
+ this.isLoadingResults = false;
+ this.restService.handleError(error, 'post');
+ });
+ }
+ /** Primitive type change event @public */
+ public primitiveTypeChange(data: { value: string }): void {
+ this.primitiveList = [];
+ this.primitiveParameter = [];
+ this.initializeForm();
+ if (data.value === 'NS_Primitive') {
+ this.primitiveList = !isNullOrUndefined(this.params.nsConfig['config-primitive']) ?
+ this.params.nsConfig['config-primitive'] : [];
+ this.getFormControl('vnf_member_index').setValidators([]);
+ }
+ }
+ /** Member index change event */
+ public indexChange(data: {}): void {
+ if (data) {
+ this.getVnfdInfo(data['vnfd-id-ref']);
+ } else {
+ this.primitiveList = [];
+ this.getFormControl('primitive').setValue(null);
+ this.primitiveParameter = [];
+ }
+ }
+ /** Primivtive change event */
+ public primitiveChange(data: { parameter: {}[] }): void {
+ this.primitiveParameter = [];
+ const formArr: FormArray = this.getFormControl('primitive_params') as FormArray;
+ formArr.controls = [];
+ this.createPrimitiveParams();
+ if (data) {
+ this.updatePrimitive(data);
+ }
+ }
+ /** Update primitive value based on parameter */
+ private updatePrimitive(primitive: { parameter: {}[] }): void {
+ if (primitive.parameter) {
+ this.primitiveParameter = primitive.parameter;
+ } else {
+ this.primitiveParameter = [];
+ const formArr: AbstractControl[] = this.getControls();
+ formArr.forEach((formGp: FormGroup) => {
+ formGp.controls.primitive_params_name.setValidators([]);
+ formGp.controls.primitive_params_name.updateValueAndValidity();
+ formGp.controls.primitive_params_value.setValidators([]);
+ formGp.controls.primitive_params_value.updateValueAndValidity();
+ });
+ }
+ }
+ /** Get primivitive actions from vnfd data */
+ private getVnfdInfo(vnfdRef: string): void {
+ this.primitiveList = [];
+ this.primitiveParameter = [];
+ this.getFormControl('primitive').setValue(null);
+ const apiUrl: string = environment.VNFPACKAGES_URL + '?short-name=' + vnfdRef;
+ this.isLoadingResults = true;
+ this.restService.getResource(apiUrl)
+ .subscribe((vnfdInfo: {}) => {
+ if (vnfdInfo[0]['vnf-configuration']) {
+ this.primitiveList = vnfdInfo[0]['vnf-configuration']['config-primitive'];
+ }
+ this.isLoadingResults = false;
+ }, (error: ERRORDATA) => {
+ this.isLoadingResults = false;
+ this.restService.handleError(error, 'get');
+ });
+ }
+ /** Used to get the AbstractControl of controlName passed @private */
+ private getFormControl(controlName: string): AbstractControl {
+ return this.primitiveForm.controls[controlName];
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<ng-sidebar-container class="ns-instance-topology-sidebar-container">
+ <!-- A sidebar -->
+ <ng-sidebar [(opened)]="sideBarOpened" position="left">
+ <div class="sidebar-header">
+ <span class="topology_title" *ngIf="isShowNSDetails">{{'NS' | translate}} {{'VIEW' | translate}}</span>
+ <span class="topology_title" *ngIf="isShowVLetails">{{'PAGE.TOPOLOGY.VIRTUALLINK' | translate}}</span>
+ <span class="topology_title" *ngIf="isShowVNFRDetails">{{'PAGE.TOPOLOGY.VNF' | translate}}</span>
+ </div>
+ <div class="sidebar-body">
+ <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 mb-2" *ngIf="isShowNSDetails && nsInfo">
+ <div class="row">
+ <div class="col-12 p-0">
+ <table class="table table-bordered text-dark custom-table">
+ <tr>
+ <td>{{'NS' | translate}} {{'INSTANCE' | translate}} Id</td>
+ <td>{{(nsInfo.nsInstanceID)?nsInfo.nsInstanceID:'-'}}</td>
+ </tr>
+ <tr>
+ <td>{{'NSDNAME' | translate}}</td>
+ <td>{{(nsInfo.nsName)?nsInfo.nsName:'-'}}</td>
+ </tr>
+ <tr>
+ <td>{{'OPERATIONALSTATUS' | translate}}</td>
+ <td>{{(nsInfo.nsOperationalStatus)?nsInfo.nsOperationalStatus:'-'}}</td>
+ </tr>
+ <tr>
+ <td>{{'CONFIGSTATUS' | translate}}</td>
+ <td>{{(nsInfo.nsConfigStatus)?nsInfo.nsConfigStatus:'-'}}</td>
+ </tr>
+ <tr>
+ <td>{{'DETAILEDSTATUS' | translate}}</td>
+ <td>{{(nsInfo.nsDetailedStatus)?nsInfo.nsDetailedStatus:'-'}}</td>
+ </tr>
+ <tr>
+ <td>{{'RESOURCEORCHESTRATOR' | translate}}</td>
+ <td>{{(nsInfo.nsResourceOrchestrator)?nsInfo.nsResourceOrchestrator:'-'}}</td>
+ </tr>
+ </table>
+ </div>
+ </div>
+ </div>
+ <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 mb-2" *ngIf="isShowVLetails && virtualLink">
+ <div class="row">
+ <div class="col-12 p-0">
+ <table class="table table-bordered text-dark custom-table">
+ <tbody>
+ <tr>
+ <td>short-name</td>
+ <td>{{(virtualLink.shortName)?virtualLink.shortName:'-'}}</td>
+ </tr>
+ <tr>
+ <td>Name</td>
+ <td>{{(virtualLink.name)?virtualLink.name:'-'}}</td>
+ </tr>
+ <tr>
+ <td>Vim network name</td>
+ <td>{{(virtualLink.vimNetworkName)?virtualLink.vimNetworkName:'-'}}</td>
+ </tr>
+ <tr>
+ <td>Type</td>
+ <td>{{(virtualLink.type)?virtualLink.type:'-'}}</td>
+ </tr>
+ <tr>
+ <td>Id</td>
+ <td>{{(virtualLink.id)?virtualLink.id:'-'}}</td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ </div>
+ <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 mb-2" *ngIf="isShowVNFRDetails && vnfr">
+ <div class="row">
+ <div class="col-12 p-0">
+ <table class="table table-bordered text-dark custom-table">
+ <tbody>
+ <tr>
+ <td>VIM Id</td>
+ <td>{{(vnfr.vimID)?vnfr.vimID:'-'}}</td>
+ </tr>
+ <tr>
+ <td>_id</td>
+ <td>{{(vnfr._id)?vnfr._id:'-'}}</td>
+ </tr>
+ <tr>
+ <td>IP</td>
+ <td>{{(vnfr.ip)?vnfr.ip:'-'}}</td>
+ </tr>
+ <tr>
+ <td>Nsr Id</td>
+ <td>{{(vnfr.nsrID)?vnfr.nsrID:'-'}}</td>
+ </tr>
+ <tr>
+ <td>Id</td>
+ <td>{{(vnfr.id)?vnfr.id:'-'}}</td>
+ </tr>
+ <tr>
+ <td>Vnfd Ref</td>
+ <td>{{(vnfr.vnfdRef)?vnfr.vnfdRef:'-'}}</td>
+ </tr>
+ <tr>
+ <td>Vnfd Id</td>
+ <td>{{(vnfr.vnfdID)?vnfr.vnfdID:'-'}}</td>
+ </tr>
+ <tr>
+ <td>Member index</td>
+ <td>{{(vnfr.memberIndex)?vnfr.memberIndex:'-'}}</td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ </div>
+ </div>
+ </ng-sidebar>
+ <!-- Page content -->
+ <div ng-sidebar-content>
+ <button (click)="toggleSidebar()" class="btn btn-default" placement="right" ngbTooltip="{{'OPEN' | translate }}">
+ <i class="fa fa-arrow-right detail-sidebar" aria-hidden="true"></i>
+ </button>
+ </div>
+</ng-sidebar-container>
+<div class="container-fluid text-dark">
+ <div class="row ns-instance-form justify-content-end ">
+ <div class="col-xs-9 col-sm-9 col-md-9 col-lg-9">
+ <div class="row">
+ <div class="col-xs-6 col-sm-6 col-md-6 col-lg-6 pl-0">
+ <div class="btn-group list" role="group" aria-label="Basic example">
+ <button type="button" class="btn btn-primary topology-btn" (click)="onFreeze()"
+ [class.pinned]="classApplied" placement="top" container="body"
+ ngbTooltip="{{(classApplied ? 'UNFREEZE' : 'FREEZE') | translate}}">
+ <i class="fas fa-thumbtack"></i>
+ </button>
+ </div>
+ </div>
+ <div class="col-xs-6 col-sm-6 col-md-6 col-lg-6 text-right pr-0 badgegroup">
+ <span class="badge badge-primary badge-pill bg-white text-body font-weight-bold">
+ <img src="assets/images/VNFD.svg" class="ns-svg" draggable="false"/>
+ <br>VNFR</span>
+ <span class="badge badge-primary badge-pill bg-white text-body font-weight-bold">
+ <img src="assets/images/VL.svg" class="ns-svg" draggable="false"/>
+ <br>VL</span>
+ <span class="badge badge-primary badge-pill bg-white text-body font-weight-bold">
+ <img src="assets/images/CP.svg" class="ns-svg" draggable="false"/>
+ <br>CP</span>
+ </div>
+ </div>
+ <div class="row border-all">
+ <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 svg-container">
+ <svg preserveAspectRatio="xMidYMin slice" id="graphContainer" #graphContainer></svg>
+ </div>
+ </div>
+ </div>
+ </div>
+</div>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @file NS Topology Component
+ */
+/* tslint:disable:no-increment-decrement */
+import { Component, ElementRef, Injector, ViewChild, ViewEncapsulation } from '@angular/core';
+import { ActivatedRoute } from '@angular/router';
+import { Router } from '@angular/router';
+import { TranslateService } from '@ngx-translate/core';
+import { ERRORDATA } from 'CommonModel';
+import * as d3 from 'd3';
+import { environment } from 'environment';
+import * as HttpStatus from 'http-status-codes';
+import { VNFDCONNECTIONPOINTREF } from 'NSDModel';
+import { COMPOSERNODES, CONNECTIONPOINT, NSD, NSDVLD, NSINFO, NSInstanceDetails, NSINSTANCENODES, VLINFO, VNFRINFO } from 'NSInstanceModel';
+import { GRAPHDETAILS, Tick, TickPath } from 'NSTopologyModel';
+import { RestService } from 'src/services/RestService';
+import { isNullOrUndefined } from 'util';
+
+/**
+ * Creating component
+ * @Component takes NSTopologyComponent.html as template url
+ */
+@Component({
+ selector: 'app-ns-topology',
+ templateUrl: './NSTopologyComponent.html',
+ styleUrls: ['./NSTopologyComponent.scss'],
+ encapsulation: ViewEncapsulation.None
+})
+/** Exporting a class @exports NSTopologyComponent */
+export class NSTopologyComponent {
+ /** Injector to invoke other services @public */
+ public injector: Injector;
+ /** View child contains graphContainer ref @public */
+ @ViewChild('graphContainer', { static: true }) public graphContainer: ElementRef;
+ /** Holds the basic information of NS @public */
+ public nsInfo: NSINFO;
+ /** Contains tranlsate instance @private */
+ public translateService: TranslateService;
+ /** Add the activeclass for the selected @public */
+ public activeClass: string = 'active';
+ /** Add the fixed class for the freeze @public */
+ public fixedClass: string = 'fixed';
+ /** Check the loading results @public */
+ public isLoadingResults: boolean = true;
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+ /** Assign the forcesimulation active @public */
+ public forceSimulationActive: boolean = false;
+ /** Assign pinned class for the button when freezed @public */
+ public classApplied: boolean = false;
+ /** Contains sidebar open status @public */
+ public sideBarOpened: boolean = true;
+ /** Need to show the NS Details @public */
+ public isShowNSDetails: boolean = true;
+ /** Need to show the VL Details @public */
+ public isShowVLetails: boolean = false;
+ /** Need to show the VNFR Details @public */
+ public isShowVNFRDetails: boolean = false;
+ /** Show right side info of Virtual Link @public */
+ public virtualLink: VLINFO;
+ /** Show right side info of Virtual Link @public */
+ public vnfr: VNFRINFO;
+
+ /** Contains lastkeypressed instance @private */
+ private lastKeyDown: number = -1;
+ /** Instance of the rest service @private */
+ private restService: RestService;
+ /** Holds the instance of AuthService class of type AuthService @private */
+ private activatedRoute: ActivatedRoute;
+ /** Holds the NS Id @private */
+ private nsIdentifier: string;
+ /** Contains SVG attributes @private */
+ // tslint:disable-next-line:no-any
+ private svg: any;
+ /** Contains forced node animations @private */
+ // tslint:disable-next-line:no-any
+ private force: any;
+ /** Contains path information of the node */
+ // tslint:disable-next-line:no-any
+ private path: any;
+ /** Contains node network @private */
+ // tslint:disable-next-line:no-any
+ private network: any;
+ /** Contains node square @private */
+ // tslint:disable-next-line:no-any
+ private square: any;
+ /** Contains node circle @private */
+ // tslint:disable-next-line:no-any
+ private circle: any;
+ /** Contains the NS information @private */
+ private nsData: NSInstanceDetails;
+ /** Contains NDS information of a descriptors */
+ private nsdData: NSD;
+ /** Contains node information @private */
+ private nodes: NSINSTANCENODES[] = [];
+ /** Contains links information @private */
+ private links: {}[] = [];
+ /** holds cp count/iteration @private */
+ private cpCount: number;
+ /** VNFD nodes @private */
+ private vnfdNodes: {}[] = [];
+ /** VLD nodes @private */
+ private vldNodes: {}[] = [];
+ /** Connection CP nodes @private */
+ private cpNodes: {}[] = [];
+ /** Set timeout @private */
+ private TIMEOUT: number = 2000;
+ /** Rendered nodes represent vnf @private */
+ // tslint:disable-next-line:no-any
+ private gSquare: any;
+ /** Rendered nodes represent network @private */
+ // tslint:disable-next-line:no-any
+ private gNetwork: any;
+ /** Rendered nodes represent network @private */
+ // tslint:disable-next-line:no-any
+ private gCircle: any;
+ /** Service holds the router information @private */
+ private router: Router;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.restService = this.injector.get(RestService);
+ this.activatedRoute = this.injector.get(ActivatedRoute);
+ this.translateService = this.injector.get(TranslateService);
+ this.router = this.injector.get(Router);
+ }
+
+ /**
+ * Lifecyle Hooks the trigger before component is instantiate @public
+ */
+ public ngOnInit(): void {
+ // tslint:disable-next-line:no-backbone-get-set-outside-model
+ this.nsIdentifier = this.activatedRoute.snapshot.paramMap.get('id');
+ this.generateData();
+ }
+ /** Event to freeze the animation @public */
+ public onFreeze(): void {
+ this.classApplied = !this.classApplied;
+ const alreadyFixedIsActive: boolean = d3.select('svg#graphContainer').classed(this.fixedClass);
+ d3.select('svg#graphContainer').classed(this.fixedClass, !alreadyFixedIsActive);
+ if (alreadyFixedIsActive) {
+ this.force.stop();
+ }
+ this.forceSimulationActive = alreadyFixedIsActive;
+ this.nodes.forEach((d: COMPOSERNODES) => {
+ d.fx = (alreadyFixedIsActive) ? null : d.x;
+ d.fy = (alreadyFixedIsActive) ? null : d.y;
+ });
+ if (alreadyFixedIsActive) {
+ this.force.restart();
+ }
+ }
+ /** Events handles when dragended @public */
+ public toggleSidebar(): void {
+ this.sideBarOpened = !this.sideBarOpened;
+ this.deselectAllNodes();
+ this.showRightSideInfo(true, false, false);
+ }
+ /** Get the default Configuration of containers @private */
+ private getGraphContainerAttr(): GRAPHDETAILS {
+ return {
+ width: 700,
+ height: 400,
+ nodeHeight: 50,
+ nodeWidth: 35,
+ textX: -35,
+ textY: 30,
+ radius: 5,
+ distance: 50,
+ strength: -500,
+ forcex: 2,
+ forcey: 2,
+ sourcePaddingYes: 17,
+ sourcePaddingNo: 12,
+ targetPaddingYes: 4,
+ targetPaddingNo: 3,
+ alphaTarget: 0.3,
+ imageX: -25,
+ imageY: -25,
+ shiftKeyCode: 17
+ };
+ }
+ /** Show the right-side information @private */
+ private showRightSideInfo(nsDetails: boolean, vlDetails: boolean, vnfrDeails: boolean): void {
+ this.isShowNSDetails = nsDetails;
+ this.isShowVLetails = vlDetails;
+ this.isShowVNFRDetails = vnfrDeails;
+ }
+ /** De-select all the selected nodes @private */
+ private deselectAllNodes(): void {
+ this.square.select('image').classed(this.activeClass, false);
+ this.network.select('image').classed(this.activeClass, false);
+ this.circle.select('image').classed(this.activeClass, false);
+ }
+ /** Prepare all the information for node creation @private */
+ private generateData(): void {
+ this.restService.getResource(environment.NSINSTANCESCONTENT_URL + '/' + this.nsIdentifier).subscribe((nsData: NSInstanceDetails) => {
+ this.nsData = nsData;
+ this.nsInfo = {
+ nsInstanceID: nsData._id,
+ nsName: nsData.name,
+ nsOperationalStatus: nsData['operational-status'],
+ nsConfigStatus: nsData['config-status'],
+ nsDetailedStatus: nsData['detailed-status'],
+ nsResourceOrchestrator: nsData['resource-orchestrator']
+ };
+ if (this.nsData['constituent-vnfr-ref'] !== undefined) {
+ this.generateVNFRCPNodes();
+ }
+ if (this.nsData.vld !== undefined) {
+ this.generateVLDNetworkNodes();
+ }
+ setTimeout(() => {
+ this.pushAllNodes();
+ this.generateVNFDCP();
+ this.generateVLDCP();
+ this.isLoadingResults = false;
+ this.createNode(this.nodes, this.links);
+ }, this.TIMEOUT);
+ }, (error: ERRORDATA) => {
+ this.isLoadingResults = false;
+ if (error.error.status === HttpStatus.NOT_FOUND || error.error.status === HttpStatus.UNAUTHORIZED) {
+ this.router.navigateByUrl('404', { skipLocationChange: true }).catch();
+ } else {
+ this.restService.handleError(error, 'get');
+ }
+ });
+ }
+
+ /** Fetching all the VNFR Information @private */
+ private generateVNFRCPNodes(): void {
+ this.nsData['constituent-vnfr-ref'].forEach((vnfdrID: string) => {
+ this.restService.getResource(environment.VNFINSTANCES_URL + '/' + vnfdrID).subscribe((vndfrDetail: NSD) => {
+ this.nodes.push({
+ id: vndfrDetail['vnfd-ref'] + ':' + vndfrDetail['member-vnf-index-ref'],
+ nodeTypeRef: 'vnfd',
+ cp: vndfrDetail['connection-point'],
+ vdur: vndfrDetail.vdur,
+ vld: vndfrDetail.vld,
+ nsID: vndfrDetail['nsr-id-ref'],
+ vnfdID: vndfrDetail['vnfd-id'],
+ vimID: vndfrDetail['vim-account-id'],
+ vndfrID: vndfrDetail.id,
+ ipAddress: vndfrDetail['ip-address'],
+ memberIndex: vndfrDetail['member-vnf-index-ref'],
+ vnfdRef: vndfrDetail['vnfd-ref'],
+ selectorId: 'nsInst-' + vndfrDetail.id
+ });
+ // Fetching all the connection point of VNF & Interface
+ vndfrDetail['connection-point'].forEach((cp: CONNECTIONPOINT) => {
+ this.nodes.push({
+ id: cp.name + ':' + vndfrDetail['member-vnf-index-ref'],
+ vndfCPRef: vndfrDetail['vnfd-ref'] + ':' + vndfrDetail['member-vnf-index-ref'],
+ nodeTypeRef: 'cp',
+ name: cp.name
+ });
+ });
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'get');
+ });
+ });
+ }
+
+ /** Fetching all the VLD/Network Information @private */
+ private generateVLDNetworkNodes(): void {
+ this.nsdData = this.nsData.nsd;
+ this.nsdData.vld.forEach((ref: NSDVLD) => {
+ this.nodes.push({
+ id: ref.id,
+ nodeTypeRef: 'vld',
+ name: ref.name,
+ type: ref.type,
+ vnfdCP: ref['vnfd-connection-point-ref'],
+ vimNetworkName: ref['vim-network-name'],
+ shortName: ref['short-name'],
+ selectorId: 'nsInst-' + ref.id
+ });
+ });
+ }
+
+ /** Pushing connection points of path/links nodes @private */
+ private pushAllNodes(): void {
+ this.nodes.forEach((nodeList: NSINSTANCENODES) => {
+ if (nodeList.nodeTypeRef === 'vnfd') {
+ this.vnfdNodes.push(nodeList);
+ } else if (nodeList.nodeTypeRef === 'vld') {
+ this.vldNodes.push(nodeList);
+ } else if (nodeList.nodeTypeRef === 'cp') {
+ this.cpNodes.push(nodeList);
+ }
+ });
+ }
+
+ /** Get CP position based on vndf @private */
+ private generateVNFDCP(): void {
+ this.vnfdNodes.forEach((list: NSINSTANCENODES) => {
+ const vndfPos: number = this.nodes.map((e: NSINSTANCENODES) => { return e.id; }).indexOf(list.id);
+ this.cpCount = 0;
+ this.nodes.forEach((res: NSINSTANCENODES) => {
+ if (res.nodeTypeRef === 'cp' && res.vndfCPRef === list.id) {
+ this.links.push({ source: this.nodes[vndfPos], target: this.nodes[this.cpCount] });
+ }
+ this.cpCount++;
+ });
+ });
+ }
+
+ /** Get CP position based on vld @private */
+ private generateVLDCP(): void {
+ let vldPos: number = 0;
+ this.vldNodes.forEach((list: NSINSTANCENODES) => {
+ if (!isNullOrUndefined(list.vnfdCP)) {
+ list.vnfdCP.forEach((cpRef: VNFDCONNECTIONPOINTREF) => {
+ this.cpCount = 0;
+ this.nodes.forEach((res: NSINSTANCENODES) => {
+ if (res.nodeTypeRef === 'cp' && res.id === cpRef['vnfd-connection-point-ref'] + ':' + cpRef['member-vnf-index-ref']) {
+ this.links.push({ source: this.nodes[vldPos], target: this.nodes[this.cpCount] });
+ }
+ this.cpCount++;
+ });
+ });
+ vldPos++;
+ }
+ });
+ }
+
+ /** Node is created and render at D3 region @private */
+ private createNode(nodes: NSINSTANCENODES[], links: {}[]): void {
+ const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
+ d3.selectAll('svg#graphContainer > *').remove();
+ d3.select(window).on('keydown', () => { this.keyDown(); });
+ d3.select(window).on('keyup', () => { this.keyUp(); });
+ this.svg = d3.select('#graphContainer')
+ .attr('oncontextmenu', 'return false;')
+ .attr('width', graphContainerAttr.width)
+ .attr('height', graphContainerAttr.height);
+ this.force = d3.forceSimulation()
+ .force('charge', d3.forceManyBody().strength(graphContainerAttr.strength))
+ .force('link', d3.forceLink().id((d: TickPath) => d.id).distance(graphContainerAttr.distance))
+ .force('center', d3.forceCenter(graphContainerAttr.width / graphContainerAttr.forcex,
+ graphContainerAttr.height / graphContainerAttr.forcey))
+ .force('x', d3.forceX(graphContainerAttr.width / graphContainerAttr.forcex))
+ .force('y', d3.forceY(graphContainerAttr.height / graphContainerAttr.forcey))
+ .on('tick', () => { this.tick(); });
+ // handles to link and node element groups
+ this.path = this.svg.append('svg:g').selectAll('path');
+ this.network = this.svg.append('svg:g').selectAll('network');
+ this.square = this.svg.append('svg:g').selectAll('rect');
+ this.circle = this.svg.append('svg:g').selectAll('circle');
+ this.restart(nodes, links);
+ }
+
+ /** Update force layout (called automatically each iteration) @private */
+ private tick(): void {
+ const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
+ // draw directed edges with proper padding from node centers
+ this.path.attr('class', 'link').attr('d', (d: Tick) => {
+ const deltaX: number = d.target.x - d.source.x;
+ const deltaY: number = d.target.y - d.source.y;
+ const dist: number = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
+ const normX: number = deltaX / dist;
+ const normY: number = deltaY / dist;
+ const sourcePadding: number = d.left ? graphContainerAttr.sourcePaddingYes : graphContainerAttr.sourcePaddingNo;
+ const targetPadding: number = d.right ? graphContainerAttr.targetPaddingYes : graphContainerAttr.targetPaddingNo;
+ const sourceX: number = d.source.x + (sourcePadding * normX);
+ const sourceY: number = d.source.y + (sourcePadding * normY);
+ const targetX: number = d.target.x - (targetPadding * normX);
+ const targetY: number = d.target.y - (targetPadding * normY);
+ return `M${sourceX},${sourceY}L${targetX},${targetY}`;
+ });
+ this.network.attr('transform', (t: TickPath) => `translate(${t.x},${t.y})`);
+ this.square.attr('transform', (t: TickPath) => `translate(${t.x},${t.y})`);
+ this.circle.attr('transform', (t: TickPath) => `translate(${t.x},${t.y})`);
+ }
+
+ /** Update graph (called when needed) @private */
+ private restart(nodes: NSINSTANCENODES[], links: {}[]): void {
+ const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
+ this.path = this.path.data(links);
+ const vnfdNodes: {}[] = []; const vldNodes: {}[] = []; const cpNodes: {}[] = []; // NB: Nodes are known by id, not by index!
+ nodes.forEach((nodeList: NSINSTANCENODES) => {
+ if (nodeList.nodeTypeRef === 'vnfd') { vnfdNodes.push(nodeList); }
+ else if (nodeList.nodeTypeRef === 'vld') { vldNodes.push(nodeList); }
+ else if (nodeList.nodeTypeRef === 'cp') { cpNodes.push(nodeList); }
+ });
+ this.square = this.square.data(vnfdNodes, (d: { id: number }) => d.id);
+ this.network = this.network.data(vldNodes, (d: { id: number }) => d.id);
+ this.circle = this.circle.data(cpNodes, (d: { id: number }) => d.id);
+ this.resetAndCreateNodes();
+ this.force.nodes(nodes).force('link').links(links); //Set the graph in motion
+ this.force.alphaTarget(graphContainerAttr.alphaTarget).restart();
+ }
+
+ /** Rest and create nodes @private */
+ private resetAndCreateNodes(): void {
+ this.path.exit().remove();
+ this.square.exit().remove();
+ this.network.exit().remove();
+ this.circle.exit().remove();
+ // tslint:disable-next-line:no-any
+ const gPath: any = this.path.enter().append('svg:path').attr('class', 'link');
+ this.getgSquare();
+ this.getgNetwork();
+ this.getgCircle();
+ this.square = this.gSquare.merge(this.square);
+ this.network = this.gNetwork.merge(this.network);
+ this.path = gPath.merge(this.path);
+ this.circle = this.gCircle.merge(this.circle);
+ }
+
+ /** Events handles when Shift Click to perform create cp @private */
+ // tslint:disable-next-line: no-any
+ private singleClick(nodeSelected: any, d: COMPOSERNODES): void {
+ this.selectNodeExclusive(nodeSelected, d);
+ }
+ /** Selected nodes @private */
+ // tslint:disable-next-line: no-any
+ private selectNodeExclusive(nodeSelected: any, d: COMPOSERNODES): void {
+ const alreadyIsActive: boolean = nodeSelected.select('#' + d.selectorId).classed(this.activeClass);
+ this.deselectAllNodes();
+ nodeSelected.select('#' + d.selectorId).classed(this.activeClass, !alreadyIsActive);
+ if (d.nodeTypeRef === 'vld' && !alreadyIsActive) {
+ this.virtualLink = {
+ id: d.id,
+ name: d.name,
+ type: d.type,
+ shortName: d.shortName,
+ vimNetworkName: d.vimNetworkName
+ };
+ this.showRightSideInfo(false, true, false);
+ } else if (d.nodeTypeRef === 'vnfd' && !alreadyIsActive) {
+ this.vnfr = {
+ vimID: d.vimID,
+ _id: d.vndfrID,
+ ip: d.ipAddress,
+ nsrID: d.nsID,
+ id: d.selectorId,
+ vnfdRef: d.vnfdRef,
+ vnfdId: d.vnfdID,
+ memberIndex: d.memberIndex
+ };
+ this.showRightSideInfo(false, false, true);
+ } else {
+ this.showRightSideInfo(true, false, false);
+ }
+ }
+ /** Setting all the square/vnf attributes of nodes @private */
+ private getgSquare(): void {
+ const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
+ this.gSquare = this.square.enter().append('svg:g');
+ this.gSquare.append('svg:circle').attr('r', graphContainerAttr.radius).style('fill', '#eeeeee');
+ this.gSquare.append('svg:image')
+ .style('opacity', 1)
+ .attr('x', graphContainerAttr.imageX)
+ .attr('y', graphContainerAttr.imageY)
+ .attr('id', (d: COMPOSERNODES) => { return d.selectorId; })
+ .attr('class', 'node').attr('width', graphContainerAttr.nodeWidth).attr('height', graphContainerAttr.nodeHeight)
+ .attr('xlink:href', 'assets/images/VNFD.svg')
+ .on('click', (d: COMPOSERNODES) => { this.singleClick(this.gSquare, d); this.onNodeClickToggleSidebar(); });
+ this.gSquare.append('svg:text')
+ .attr('class', 'node_text')
+ .attr('y', graphContainerAttr.textY)
+ .text((d: COMPOSERNODES) => d.id);
+ }
+
+ /** Settings all the network attributes of nodes @private */
+ private getgNetwork(): void {
+ const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
+ this.gNetwork = this.network.enter().append('svg:g');
+ this.gNetwork.append('svg:circle').attr('r', graphContainerAttr.radius).style('fill', '#eeeeee');
+ this.gNetwork.append('svg:image')
+ .style('opacity', 1)
+ .attr('x', graphContainerAttr.imageX)
+ .attr('y', graphContainerAttr.imageY)
+ .attr('id', (d: COMPOSERNODES) => { return d.selectorId; })
+ .attr('class', 'node').attr('width', graphContainerAttr.nodeWidth).attr('height', graphContainerAttr.nodeHeight)
+ .attr('xlink:href', 'assets/images/VL.svg')
+ .on('click', (d: COMPOSERNODES) => { this.singleClick(this.gNetwork, d); this.onNodeClickToggleSidebar(); });
+ this.gNetwork.append('svg:text')
+ .attr('class', 'node_text')
+ .attr('y', graphContainerAttr.textY)
+ .text((d: COMPOSERNODES) => d.name);
+ }
+
+ /** Settings all the connection point attributes of nodes @private */
+ private getgCircle(): void {
+ const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
+ this.gCircle = this.circle.enter().append('svg:g');
+ this.gCircle.append('svg:circle').attr('r', graphContainerAttr.radius).style('fill', '#eeeeee');
+ this.gCircle.append('svg:image')
+ .style('opacity', 1)
+ .attr('x', graphContainerAttr.imageX)
+ .attr('y', graphContainerAttr.imageY)
+ .attr('class', 'node').attr('width', graphContainerAttr.nodeWidth).attr('height', graphContainerAttr.nodeHeight)
+ .attr('xlink:href', 'assets/images/CP.svg');
+ this.gCircle.append('svg:text')
+ .attr('class', 'node_text')
+ .attr('y', graphContainerAttr.textY)
+ .text((d: COMPOSERNODES) => d.name);
+ }
+
+ /** Key press event @private */
+ private keyDown(): void {
+ const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
+ if (this.lastKeyDown !== -1) { return; }
+ this.lastKeyDown = d3.event.keyCode;
+ if (d3.event.keyCode === graphContainerAttr.shiftKeyCode) {
+ this.gSquare.call(d3.drag()
+ .on('start', this.dragstarted).on('drag', this.dragged).on('end', this.dragended)
+ );
+ this.gNetwork.call(d3.drag()
+ .on('start', this.dragstarted).on('drag', this.dragged).on('end', this.dragended)
+ );
+ this.gCircle.call(d3.drag()
+ .on('start', this.dragstarted).on('drag', this.dragged).on('end', this.dragended)
+ );
+ this.svg.classed('ctrl', true);
+ }
+ }
+ /** Key realse event @private */
+ private keyUp(): void {
+ const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
+ this.lastKeyDown = -1;
+ if (d3.event.keyCode === graphContainerAttr.shiftKeyCode) {
+ this.gSquare.on('.drag', null);
+ this.gNetwork.on('.drag', null);
+ this.gCircle.on('.drag', null);
+ this.svg.classed('ctrl', false);
+ }
+ }
+ /** Events handles when dragstarted @private */
+ private dragstarted(d: COMPOSERNODES): void {
+ d.fx = d.x;
+ d.fy = d.y;
+ }
+ /** Events handles when dragged @private */
+ private dragged(d: COMPOSERNODES): void {
+ d.fx = d.x = d3.event.x;
+ d.fy = d.y = d3.event.y;
+ }
+ /** Events handles when dragended @private */
+ private dragended(d: COMPOSERNODES): void {
+ if (this.forceSimulationActive) {
+ d.fx = null;
+ d.fy = null;
+ } else {
+ d.fx = d.x;
+ d.fy = d.y;
+ this.forceSimulationActive = false;
+ }
+ }
+ /** Events handles when node single click @private */
+ private onNodeClickToggleSidebar(): void {
+ this.sideBarOpened = true;
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="row d-flex flex-row justify-content-between">
+ <div class="d-flex align-items-center header-style">{{'PDUINSTANCES' | translate}}</div>
+ <span class="button">
+ <button class="btn btn-primary" type="button" placement="top" container="body"
+ ngbTooltip="{{'PAGE.PDUINSTANCE.NEWPDUINSTANCE' | translate}}" (click)="addPDUInstanceModal()">
+ <i class="fas fa-plus-circle" aria-hidden="true"></i>
+ {{'PAGE.PDUINSTANCE.NEWPDUINSTANCE' | translate}}
+ </button>
+ </span>
+</div>
+<div class="row mt-2 mb-0 form-group justify-content-end list-utilites-actions">
+ <page-per-row class="mr-2" (pagePerRow)="onChange($event)"></page-per-row>
+ <page-reload></page-reload>
+</div>
+<div class="smarttable-style bg-white mt-1">
+ <ng2-smart-table [ngClass]="checkDataClass" [settings]="settings" [source]="dataSource" (userRowSelect)="onUserRowSelect($event)">
+ </ng2-smart-table>
+</div>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @file PDU Instance Component
+ */
+import { Component, Injector, OnDestroy, OnInit } from '@angular/core';
+import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateService } from '@ngx-translate/core';
+import { AddPDUInstancesComponent } from 'AddPDUInstancesComponent';
+import { ERRORDATA, MODALCLOSERESPONSEDATA } from 'CommonModel';
+import { DataService } from 'DataService';
+import { environment } from 'environment';
+import { LocalDataSource } from 'ng2-smart-table';
+import { PDUInstanceDetails } from 'PDUInstanceModel';
+import { PDUInstancesActionComponent } from 'PDUInstancesActionComponent';
+import { RestService } from 'RestService';
+import { Subscription } from 'rxjs';
+import { SharedService } from 'SharedService';
+
+/**
+ * Creating component
+ * @Component takes PDUInstancesComponent.html as template url
+ */
+@Component({
+ templateUrl: './PDUInstancesComponent.html',
+ styleUrls: ['./PDUInstancesComponent.scss']
+})
+/** Exporting a class @exports PDUInstancesComponent */
+export class PDUInstancesComponent implements OnInit, OnDestroy {
+ /** Injector to invoke other services @public */
+ public injector: Injector;
+
+ /** NS Instance array @public */
+ public pduInstanceData: object[] = [];
+
+ /** Datasource instance @public */
+ public dataSource: LocalDataSource = new LocalDataSource();
+
+ /** SelectedRows array @public */
+ public selectedRows: object[] = [];
+
+ /** Selected list array @public */
+ public selectList: object[] = [];
+
+ /** Instance component are stored in settings @public */
+ public settings: {} = {};
+
+ /** Contains objects for menu settings @public */
+ public columnList: {} = {};
+
+ /** Check the loading results @public */
+ public isLoadingResults: boolean = true;
+
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+
+ /** Class for empty and present data @public */
+ public checkDataClass: string;
+
+ /** Instance of the modal service @private */
+ private modalService: NgbModal;
+
+ /** dataService to pass the data from one component to another @private */
+ private dataService: DataService;
+
+ /** Utilizes rest service for any CRUD operations @private */
+ private restService: RestService;
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ /** Contains tranlsate instance @private */
+ private translateService: TranslateService;
+
+ /** Instance of subscriptions @private */
+ private generateDataSub: Subscription;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.restService = this.injector.get(RestService);
+ this.dataService = this.injector.get(DataService);
+ this.sharedService = this.injector.get(SharedService);
+ this.translateService = this.injector.get(TranslateService);
+ this.modalService = this.injector.get(NgbModal);
+ }
+
+ /**
+ * Lifecyle Hooks the trigger before component is instantiate
+ */
+ public ngOnInit(): void {
+ this.generateTableColumn();
+ this.generateTableSettings();
+ this.generateData();
+ this.generateDataSub = this.sharedService.dataEvent.subscribe(() => { this.generateData(); });
+ }
+
+ /** Generate smart table row title and filters @public */
+ public generateTableSettings(): void {
+ this.settings = {
+ columns: this.columnList,
+ actions: { add: false, edit: false, delete: false, position: 'right' },
+ attr: this.sharedService.tableClassConfig(),
+ pager: this.sharedService.paginationPagerConfig(),
+ noDataMessage: this.translateService.instant('NODATAMSG')
+ };
+ }
+
+ /** Generate smart table row title and filters @public */
+ public generateTableColumn(): void {
+ this.columnList = {
+ identifier: { title: this.translateService.instant('IDENTIFIER'), width: '25%' },
+ name: { title: this.translateService.instant('NAME'), width: '20%', sortDirection: 'asc' },
+ type: { title: this.translateService.instant('TYPE'), width: '15%' },
+ usageState: { title: this.translateService.instant('USAGESTATE'), width: '15%' },
+ CreatedAt: { title: this.translateService.instant('CREATEDAT'), width: '15%' },
+ Actions: {
+ name: 'Action', width: '10%', filter: false, sort: false, type: 'custom',
+ title: this.translateService.instant('ACTIONS'),
+ valuePrepareFunction: (cell: PDUInstanceDetails, row: PDUInstanceDetails): PDUInstanceDetails => row,
+ renderComponent: PDUInstancesActionComponent
+ }
+ };
+ }
+
+ /** generateData initiate the ns-instance list @public */
+ public generateData(): void {
+ this.pduInstanceData = [];
+ this.isLoadingResults = true;
+ this.restService.getResource(environment.PDUINSTANCE_URL).subscribe((pduInstancesData: PDUInstanceDetails[]) => {
+ pduInstancesData.forEach((pduInstanceData: PDUInstanceDetails) => {
+ const pduDataObj: {} = {
+ name: pduInstanceData.name,
+ identifier: pduInstanceData._id,
+ type: pduInstanceData.type,
+ usageState: pduInstanceData._admin.usageState,
+ CreatedAt: this.sharedService.convertEpochTime(Number(pduInstanceData._admin.created))
+ };
+ this.pduInstanceData.push(pduDataObj);
+ });
+ if (this.pduInstanceData.length > 0) {
+ this.checkDataClass = 'dataTables_present';
+ } else {
+ this.checkDataClass = 'dataTables_empty';
+ }
+ this.dataSource.load(this.pduInstanceData).then((data: {}) => {
+ this.isLoadingResults = false;
+ }).catch();
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'get');
+ this.isLoadingResults = false;
+ });
+ }
+
+ /** smart table listing manipulation @public */
+ public onChange(perPageValue: number): void {
+ this.dataSource.setPaging(1, perPageValue, true);
+ }
+
+ /** smart table listing manipulation @public */
+ public onUserRowSelect(event: MessageEvent): void {
+ Object.assign(event.data, { page: 'pdu-instances' });
+ this.dataService.changeMessage(event.data);
+ }
+
+ /** Add PDU Instance modal using modalservice @public */
+ public addPDUInstanceModal(): void {
+ const modalRef: NgbModalRef = this.modalService.open(AddPDUInstancesComponent, { backdrop: 'static' });
+ modalRef.componentInstance.title = this.translateService.instant('PAGE.PDUINSTANCE.NEWPDUINSTANCE');
+ modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
+ if (result) {
+ this.generateData();
+ }
+ }).catch();
+ }
+
+ /**
+ * Lifecyle hook which get trigger on component destruction
+ */
+ public ngOnDestroy(): void {
+ this.generateDataSub.unsubscribe();
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="modal-header">
+ <h4 class="modal-title" id="modal-basic-title">{{title}}</h4>
+ <button class="button-xs" type="button" class="close" aria-label="Close" (click)="activeModal.close()">
+ <i class="fas fa-times-circle text-danger"></i>
+ </button>
+</div>
+<form [formGroup]="pduInstancesForm" (ngSubmit)="createPDUInstances()" autocomplete="off">
+ <div class="modal-body">
+ <div class="form-group row">
+ <label class="col-sm-12 col-form-label mandatory-label" [ngClass]="{'text-danger': pduInstancesForm.invalid === true && submitted === true}">{{'MANDATORYCHECK' | translate}}</label>
+ <label class="col-sm-3 col-form-label" for="name">{{'NAME' | translate}}*</label>
+ <div class="col-sm-3">
+ <input placeholder="{{'NAME' | translate}}" type="text" class="form-control" formControlName="name" id="name" [ngClass]="{ 'is-invalid': submitted && f.name.errors }"
+ required>
+ </div>
+ <label class="col-sm-3 col-form-label" for="type">{{'PAGE.PDUINSTANCE.PDUTYPE' | translate}}*</label>
+ <div class="col-sm-3">
+ <input placeholder="{{'PAGE.PDUINSTANCE.PDUTYPE' | translate}}" type="text" class="form-control" formControlName="type" id="type" [ngClass]="{ 'is-invalid': submitted && f.type.errors }">
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-3 col-form-label" for="vim_accounts">{{'VIMACCOUNTS' | translate}}*</label>
+ <div class="col-sm-9">
+ <ng-select placeholder="{{'VIMACCOUNTS' | translate}}" [items]="vimAccountSelect" multiple="true" bindLabel="name" bindValue="_id" formControlName="vim_accounts" id="vim_accounts"
+ [ngClass]="{ 'is-invalid': submitted && f.vim_accounts.errors }" [(ngModel)]="selectedVIM">
+ </ng-select>
+ </div>
+ </div>
+ <div class="form-group row p-2 bg-light text-dark">
+ <div class="col-sm-7 align-self-center"><span>{{'PAGE.PDUINSTANCE.PARAMETERS' | translate}}</span></div>
+ <div class="col-sm-5">
+ <button type="button" class="btn btn-primary" (click)="createInterfaces()">
+ <i class="fas fa-plus-square"></i> {{'PAGE.PDUINSTANCE.ADDINSTANCEPARAMS' | translate}}</button>
+ </div>
+ </div>
+ <div formArrayName="interfaces" *ngFor="let params of getControls(); let i = index;">
+ <div class="form-group" [formGroupName]="i">
+ <div class="row">
+ <div class="col-sm-11">
+ <div class="row">
+ <label class="col-sm-2 col-form-label" for="name_{{i}}">{{'NAME' | translate}}*</label>
+ <div class="col-sm-4">
+ <input placeholder="{{'NAME' | translate}}" type="text" class="form-control" formControlName="name" id="name_{{i}}" [ngClass]="{ 'is-invalid': submitted && params.controls.name.errors }">
+ </div>
+ <label class="col-sm-2 col-form-label padLeft0 padRight0" for="ipAddress{{i}}">{{'IPADDRESS' | translate}}*</label>
+ <div class="col-sm-4">
+ <input placeholder="{{'IPADDRESS' | translate}}" type="text" class="form-control" formControlName="ip-address" id="ipAddress{{i}}" [ngClass]="{ 'is-invalid': submitted && params.controls['ip-address'].errors }">
+ <div *ngIf="pduInstancesForm.invalid" class="invalid-feedback">
+ <div *ngIf="params.controls['ip-address'].errors && params.controls['ip-address'].value">{{'DOMVALIDATIONS.INVALIDIPADDRESS' | translate}}</div>
+ </div>
+ </div>
+ </div>
+ <div class="row mr-top-5">
+ <label class="col-sm-2 col-form-label" for="mgmt{{i}}">{{'MGMT' | translate}}*</label>
+ <div class="col-sm-4">
+ <ng-select placeholder="{{'SELECT' | translate}} {{'MGMT' | translate}}" [items]="mgmtState" bindLabel="name" bindValue="value" formControlName="mgmt" id="mgmt{{i}}" [(ngModel)]="selectedMgmt" [ngClass]="{ 'is-invalid': submitted && params.controls.mgmt.errors }"></ng-select>
+ </div>
+ <label class="col-sm-2 col-form-label padLeft0 padRight0" for="vimNetName{{i}}">{{'NETNAME' | translate}}*</label>
+ <div class="col-sm-4">
+ <input placeholder="{{'NETNAME' | translate}}" type="text" class="form-control" formControlName="vim-network-name" id="vimNetName{{i}}" [ngClass]="{ 'is-invalid': submitted && params.controls['vim-network-name'].errors }">
+ </div>
+ </div>
+ </div>
+ <div class="col-sm-1 remove-params" [hidden]="i==0">
+ <button type="button" class="btn btn-sm btn-danger remove-mapping" (click)="removeInterfaces(i)">
+ <i class="fas fa-times-circle"></i>
+ </button>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-danger" (click)="activeModal.close()">{{'CANCEL' | translate}}</button>
+ <button type="submit" class="btn btn-primary">{{'CREATE' | translate}}</button>
+ </div>
+</form>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+@import '../../../../assets/scss/mixins/mixin';
+@import '../../../../assets/scss/variable';
+
+.head {
+ @include padding-value(10, 10, 10, 10);
+ line-height: 2em;
+ .btn-params {
+ @include border(all, 1, solid, $white);
+ }
+}
+
+.remove-params {
+ display: flex;
+ align-items: center;
+ font-size: 20px;
+ cursor: pointer;
+}
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @file ADD PDU Instances Component
+ */
+import { Component, Injector, Input, OnInit, Output } from '@angular/core';
+import { AbstractControl, FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms';
+import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateService } from '@ngx-translate/core';
+import { NotifierService } from 'angular-notifier';
+import { APIURLHEADER, ERRORDATA, MODALCLOSERESPONSEDATA } from 'CommonModel';
+import { DataService } from 'DataService';
+import { environment } from 'environment';
+import { PDUInstanceDetails } from 'PDUInstanceModel';
+import { RestService } from 'RestService';
+import { SharedService } from 'SharedService';
+import { VimAccountDetails } from 'VimAccountModel';
+
+/**
+ * Creating component
+ * @Component takes AddPDUInstancesComponent.html as template url
+ */
+@Component({
+ templateUrl: './AddPDUInstancesComponent.html',
+ styleUrls: ['./AddPDUInstancesComponent.scss']
+})
+/** Exporting a class @exports AddPDUInstancesComponent */
+export class AddPDUInstancesComponent implements OnInit {
+ /** Form valid on submit trigger @public */
+ public submitted: boolean = false;
+
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** Instance for active modal service @public */
+ public activeModal: NgbActiveModal;
+
+ /** FormGroup instance added to the form @ html @public */
+ public pduInstancesForm: FormGroup;
+
+ /** Primitive params array @public */
+ public pduInterfaces: FormArray;
+
+ /** Variable set for twoway binding @public */
+ public pduInstanceId: string;
+
+ /** Set mgmt field to empty on load @public */
+ public selectedMgmt: string;
+
+ /** Set vim field to empty on load @public */
+ public selectedVIM: string;
+
+ /** Contains boolean value as select options for mgmt @public */
+ public mgmtState: {}[] = [{ name: 'True', value: true }, { name: 'False', value: false }];
+
+ /** Input contains Modal dialog component Instance @private */
+ @Input() public title: string;
+
+ /** Contains all the vim accounts list @public */
+ public vimAccountSelect: VimAccountDetails;
+
+ /** Check the loading results @public */
+ public isLoadingResults: boolean = false;
+
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+
+ /** FormBuilder instance added to the formBuilder @private */
+ private formBuilder: FormBuilder;
+
+ /** Utilizes rest service for any CRUD operations @private */
+ private restService: RestService;
+
+ /** packages data service collections @private */
+ private dataService: DataService;
+
+ /** Contains tranlsate instance @private */
+ private translateService: TranslateService;
+
+ /** Notifier service to popup notification @private */
+ private notifierService: NotifierService;
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.restService = this.injector.get(RestService);
+ this.dataService = this.injector.get(DataService);
+ this.translateService = this.injector.get(TranslateService);
+ this.notifierService = this.injector.get(NotifierService);
+ this.sharedService = this.injector.get(SharedService);
+ this.activeModal = this.injector.get(NgbActiveModal);
+ this.formBuilder = this.injector.get(FormBuilder);
+ }
+
+ /**
+ * Lifecyle Hooks the trigger before component is instantiate
+ */
+ public ngOnInit(): void {
+ /** Setting up initial value for NSD */
+ this.dataService.currentMessage.subscribe((event: PDUInstanceDetails) => {
+ if (event.identifier !== undefined || event.identifier !== '' || event.identifier !== null) {
+ this.pduInstanceId = event.identifier;
+ }
+ });
+ this.generateVIMAccounts();
+ this.initializeForm();
+ }
+
+ /** convenience getter for easy access to form fields */
+ get f(): FormGroup['controls'] { return this.pduInstancesForm.controls; }
+
+ /** initialize Forms @public */
+ public initializeForm(): void {
+ this.pduInstancesForm = this.formBuilder.group({
+ name: ['', [Validators.required]],
+ type: ['', [Validators.required]],
+ vim_accounts: ['', [Validators.required]],
+ interfaces: this.formBuilder.array([this.interfacesBuilder()])
+ });
+ }
+
+ /** Generate interfaces fields @public */
+ public interfacesBuilder(): FormGroup {
+ return this.formBuilder.group({
+ name: ['', [Validators.required]],
+ 'ip-address': ['', [Validators.required, Validators.pattern(this.sharedService.REGX_IP_PATTERN)]],
+ mgmt: ['', [Validators.required]],
+ 'vim-network-name': ['', [Validators.required]]
+ });
+ }
+
+ /** Handle FormArray Controls @public */
+ public getControls(): AbstractControl[] {
+ // tslint:disable-next-line:no-backbone-get-set-outside-model
+ return (this.pduInstancesForm.get('interfaces') as FormArray).controls;
+ }
+
+ /** Push all primitive params on user's action @public */
+ public createInterfaces(): void {
+ // tslint:disable-next-line:no-backbone-get-set-outside-model
+ this.pduInterfaces = this.pduInstancesForm.get('interfaces') as FormArray;
+ this.pduInterfaces.push(this.interfacesBuilder());
+ }
+
+ /** Remove interfaces on user's action @public */
+ public removeInterfaces(index: number): void {
+ this.pduInterfaces.removeAt(index);
+ }
+
+ /** Execute New PDU Instances @public */
+ public createPDUInstances(): void {
+ this.submitted = true;
+ this.sharedService.cleanForm(this.pduInstancesForm);
+ if (this.pduInstancesForm.invalid) { return; } // Proceed, onces form is valid
+ this.isLoadingResults = true;
+ const modalData: MODALCLOSERESPONSEDATA = {
+ message: 'Done'
+ };
+ const apiURLHeader: APIURLHEADER = {
+ url: environment.PDUINSTANCE_URL
+ };
+ this.restService.postResource(apiURLHeader, this.pduInstancesForm.value).subscribe((result: {}) => {
+ this.activeModal.close(modalData);
+ this.notifierService.notify('success', this.translateService.instant('PAGE.PDUINSTANCE.CREATEDSUCCESSFULLY'));
+ this.isLoadingResults = false;
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'post');
+ this.isLoadingResults = false;
+ });
+ }
+
+ /** Generate vim accounts list @public */
+ public generateVIMAccounts(): void {
+ this.restService.getResource(environment.VIMACCOUNTS_URL).subscribe((vimData: VimAccountDetails) => {
+ this.vimAccountSelect = vimData;
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'get');
+ });
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="row d-flex flex-row justify-content-between">
+ <div class="d-flex align-items-center header-style">{{'VNFINSTANCES' | translate}}</div>
+</div>
+<div class="row mt-2 mb-0 form-group justify-content-end list-utilites-actions">
+ <page-per-row class="mr-2" (pagePerRow)="onChange($event)"></page-per-row>
+ <page-reload></page-reload>
+</div>
+<div class="smarttable-style bg-white mt-1">
+ <ng2-smart-table [ngClass]="checkDataClass" [settings]="settings" [source]="dataSource" (userRowSelect)="onUserRowSelect($event)">
+ </ng2-smart-table>
+</div>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file NVF Instance Component
+ */
+import { Component, Injector, OnInit } from '@angular/core';
+import { TranslateService } from '@ngx-translate/core';
+import { ERRORDATA } from 'CommonModel';
+import { DataService } from 'DataService';
+import { environment } from 'environment';
+import { LocalDataSource } from 'ng2-smart-table';
+import { RestService } from 'RestService';
+import { Subscription } from 'rxjs';
+import { SharedService } from 'SharedService';
+import { VNFInstanceData, VNFInstanceDetails } from 'VNFInstanceModel';
+import { VNFInstancesActionComponent } from 'VNFInstancesActionComponent';
+import { VNFLinkComponent } from 'VNFLinkComponent';
+
+/**
+ * Creating component
+ * @Component takes VNFInstancesComponent.html as template url
+ */
+@Component({
+ templateUrl: './VNFInstancesComponent.html',
+ styleUrls: ['./VNFInstancesComponent.scss']
+})
+/** Exporting a class @exports VNFInstancesComponent */
+export class VNFInstancesComponent implements OnInit {
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** smart table data service collections @public */
+ public dataSource: LocalDataSource = new LocalDataSource();
+
+ /** Instance component are stored in settings @public */
+ public settings: {} = {};
+
+ /** Contains objects for menu settings @public */
+ public columnList: {} = {};
+
+ /** vnf instance array @public */
+ public vnfInstanceData: {}[] = [];
+
+ /** selected rows array @public */
+ public selectedRows: string[] = [];
+
+ /** selected list array @public */
+ public selectList: string[] = [];
+
+ /** Check the loading results @public */
+ public isLoadingResults: boolean = true;
+
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+
+ /** Class for empty and present data @public */
+ public checkDataClass: string;
+
+ /** Utilizes rest service for any CRUD operations @private */
+ private restService: RestService;
+
+ /** packages data service collections @private */
+ private dataService: DataService;
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ /** Contains tranlsate instance @private */
+ private translateService: TranslateService;
+
+ /** Instance of subscriptions @private */
+ private generateDataSub: Subscription;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.restService = this.injector.get(RestService);
+ this.dataService = this.injector.get(DataService);
+ this.sharedService = this.injector.get(SharedService);
+ this.translateService = this.injector.get(TranslateService);
+ }
+
+ /**
+ * Lifecyle Hooks the trigger before component is instantiate
+ */
+ public ngOnInit(): void {
+ this.generateTableColumn();
+ this.generateTableSettings();
+ this.generateData();
+ this.generateDataSub = this.sharedService.dataEvent.subscribe(() => { this.generateData(); });
+ }
+
+ /** Generate smart table row title and filters @public */
+ public generateTableSettings(): void {
+ this.settings = {
+ actions: { add: false, edit: false, delete: false, position: 'right' },
+ columns: this.columnList,
+ attr: this.sharedService.tableClassConfig(),
+ pager: this.sharedService.paginationPagerConfig(),
+ noDataMessage: this.translateService.instant('NODATAMSG')
+ };
+ }
+
+ /** Generate smart table row title and filters @public */
+ public generateTableColumn(): void {
+ this.columnList = {
+ identifier: { title: this.translateService.instant('IDENTIFIER'), width: '25%', sortDirection: 'asc' },
+ VNFD: {
+ title: this.translateService.instant('VNFD'), width: '20%', type: 'custom',
+ valuePrepareFunction: (cell: VNFInstanceData, row: VNFInstanceData): VNFInstanceData => row,
+ renderComponent: VNFLinkComponent
+ },
+ MemberIndex: { title: this.translateService.instant('MEMBERINDEX'), width: '15%' },
+ NS: { title: this.translateService.instant('NS'), width: '20%' },
+ CreatedAt: { title: this.translateService.instant('CREATEDAT'), width: '15%' },
+ Actions: {
+ name: 'Action', width: '5%', filter: false, sort: false, type: 'custom',
+ title: this.translateService.instant('ACTIONS'),
+ valuePrepareFunction: (cell: VNFInstanceData, row: VNFInstanceData): VNFInstanceData => row,
+ renderComponent: VNFInstancesActionComponent
+ }
+ };
+ }
+
+ /** generateData initiate the vnf-instance list */
+ public generateData(): void {
+ this.isLoadingResults = true;
+ this.restService.getResource(environment.VNFINSTANCES_URL).subscribe((vnfInstancesData: VNFInstanceDetails[]) => {
+ this.vnfInstanceData = [];
+ vnfInstancesData.forEach((vnfInstanceData: VNFInstanceDetails) => {
+ const vnfDataObj: {} =
+ {
+ VNFD: vnfInstanceData['vnfd-ref'],
+ identifier: vnfInstanceData._id,
+ MemberIndex: vnfInstanceData['member-vnf-index-ref'],
+ NS: vnfInstanceData['nsr-id-ref'],
+ VNFID: vnfInstanceData['vnfd-id'],
+ CreatedAt: this.sharedService.convertEpochTime(Number(vnfInstanceData['created-time']))
+ };
+ this.vnfInstanceData.push(vnfDataObj);
+ });
+ if (this.vnfInstanceData.length > 0) {
+ this.checkDataClass = 'dataTables_present';
+ } else {
+ this.checkDataClass = 'dataTables_empty';
+ }
+ this.dataSource.load(this.vnfInstanceData).then((data: {}) => {
+ this.isLoadingResults = false;
+ }).catch();
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'get');
+ this.isLoadingResults = false;
+ });
+ }
+
+ /** smart table listing manipulation @public */
+ public onChange(perPageValue: number): void {
+ this.dataSource.setPaging(1, perPageValue, true);
+ }
+
+ /** smart table listing manipulation @public */
+ public onUserRowSelect(event: MessageEvent): void {
+ Object.assign(event.data, { page: 'vnf-instance' });
+ this.dataService.changeMessage(event.data);
+ }
+
+ /**
+ * Lifecyle hook which get trigger on component destruction
+ */
+ public ngOnDestroy(): void {
+ this.generateDataSub.unsubscribe();
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<a class="link" routerLink="/packages/vnf/edit/{{value.VNFID}}">{{value.VNFD}}</a>
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file VNFD Link Component.
+ */
+import { Component, Injector, OnInit } from '@angular/core';
+import { VNFInstanceData } from 'VNFInstanceModel';
+/**
+ * Creating component
+ * @Component takes VNFLinkComponent.html as template url
+ */
+@Component({
+ selector: 'app-vnf-link',
+ templateUrl: './VNFLinkComponent.html',
+ styleUrls: ['./VNFLinkComponent.scss']
+})
+/** Exporting a class @exports VnfLinkComponent */
+export class VNFLinkComponent implements OnInit {
+ /** Invoke service injectors @public */
+ public injector: Injector;
+ /** To get the value from the VNFInstance via valuePrepareFunction default Property of ng-smarttable @public */
+ public value: VNFInstanceData;
+ constructor(injector: Injector) {
+ this.injector = injector;
+ }
+ /** Lifecyle Hooks the trigger before component is instantiate @public */
+ public ngOnInit(): void {
+ //empty
+ }
+
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<router-outlet></router-outlet>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file k8s.ts.
+ */
+import { Component, Injector } from '@angular/core';
+import { Router, RouterEvent } from '@angular/router';
+/**
+ * Creating Component
+ * @Component takes K8sComponent.html as template url
+ */
+@Component({
+ selector: 'app-k8s',
+ templateUrl: './K8sComponent.html',
+ styleUrls: ['./K8sComponent.scss']
+})
+/** Exporting a class @exports K8sComponent */
+export class K8sComponent {
+ /** Invoke service injectors @public */
+ public injector: Injector;
+
+ /** Holds teh instance of AuthService class of type AuthService @private */
+ private router: Router;
+
+ /** creates k8s component */
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.router = this.injector.get(Router);
+ this.router.events.subscribe((event: RouterEvent) => {
+ this.redirectToList(event.url);
+ });
+ }
+
+ /** Return to list NS Package List */
+ public redirectToList(getURL: string): void {
+ if (getURL === '/k8s') {
+ this.router.navigate(['/k8s/cluster']).catch();
+ }
+ }
+
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file K8s Module.
+ */
+import { CommonModule } from '@angular/common';
+import { HttpClientModule } from '@angular/common/http';
+import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
+import { FormsModule } from '@angular/forms';
+import { ReactiveFormsModule } from '@angular/forms';
+import { RouterModule, Routes } from '@angular/router';
+import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
+import { NgSelectModule } from '@ng-select/ng-select';
+import { TranslateModule } from '@ngx-translate/core';
+import { DataService } from 'DataService';
+import { K8sActionComponent } from 'K8sActionComponent';
+import { K8sAddClusterComponent } from 'K8sAddClusterComponent';
+import { K8sAddRepoComponent } from 'K8sAddRepoComponent';
+import { K8sClusterComponent } from 'K8sClusterComponent';
+import { K8sComponent } from 'K8sComponent';
+import { K8sRepositoryComponent } from 'K8sRepositoryComponent';
+import { LoaderModule } from 'LoaderModule';
+import { Ng2SmartTableModule } from 'ng2-smart-table';
+import { PagePerRowModule } from 'PagePerRowModule';
+import { PageReloadModule } from 'PageReloadModule';
+
+/** To halndle project information */
+const projectInfo: {} = { title: '{project}', url: '/' };
+
+/**
+ * configures routers
+ */
+const routes: Routes = [
+ {
+ path: '',
+ component: K8sComponent,
+ children: [
+ {
+ path: 'cluster',
+ data: {
+ breadcrumb: [{ title: 'PAGE.DASHBOARD.DASHBOARD', url: '/' }, { title: 'PAGE.DASHBOARD.PROJECTS', url: '/projects' },
+ projectInfo, { title: 'PAGE.K8S.MENUK8SCLUSTER', url: null }]
+ },
+ component: K8sClusterComponent
+ },
+ {
+ path: 'repo',
+ data: {
+ breadcrumb: [{ title: 'PAGE.DASHBOARD.DASHBOARD', url: '/' }, { title: 'PAGE.DASHBOARD.PROJECTS', url: '/projects' },
+ projectInfo, { title: 'PAGE.K8S.MENUK8SREPO', url: null }]
+ },
+ component: K8sRepositoryComponent
+ }
+ ]
+ }
+];
+/**
+ * Creating @NgModule component for Modules
+ */
+@NgModule({
+ imports: [
+ ReactiveFormsModule.withConfig({ warnOnNgModelWithFormControl: 'never' }),
+ FormsModule,
+ CommonModule,
+ HttpClientModule,
+ NgSelectModule,
+ Ng2SmartTableModule,
+ TranslateModule,
+ RouterModule.forChild(routes),
+ NgbModule,
+ PagePerRowModule,
+ LoaderModule,
+ PageReloadModule
+ ],
+ declarations: [
+ K8sComponent,
+ K8sClusterComponent,
+ K8sRepositoryComponent,
+ K8sActionComponent,
+ K8sAddClusterComponent,
+ K8sAddRepoComponent
+ ],
+ providers: [DataService],
+ schemas: [CUSTOM_ELEMENTS_SCHEMA],
+ entryComponents: [K8sActionComponent, K8sAddClusterComponent, K8sAddRepoComponent]
+})
+/** Exporting a class @exports K8sModule */
+export class K8sModule {
+ /** Variables declared to avoid state-less class */
+ private k8sModule: string;
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="btn-group list action" role="group">
+ <button type="button" class="btn btn-primary" (click)="infoK8s(getK8sType)" placement="top" container="body"
+ ngbTooltip="{{'INFO' | translate}}">
+ <i class="fas fa-info icons list" title="info"></i>
+ </button>
+ <button type="button" class="btn btn-primary" (click)="deleteK8s(getK8sType)" placement="top"
+ container="body" ngbTooltip="{{'DELETE' | translate}}">
+ <i class="far fa-trash-alt icons" title="delete"></i>
+ </button>
+</div>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @file K8 Action Component
+ */
+import { Component, Injector } from '@angular/core';
+import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateService } from '@ngx-translate/core';
+import { MODALCLOSERESPONSEDATA } from 'CommonModel';
+import { DeleteComponent } from 'DeleteComponent';
+import { K8SCLUSTERDATADISPLAY, K8SREPODATADISPLAY } from 'K8sModel';
+import { SharedService } from 'SharedService';
+import { ShowInfoComponent } from 'ShowInfoComponent';
+/**
+ * Creating component
+ * @Component takes K8sActionComponent.html as template url
+ */
+@Component({
+ selector: 'app-k8s-action',
+ templateUrl: './K8sActionComponent.html',
+ styleUrls: ['./K8sActionComponent.scss']
+})
+/** Exporting a class @exports K8sActionComponent */
+export class K8sActionComponent{
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** To get the value from the Users action via valuePrepareFunction default Property of ng-smarttable @public */
+ public value: K8SCLUSTERDATADISPLAY | K8SREPODATADISPLAY;
+
+ /** handle translate @public */
+ public translateService: TranslateService;
+
+ /** Contains K8s Type @private */
+ public getK8sType: string;
+
+ /** Instance of the modal service @private */
+ private modalService: NgbModal;
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ /** Contains instance ID @private */
+ private instanceID: string;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.modalService = this.injector.get(NgbModal);
+ this.sharedService = this.injector.get(SharedService);
+ this.translateService = this.injector.get(TranslateService);
+ }
+
+ /**
+ * Lifecyle Hooks the trigger before component is instantiate
+ */
+ public ngOnInit(): void {
+ this.instanceID = this.value.identifier;
+ this.getK8sType = this.value.pageType;
+ }
+
+ /** Delete User Account @public */
+ public deleteK8s(pageType: string): void {
+ const modalRef: NgbModalRef = this.modalService.open(DeleteComponent, { backdrop: 'static' });
+ modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
+ if (result) {
+ this.sharedService.callData();
+ }
+ }).catch();
+ }
+
+ /** Shows information using modalservice @public */
+ public infoK8s(pageType: string): void {
+ let pageName: string = '';
+ let title: string = '';
+ if (pageType === 'repo') {
+ pageName = 'k8s-repo';
+ title = 'PAGE.K8S.K8SREPODETAILS';
+ } else {
+ pageName = 'k8s-cluster';
+ title = 'PAGE.K8S.K8SCLUSTERDETAILS';
+ }
+ this.modalService.open(ShowInfoComponent, { backdrop: 'static' }).componentInstance.params = {
+ id: this.instanceID,
+ page: pageName,
+ titleName: title
+ };
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<form [formGroup]="k8sclusterForm" (ngSubmit)="k8sAddClusterSubmit();">
+ <div class="modal-header">
+ <h4 class="modal-title" id="modal-basic-title">{{'PAGE.K8S.NEWK8SCLUSTER' | translate}}</h4>
+ <button class="button-xs" type="button" class="close" aria-label="Close" (click)="activeModal.close()">
+ <i class="fas fa-times-circle text-danger"></i>
+ </button>
+ </div>
+ <div class="modal-body modal-body-custom-height">
+ <div class="form-group row">
+ <label class="col-sm-12 col-form-label mandatory-label"
+ [ngClass]="{'text-danger': k8sclusterForm.invalid === true && submitted === true}">{{'MANDATORYCHECK' | translate}}</label>
+ <label class="col-sm-4 col-form-label" for="name">{{'PAGE.K8S.NAME' | translate}}*</label>
+ <div class="col-sm-8">
+ <input autocomplete="off" class="form-control" placeholder="{{'PAGE.K8S.NAME' | translate}}" type="text"
+ formControlName="name" id="name" [ngClass]="{ 'is-invalid': submitted && f.name.errors }" required>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label" for="k8s_version">{{'PAGE.K8S.K8SVERSION' | translate}}*</label>
+ <div class="col-sm-8">
+ <input autocomplete="off" class="form-control" placeholder="{{'PAGE.K8S.K8SVERSION' | translate}}" type="text"
+ formControlName="k8s_version" id="k8s_version" [ngClass]="{ 'is-invalid': submitted && f.k8s_version.errors }"
+ required>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label" for="vim_account">{{'PAGE.K8S.VIMACCOUNT' | translate}}*</label>
+ <div class="col-sm-8">
+ <ng-select placeholder="{{'SELECT' | translate}} {{'PAGE.K8S.VIMACCOUNT' | translate}}"
+ [items]="vimAccountSelect" bindLabel="name" bindValue="_id" formControlName="vim_account" id="vimAccountId"
+ [ngClass]="{ 'is-invalid': submitted && f.vim_account.errors }" required>
+ </ng-select>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label" for="description">{{'PAGE.K8S.DESCRIPTION' | translate}}*</label>
+ <div class="col-sm-8">
+ <textarea class="form-control" placeholder="{{'PAGE.K8S.DESCRIPTION' | translate}}" type="text"
+ formControlName="description" id="description" [ngClass]="{ 'is-invalid': submitted && f.description.errors }"
+ required></textarea>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label" for="nets">{{'PAGE.K8S.NETS' | translate}}*</label>
+ <div class="col-sm-8">
+ <textarea rows="5" cols="50" class="form-control" placeholder="{{'PAGE.K8S.NETSPLACEHOLDER' | translate}}"
+ formControlName="nets" id="nets" [ngClass]="{ 'is-invalid': submitted && f.nets.errors }" required></textarea>
+ <div class="fileupload-text mt-1 mb-1">{{'FILEUPLOADLABEL' | translate}}</div>
+ <div class="custom-file">
+ <input type="file" #fileInputNets class="custom-file-input" (change)="netsFile($event.target.files)"
+ id="customFileNets">
+ <label class="custom-file-label" #fileInputNetsLabel for="customFileNets">{{'CHOOSEFILE' | translate}}</label>
+ </div>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label" for="credentials">{{'PAGE.K8S.CREDENTIALS' | translate}}*</label>
+ <div class="col-sm-8">
+ <textarea rows="5" cols="50" class="form-control" placeholder="{{'YAMLCONFIG' | translate}}" formControlName="credentials"
+ id="credentials" [ngClass]="{ 'is-invalid': submitted && f.credentials.errors }" required></textarea>
+ <div class="fileupload-text mt-1 mb-1">{{'FILEUPLOADLABEL' | translate}}</div>
+ <div class="custom-file">
+ <input type="file" #fileInputCredentials class="custom-file-input" (change)="credentialsFile($event.target.files)"
+ id="customFileCredentials">
+ <label class="custom-file-label" #fileInputCredentialsLabel for="customFileCredentials">{{'CHOOSEFILE' | translate}}</label>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-danger" (click)="activeModal.close()">{{'CANCEL' | translate}}</button>
+ <button type="submit" class="btn btn-primary">{{'CREATE' | translate}}</button>
+ </div>
+</form>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file K8sAddClusterComponent.ts.
+ */
+import { HttpHeaders } from '@angular/common/http';
+import { Component, ElementRef, Injector, OnInit, ViewChild } from '@angular/core';
+import { FormBuilder, FormGroup, Validators } from '@angular/forms';
+import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateService } from '@ngx-translate/core';
+import { NotifierService } from 'angular-notifier';
+import { APIURLHEADER, ERRORDATA, MODALCLOSERESPONSEDATA } from 'CommonModel';
+import { environment } from 'environment';
+import * as jsyaml from 'js-yaml';
+import { RestService } from 'RestService';
+import { SharedService } from 'SharedService';
+import { isNullOrUndefined } from 'util';
+import { VimAccountDetails } from 'VimAccountModel';
+/**
+ * Creating Component
+ * @Component takes K8sAddClusterComponent.html as template url
+ */
+@Component({
+ selector: 'app-k8s-add-cluster',
+ templateUrl: './K8sAddClusterComponent.html',
+ styleUrls: ['./K8sAddClusterComponent.scss']
+})
+/** Exporting a class @exports K8sAddClusterComponent */
+export class K8sAddClusterComponent implements OnInit {
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** FormGroup instance added to the form @ html @public */
+ public k8sclusterForm: FormGroup;
+
+ /** Contains all vim account collections */
+ public vimAccountSelect: VimAccountDetails;
+
+ /** Instance for active modal service @public */
+ public activeModal: NgbActiveModal;
+
+ /** Variable set for twoway bindng @public */
+ public vimAccountId: string;
+
+ /** Form submission Add */
+ public submitted: boolean = false;
+
+ /** Check the loading results @public */
+ public isLoadingResults: boolean = false;
+
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+
+ /** Element ref for fileInputNets @public */
+ @ViewChild('fileInputNets', { static: true }) public fileInputNets: ElementRef;
+
+ /** Element ref for fileInputNetsLabel @public */
+ @ViewChild('fileInputNetsLabel', { static: true }) public fileInputNetsLabel: ElementRef;
+
+ /** Element ref for fileInputCredentials @public */
+ @ViewChild('fileInputCredentials', { static: true }) public fileInputCredentials: ElementRef;
+
+ /** Element ref for fileInputCredentialsLabel @public */
+ @ViewChild('fileInputCredentialsLabel', { static: true }) public fileInputCredentialsLabel: ElementRef;
+
+ /** FormBuilder instance added to the formBuilder @private */
+ private formBuilder: FormBuilder;
+
+ /** Utilizes rest service for any CRUD operations @private */
+ private restService: RestService;
+
+ /** Notifier service to popup notification @private */
+ private notifierService: NotifierService;
+
+ /** Contains tranlsate instance @private */
+ private translateService: TranslateService;
+
+ /** Controls the header form @private */
+ private headers: HttpHeaders;
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.restService = this.injector.get(RestService);
+ this.activeModal = this.injector.get(NgbActiveModal);
+ this.formBuilder = this.injector.get(FormBuilder);
+ this.notifierService = this.injector.get(NotifierService);
+ this.translateService = this.injector.get(TranslateService);
+ this.sharedService = this.injector.get(SharedService);
+ }
+
+ public ngOnInit(): void {
+ /** On Initializing call the methods */
+ this.k8sclusterFormAction();
+ this.getDetailsvimAccount();
+ this.headers = new HttpHeaders({
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
+ });
+ }
+
+ /** On modal initializing forms @public */
+ public k8sclusterFormAction(): void {
+ this.k8sclusterForm = this.formBuilder.group({
+ name: ['', [Validators.required]],
+ k8s_version: ['', [Validators.required]],
+ vim_account: [null, [Validators.required]],
+ description: ['', [Validators.required]],
+ nets: ['', [Validators.required]],
+ credentials: ['', [Validators.required]]
+ });
+ }
+
+ /** convenience getter for easy access to form fields */
+ get f(): FormGroup['controls'] { return this.k8sclusterForm.controls; }
+
+ /** Call the vimAccount details in the selection options @public */
+ public getDetailsvimAccount(): void {
+ this.isLoadingResults = true;
+ this.restService.getResource(environment.VIMACCOUNTS_URL).subscribe((vimAccounts: VimAccountDetails) => {
+ this.vimAccountSelect = vimAccounts;
+ this.isLoadingResults = false;
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'get');
+ this.isLoadingResults = false;
+ });
+ }
+
+ /** On modal submit k8sAddClusterSubmit will called @public */
+ public k8sAddClusterSubmit(): void {
+ this.submitted = true;
+ this.sharedService.cleanForm(this.k8sclusterForm);
+ if (this.k8sclusterForm.invalid) {
+ return;
+ }
+ const modalData: MODALCLOSERESPONSEDATA = {
+ message: 'Done'
+ };
+ const apiURLHeader: APIURLHEADER = {
+ url: environment.K8SCLUSTER_URL,
+ httpOptions: { headers: this.headers }
+ };
+ const validJSONCredentails: boolean = this.sharedService.checkJson(this.k8sclusterForm.value.credentials);
+ if (validJSONCredentails) {
+ this.k8sclusterForm.value.credentials = jsyaml.load(this.k8sclusterForm.value.credentials.toString(), { json: true });
+ } else {
+ this.notifierService.notify('error', this.translateService.instant('INVALIDCONFIG'));
+ return;
+ }
+ const validJSONNets: boolean = this.sharedService.checkJson(this.k8sclusterForm.value.nets);
+ if (validJSONNets) {
+ this.k8sclusterForm.value.nets = jsyaml.load(this.k8sclusterForm.value.nets.toString(), { json: true });
+ } else {
+ this.notifierService.notify('error', this.translateService.instant('INVALIDCONFIG'));
+ return;
+ }
+ this.isLoadingResults = true;
+ this.restService.postResource(apiURLHeader, this.k8sclusterForm.value).subscribe((result: {}) => {
+ this.activeModal.close(modalData);
+ this.isLoadingResults = false;
+ this.notifierService.notify('success', this.k8sclusterForm.value.name +
+ this.translateService.instant('PAGE.K8S.CREATEDSUCCESSFULLY'));
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'post');
+ this.isLoadingResults = false;
+ });
+ }
+
+ /** Nets file process @private */
+ public netsFile(files: FileList): void {
+ if (files && files.length === 1) {
+ this.sharedService.getFileString(files, 'json').then((fileContent: string): void => {
+ const getNetsJson: string = jsyaml.load(fileContent, { json: true });
+ // tslint:disable-next-line: no-backbone-get-set-outside-model
+ this.k8sclusterForm.get('nets').setValue(JSON.stringify(getNetsJson));
+ }).catch((err: string): void => {
+ if (err === 'typeError') {
+ this.notifierService.notify('error', this.translateService.instant('JSONFILETYPEERRROR'));
+ } else {
+ this.notifierService.notify('error', this.translateService.instant('ERROR'));
+ }
+ this.fileInputNetsLabel.nativeElement.innerText = this.translateService.instant('CHOOSEFILE');
+ this.fileInputNets.nativeElement.value = null;
+ });
+ } else if (files && files.length > 1) {
+ this.notifierService.notify('error', this.translateService.instant('DROPFILESVALIDATION'));
+ }
+ this.fileInputNetsLabel.nativeElement.innerText = files[0].name;
+ this.fileInputNets.nativeElement.value = null;
+ }
+
+ /** credentials file process @private */
+ public credentialsFile(files: FileList): void {
+ if (files && files.length === 1) {
+ this.sharedService.getFileString(files, 'yaml').then((fileContent: string): void => {
+ const getCredentialsJson: string = jsyaml.load(fileContent, { json: true });
+ // tslint:disable-next-line: no-backbone-get-set-outside-model
+ this.k8sclusterForm.get('credentials').setValue(JSON.stringify(getCredentialsJson));
+ }).catch((err: string): void => {
+ if (err === 'typeError') {
+ this.notifierService.notify('error', this.translateService.instant('YAMLFILETYPEERRROR'));
+ } else {
+ this.notifierService.notify('error', this.translateService.instant('ERROR'));
+ }
+ this.fileInputCredentialsLabel.nativeElement.innerText = this.translateService.instant('CHOOSEFILE');
+ this.fileInputCredentials.nativeElement.value = null;
+ });
+ } else if (files && files.length > 1) {
+ this.notifierService.notify('error', this.translateService.instant('DROPFILESVALIDATION'));
+ }
+ this.fileInputCredentialsLabel.nativeElement.innerText = files[0].name;
+ this.fileInputCredentials.nativeElement.value = null;
+ }
+
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<form [formGroup]="k8srepoForm" (ngSubmit)="k8sAddRepoSubmit();">
+ <div class="modal-header">
+ <h4 class="modal-title" id="modal-basic-title">{{'PAGE.K8S.NEWK8SREPO' | translate}}</h4>
+ <button class="button-xs" type="button" class="close" aria-label="Close" (click)="activeModal.close()">
+ <i class="fas fa-times-circle text-danger"></i>
+ </button>
+ </div>
+ <div class="modal-body k8saddrepo">
+ <div class="form-group row">
+ <label class="col-sm-12 col-form-label mandatory-label"
+ [ngClass]="{'text-danger': k8srepoForm.invalid === true && submitted === true}">{{'MANDATORYCHECK' | translate}}</label>
+ <label class="col-sm-4 col-form-label" for="name">{{'PAGE.K8S.NAME' | translate}}*</label>
+ <div class="col-sm-8">
+ <input autocomplete="off" class="form-control" placeholder="{{'PAGE.K8S.NAME' | translate}}" type="text"
+ formControlName="name" id="name" [ngClass]="{ 'is-invalid': submitted && f.name.errors }" required>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label" for="type">{{'PAGE.K8S.TYPE' | translate}}*</label>
+ <div class="col-sm-8">
+ <ng-select [items]="repoTypeSelect" bindLabel="name" bindValue="id"
+ placeholder="{{'SELECT' | translate}} {{'PAGE.K8S.TYPE' | translate}}" formControlName="type" id="type"
+ [ngClass]="{ 'is-invalid': submitted && f.type.errors }" required>
+ </ng-select>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label" for="url">{{'PAGE.K8S.URL' | translate}}*</label>
+ <div class="col-sm-8">
+ <input autocomplete="off" class="form-control" placeholder="{{'PAGE.K8S.URL' | translate}}" type="url"
+ formControlName="url" id="url" [ngClass]="{ 'is-invalid': submitted && f.url.errors }" required>
+ <div *ngIf="k8srepoForm.invalid" class="invalid-feedback">
+ <div *ngIf="f.url.errors && f.url.value">{{'DOMVALIDATIONS.INVALIDURL' | translate}}</div>
+ </div>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label" for="description">{{'PAGE.K8S.DESCRIPTION' | translate}}*</label>
+ <div class="col-sm-8">
+ <textarea class="form-control" placeholder="{{'PAGE.K8S.DESCRIPTION' | translate}}" type="text"
+ formControlName="description" id="description" [ngClass]="{ 'is-invalid': submitted && f.description.errors }"
+ required></textarea>
+ </div>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-danger" (click)="activeModal.close()">{{'CANCEL' | translate}}</button>
+ <button type="submit" class="btn btn-primary">{{'CREATE' | translate}}</button>
+ </div>
+</form>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file k8sAddRepoComponent.ts.
+ */
+import { Component, Injector, OnInit } from '@angular/core';
+import { FormBuilder, FormGroup, Validators } from '@angular/forms';
+import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateService } from '@ngx-translate/core';
+import { NotifierService } from 'angular-notifier';
+import { APIURLHEADER, ERRORDATA, MODALCLOSERESPONSEDATA } from 'CommonModel';
+import { environment } from 'environment';
+import { RestService } from 'RestService';
+import { SharedService } from 'SharedService';
+/**
+ * Creating Component
+ * @Component takes K8sAddRepoComponent.html as template url
+ */
+@Component({
+ selector: 'app-k8s-add-repo',
+ templateUrl: './K8sAddRepoComponent.html',
+ styleUrls: ['./K8sAddRepoComponent.scss']
+})
+/** Exporting a class @exports K8sAddRepoComponent */
+export class K8sAddRepoComponent implements OnInit {
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** FormGroup instance added to the form @ html @public */
+ public k8srepoForm: FormGroup;
+
+ /** Instance for active modal service @public */
+ public activeModal: NgbActiveModal;
+
+ /** Form submission Add */
+ public submitted: boolean = false;
+
+ /** Supported Vim type for the dropdown */
+ public repoTypeSelect: {}[];
+
+ /** Check the loading results @public */
+ public isLoadingResults: boolean = false;
+
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+
+ /** FormBuilder instance added to the formBuilder @private */
+ private formBuilder: FormBuilder;
+
+ /** Utilizes rest service for any CRUD operations @private */
+ private restService: RestService;
+
+ /** Notifier service to popup notification @private */
+ private notifierService: NotifierService;
+
+ /** Contains tranlsate instance @private */
+ private translateService: TranslateService;
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.restService = this.injector.get(RestService);
+ this.activeModal = this.injector.get(NgbActiveModal);
+ this.formBuilder = this.injector.get(FormBuilder);
+ this.notifierService = this.injector.get(NotifierService);
+ this.translateService = this.injector.get(TranslateService);
+ this.sharedService = this.injector.get(SharedService);
+ }
+
+ public ngOnInit(): void {
+ this.repoTypeSelect = [
+ { id: 'helm-chart', name: 'Helm Chart' },
+ { id: 'juju-bundle', name: 'Juju Bundle' }
+ ];
+ /** On Initializing call the methods */
+ this.k8srepoFormAction();
+ }
+
+ /** On modal initializing forms @public */
+ public k8srepoFormAction(): void {
+ this.k8srepoForm = this.formBuilder.group({
+ name: ['', [Validators.required]],
+ type: [null, [Validators.required]],
+ url: ['', [Validators.required, Validators.pattern(this.sharedService.REGX_URL_PATTERN)]],
+ description: ['', [Validators.required]]
+ });
+ }
+
+ /** convenience getter for easy access to form fields */
+ get f(): FormGroup['controls'] { return this.k8srepoForm.controls; }
+
+ /** On modal submit k8sAddRepoSubmit will called @public */
+ public k8sAddRepoSubmit(): void {
+ this.submitted = true;
+ this.sharedService.cleanForm(this.k8srepoForm);
+ if (this.k8srepoForm.invalid) {
+ return;
+ }
+ this.isLoadingResults = true;
+ const modalData: MODALCLOSERESPONSEDATA = {
+ message: 'Done'
+ };
+ const apiURLHeader: APIURLHEADER = {
+ url: environment.K8REPOS_URL
+ };
+ this.restService.postResource(apiURLHeader, this.k8srepoForm.value).subscribe((result: {}) => {
+ this.activeModal.close(modalData);
+ this.notifierService.notify('success', this.k8srepoForm.value.name +
+ this.translateService.instant('PAGE.K8S.CREATEDSUCCESSFULLY'));
+ this.isLoadingResults = false;
+ }, (error: ERRORDATA) => {
+ this.isLoadingResults = false;
+ this.restService.handleError(error, 'post');
+ });
+ }
+
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="row d-flex flex-row justify-content-between">
+ <div class="d-flex align-items-center header-style">{{'PAGE.K8S.REGISTERK8CLUSTER' | translate}}</div>
+ <span class="button">
+ <button class="btn btn-primary" type="button" placement="top" container="body" ngbTooltip="{{'PAGE.K8S.ADDK8CLUSTER' | translate}}"
+ (click)="addK8sCluster()">
+ <i class="fas fa-plus-circle" aria-hidden="true"></i> {{'PAGE.K8S.ADDK8CLUSTER' | translate}}
+ </button>
+ </span>
+</div>
+<div class="row mt-2 mb-0 list-utilites-actions">
+ <div class="col-auto mr-auto">
+ <nav class="custom-items-config">
+ <span><i class="fas fa-clock text-warning"></i>{{operationalStateFirstStep}}</span>
+ <span><i class="fas fa-check-circle text-success"></i>{{operationalStateSecondStep}}</span>
+ <span><i class="fas fa-times-circle text-danger"></i>{{operationalStateThirdStep}}</span>
+ </nav>
+ </div>
+ <page-per-row class="mr-2" (pagePerRow)="onChange($event)"></page-per-row>
+ <page-reload></page-reload>
+</div>
+<div class="smarttable-style bg-white mt-1">
+ <ng2-smart-table [ngClass]="checkDataClass" [settings]="settings" [source]="dataSource" (userRowSelect)="onUserRowSelect($event)">
+ </ng2-smart-table>
+</div>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file k8sclustercomponent.ts.
+ */
+import { Component, Injector, OnDestroy, OnInit } from '@angular/core';
+import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateService } from '@ngx-translate/core';
+import { CONFIGCONSTANT, ERRORDATA, MODALCLOSERESPONSEDATA } from 'CommonModel';
+import { DataService } from 'DataService';
+import { environment } from 'environment';
+import { K8sActionComponent } from 'K8sActionComponent';
+import { K8sAddClusterComponent } from 'K8sAddClusterComponent';
+import { K8SCLUSTERDATA, K8SCLUSTERDATADISPLAY } from 'K8sModel';
+import { LocalDataSource } from 'ng2-smart-table';
+import { RestService } from 'RestService';
+import { Subscription } from 'rxjs';
+import { SharedService } from 'SharedService';
+/**
+ * Creating Component
+ * @Component takes K8sClusterComponent.html as template url
+ */
+@Component({
+ selector: 'app-k8scluster',
+ templateUrl: './K8sClusterComponent.html',
+ styleUrls: ['./K8sClusterComponent.scss']
+})
+/** Exporting a class @exports K8sClusterComponent */
+export class K8sClusterComponent implements OnInit, OnDestroy {
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** handle translate @public */
+ public translateService: TranslateService;
+
+ /** Data of smarttable populate through LocalDataSource @public */
+ public dataSource: LocalDataSource = new LocalDataSource();
+
+ /** Columns list of the smart table @public */
+ public columnList: object = {};
+
+ /** Settings for smarttable to populate the table with columns @public */
+ public settings: object = {};
+
+ /** Check the loading results @public */
+ public isLoadingResults: boolean = true;
+
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+
+ /** Class for empty and present data @public */
+ public checkDataClass: string;
+
+ /** operational State init data @public */
+ public operationalStateFirstStep: string = CONFIGCONSTANT.k8OperationalStateFirstStep;
+
+ /** operational State running data @public */
+ public operationalStateSecondStep: string = CONFIGCONSTANT.k8OperationalStateStateSecondStep;
+
+ /** operational State failed data @public */
+ public operationalStateThirdStep: string = CONFIGCONSTANT.k8OperationalStateThirdStep;
+
+ /** Instance of the rest service @private */
+ private restService: RestService;
+
+ /** dataService to pass the data from one component to another @private */
+ private dataService: DataService;
+
+ /** Formation of appropriate Data for LocalDatasource @private */
+ private k8sClusterData: {}[] = [];
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ /** Instance of the modal service @private */
+ private modalService: NgbModal;
+
+ /** Instance of subscriptions @private */
+ private generateDataSub: Subscription;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.restService = this.injector.get(RestService);
+ this.dataService = this.injector.get(DataService);
+ this.sharedService = this.injector.get(SharedService);
+ this.translateService = this.injector.get(TranslateService);
+ this.modalService = this.injector.get(NgbModal);
+ }
+ /** Lifecyle Hooks the trigger before component is instantiate @public */
+ public ngOnInit(): void {
+ this.generateColumns();
+ this.generateSettings();
+ this.generateData();
+ this.generateDataSub = this.sharedService.dataEvent.subscribe(() => { this.generateData(); });
+ }
+
+ /** smart table Header Colums @public */
+ public generateColumns(): void {
+ this.columnList = {
+ name: { title: this.translateService.instant('NAME'), width: '20%', sortDirection: 'asc' },
+ identifier: { title: this.translateService.instant('IDENTIFIER'), width: '20%' },
+ version: { title: this.translateService.instant('K8VERSION'), width: '10%' },
+ operationalState: {
+ title: this.translateService.instant('OPERATIONALSTATE'), width: '15%', type: 'html',
+ filter: {
+ type: 'list',
+ config: {
+ selectText: 'Select',
+ list: [
+ { value: this.operationalStateFirstStep, title: this.operationalStateFirstStep },
+ { value: this.operationalStateSecondStep, title: this.operationalStateSecondStep },
+ { value: this.operationalStateThirdStep, title: this.operationalStateThirdStep }
+ ]
+ }
+ },
+ valuePrepareFunction: (cell: K8SCLUSTERDATADISPLAY, row: K8SCLUSTERDATADISPLAY): string => {
+ if (row.operationalState === this.operationalStateFirstStep) {
+ return `<span class="icon-label" title="${row.operationalState}">
+ <i class="fas fa-clock text-warning"></i>
+ </span>`;
+ } else if (row.operationalState === this.operationalStateSecondStep) {
+ return `<span class="icon-label" title="${row.operationalState}">
+ <i class="fas fa-check-circle text-success"></i>
+ </span>`;
+ } else if (row.operationalState === this.operationalStateThirdStep) {
+ return `<span class="icon-label" title="${row.operationalState}">
+ <i class="fas fa-times-circle text-danger"></i>
+ </span>`;
+ } else {
+ return `<span>${row.operationalState}</span>`;
+ }
+ }
+ },
+ created: { title: this.translateService.instant('CREATED'), width: '15%' },
+ modified: { title: this.translateService.instant('MODIFIED'), width: '15%' },
+ Actions: {
+ name: 'Action', width: '5%', filter: false, sort: false, title: this.translateService.instant('ACTIONS'), type: 'custom',
+ valuePrepareFunction: (cell: K8SCLUSTERDATADISPLAY, row: K8SCLUSTERDATADISPLAY): K8SCLUSTERDATADISPLAY => row,
+ renderComponent: K8sActionComponent
+ }
+ };
+ }
+
+ /** smart table Data Settings @public */
+ public generateSettings(): void {
+ this.settings = {
+ columns: this.columnList,
+ actions: { add: false, edit: false, delete: false, position: 'right' },
+ attr: this.sharedService.tableClassConfig(),
+ pager: this.sharedService.paginationPagerConfig(),
+ noDataMessage: this.translateService.instant('NODATAMSG')
+ };
+ }
+
+ /** smart table listing manipulation @public */
+ public onChange(perPageValue: number): void {
+ this.dataSource.setPaging(1, perPageValue, true);
+ }
+
+ /** smart table listing manipulation @public */
+ public onUserRowSelect(event: MessageEvent): void {
+ Object.assign(event.data, { page: 'k8-cluster' });
+ this.dataService.changeMessage(event.data);
+ }
+
+ /** Compose new K8s Cluster Accounts @public */
+ public addK8sCluster(): void {
+ const modalRef: NgbModalRef = this.modalService.open(K8sAddClusterComponent, { backdrop: 'static' });
+ modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
+ if (result) {
+ this.sharedService.callData();
+ }
+ }).catch();
+ }
+
+ /**
+ * Lifecyle hook which get trigger on component destruction
+ */
+ public ngOnDestroy(): void {
+ this.generateDataSub.unsubscribe();
+ }
+
+ /** Generate nsData object from loop and return for the datasource @public */
+ public generateK8sclusterData(k8sClusterdata: K8SCLUSTERDATA): K8SCLUSTERDATADISPLAY {
+ return {
+ name: k8sClusterdata.name,
+ identifier: k8sClusterdata._id,
+ operationalState: k8sClusterdata._admin.operationalState,
+ version: k8sClusterdata.k8s_version,
+ created: this.sharedService.convertEpochTime(Number(k8sClusterdata._admin.created)),
+ modified: this.sharedService.convertEpochTime(Number(k8sClusterdata._admin.modified)),
+ pageType: 'cluster'
+ };
+ }
+
+ /** Fetching the data from server to Load in the smarttable @protected */
+ protected generateData(): void {
+ this.isLoadingResults = true;
+ this.restService.getResource(environment.K8SCLUSTER_URL).subscribe((k8sClusterDatas: K8SCLUSTERDATA[]) => {
+ this.k8sClusterData = [];
+ k8sClusterDatas.forEach((k8sClusterdata: K8SCLUSTERDATA) => {
+ const k8sClusterDataObj: K8SCLUSTERDATADISPLAY = this.generateK8sclusterData(k8sClusterdata);
+ this.k8sClusterData.push(k8sClusterDataObj);
+ });
+ if (this.k8sClusterData.length > 0) {
+ this.checkDataClass = 'dataTables_present';
+ } else {
+ this.checkDataClass = 'dataTables_empty';
+ }
+ this.dataSource.load(this.k8sClusterData).then((data: boolean) => {
+ this.isLoadingResults = false;
+ }).catch(() => {
+ this.isLoadingResults = false;
+ });
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'get');
+ this.isLoadingResults = false;
+ });
+ }
+
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="row d-flex flex-row justify-content-between">
+ <div class="d-flex align-items-center header-style">{{'PAGE.K8S.REGISTERK8REPO' | translate}}</div>
+ <span class="button">
+ <button class="btn btn-primary" type="button" placement="top" container="body" ngbTooltip="{{'PAGE.K8S.ADDK8REPO' | translate}}"
+ (click)="addK8sRepo()">
+ <i class="fas fa-plus-circle" aria-hidden="true"></i> {{'PAGE.K8S.ADDK8REPO' | translate}}
+ </button>
+ </span>
+</div>
+<div class="row mt-2 mb-0 form-group justify-content-end list-utilites-actions">
+ <page-per-row class="mr-2" (pagePerRow)="onChange($event)"></page-per-row>
+ <page-reload></page-reload>
+</div>
+<div class="smarttable-style bg-white mt-1">
+ <ng2-smart-table [ngClass]="checkDataClass" [settings]="settings" [source]="dataSource" (userRowSelect)="onUserRowSelect($event)">
+ </ng2-smart-table>
+</div>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file K8sRepositoryComponent.ts.
+ */
+import { Component, Injector, OnDestroy, OnInit } from '@angular/core';
+import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateService } from '@ngx-translate/core';
+import { ERRORDATA, MODALCLOSERESPONSEDATA } from 'CommonModel';
+import { DataService } from 'DataService';
+import { environment } from 'environment';
+import { K8sActionComponent } from 'K8sActionComponent';
+import { K8sAddRepoComponent } from 'K8sAddRepoComponent';
+import { K8SREPODATA, K8SREPODATADISPLAY } from 'K8sModel';
+import { LocalDataSource } from 'ng2-smart-table';
+import { RestService } from 'RestService';
+import { Subscription } from 'rxjs';
+import { SharedService } from 'SharedService';
+/**
+ * Creating Component
+ * @Component takes K8sRepositoryComponent.html as template url
+ */
+@Component({
+ selector: 'app-k8srepository',
+ templateUrl: './K8sRepositoryComponent.html',
+ styleUrls: ['./K8sRepositoryComponent.scss']
+})
+/** Exporting a class @exports K8sRepositoryComponent */
+export class K8sRepositoryComponent implements OnInit, OnDestroy {
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** handle translate @public */
+ public translateService: TranslateService;
+
+ /** Data of smarttable populate through LocalDataSource @public */
+ public dataSource: LocalDataSource = new LocalDataSource();
+
+ /** Columns list of the smart table @public */
+ public columnList: object = {};
+
+ /** Settings for smarttable to populate the table with columns @public */
+ public settings: object = {};
+
+ /** Check the loading results @public */
+ public isLoadingResults: boolean = true;
+
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+
+ /** Class for empty and present data @public */
+ public checkDataClass: string;
+
+ /** Instance of the rest service @private */
+ private restService: RestService;
+
+ /** dataService to pass the data from one component to another @private */
+ private dataService: DataService;
+
+ /** Formation of appropriate Data for LocalDatasource @private */
+ private k8sRepoData: {}[] = [];
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ /** Instance of the modal service @private */
+ private modalService: NgbModal;
+
+ /** Instance of subscriptions @private */
+ private generateDataSub: Subscription;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.restService = this.injector.get(RestService);
+ this.dataService = this.injector.get(DataService);
+ this.sharedService = this.injector.get(SharedService);
+ this.translateService = this.injector.get(TranslateService);
+ this.modalService = this.injector.get(NgbModal);
+ }
+ /** Lifecyle Hooks the trigger before component is instantiate @public */
+ public ngOnInit(): void {
+ this.generateColumns();
+ this.generateSettings();
+ this.generateData();
+ this.generateDataSub = this.sharedService.dataEvent.subscribe(() => { this.generateData(); });
+ }
+
+ /** smart table Header Colums @public */
+ public generateColumns(): void {
+ this.columnList = {
+ name: { title: this.translateService.instant('NAME'), width: '20%', sortDirection: 'asc' },
+ identifier: { title: this.translateService.instant('IDENTIFIER'), width: '20%' },
+ url: { title: this.translateService.instant('URL'), width: '15%' },
+ type: { title: this.translateService.instant('TYPE'), width: '10%' },
+ created: { title: this.translateService.instant('CREATED'), width: '15%' },
+ modified: { title: this.translateService.instant('MODIFIED'), width: '15%' },
+ Actions: {
+ name: 'Action', width: '5%', filter: false, sort: false, title: this.translateService.instant('ACTIONS'), type: 'custom',
+ valuePrepareFunction: (cell: K8SREPODATADISPLAY, row: K8SREPODATADISPLAY): K8SREPODATADISPLAY => row,
+ renderComponent: K8sActionComponent
+ }
+ };
+ }
+
+ /** smart table Data Settings @public */
+ public generateSettings(): void {
+ this.settings = {
+ columns: this.columnList,
+ actions: { add: false, edit: false, delete: false, position: 'right' },
+ attr: this.sharedService.tableClassConfig(),
+ pager: this.sharedService.paginationPagerConfig(),
+ noDataMessage: this.translateService.instant('NODATAMSG')
+ };
+ }
+
+ /** smart table listing manipulation @public */
+ public onChange(perPageValue: number): void {
+ this.dataSource.setPaging(1, perPageValue, true);
+ }
+
+ /** smart table listing manipulation @public */
+ public onUserRowSelect(event: MessageEvent): void {
+ Object.assign(event.data, { page: 'k8-repo' });
+ this.dataService.changeMessage(event.data);
+ }
+
+ /** Compose new K8s Repo Accounts @public */
+ public addK8sRepo(): void {
+ const modalRef: NgbModalRef = this.modalService.open(K8sAddRepoComponent, { backdrop: 'static' });
+ modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
+ if (result) {
+ this.sharedService.callData();
+ }
+ }).catch();
+ }
+
+ /**
+ * Lifecyle hook which get trigger on component destruction
+ */
+ public ngOnDestroy(): void {
+ this.generateDataSub.unsubscribe();
+ }
+
+ /** Generate nsData object from loop and return for the datasource @public */
+ // tslint:disable-next-line: typedef
+ public generateK8sRepoData(k8sRepodata: K8SREPODATA): K8SREPODATADISPLAY {
+ return {
+ name: k8sRepodata.name,
+ identifier: k8sRepodata._id,
+ url: k8sRepodata.url,
+ type: k8sRepodata.type,
+ created: this.sharedService.convertEpochTime(Number(k8sRepodata._admin.created)),
+ modified: this.sharedService.convertEpochTime(Number(k8sRepodata._admin.modified)),
+ pageType: 'repo'
+ };
+ }
+
+ /** Fetching the data from server to Load in the smarttable @protected */
+ protected generateData(): void {
+ this.isLoadingResults = true;
+ this.restService.getResource(environment.K8REPOS_URL).subscribe((k8sRepoDatas: K8SREPODATA[]) => {
+ this.k8sRepoData = [];
+ k8sRepoDatas.forEach((k8sRepodata: K8SREPODATA) => {
+ const k8sRepoDataObj: K8SREPODATADISPLAY = this.generateK8sRepoData(k8sRepodata);
+ this.k8sRepoData.push(k8sRepoDataObj);
+ });
+ if (this.k8sRepoData.length > 0) {
+ this.checkDataClass = 'dataTables_present';
+ } else {
+ this.checkDataClass = 'dataTables_empty';
+ }
+ this.dataSource.load(this.k8sRepoData).then((data: boolean) => {
+ this.isLoadingResults = false;
+ }).catch(() => {
+ this.isLoadingResults = false;
+ });
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'get');
+ this.isLoadingResults = false;
+ });
+ }
+
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<app-header></app-header>
+<div id="main-wrapper" class="container-fluid" dir="ltr" appGottoTop>
+ <div class="layout-wrapper mt-2">
+ <app-sidebar></app-sidebar>
+ <div class="content-section pl-4">
+ <app-breadcrumb></app-breadcrumb>
+ <div class="mt-2">
+ <div class="card custom-card shadow">
+ <div class="card-body custom-card-body">
+ <router-outlet></router-outlet>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <button class="btn btn-sm btn-primary border border-radius-default goto-top" type="button"
+ *ngIf="sharedService.showGotoTop" (click)="gotoTop()">
+ <i class="fas fa-angle-up"></i>
+ </button>
+</div>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+@import "../../assets/scss/mixins/mixin";
+@import "../../assets/scss/variable";
+#main-wrapper {
+ @include wh-value(100%, null);
+ .layout-wrapper {
+ @include flexbox(flex, null, null, null, stretch, null);
+ .content-section {
+ @include wh-value(100%, null);
+ @include transition(all, 0.3s, null, null);
+ overflow-x: auto;
+ }
+ }
+ .goto-top {
+ @include position_value(fixed, null, 30px, 10px, null);
+ @include font(null, 20px, null);
+ outline: none;
+ @include wh-value(40px, 40px);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file NS Instance Component
+ */
+import { Component } from '@angular/core';
+import { SharedService } from 'SharedService';
+/**
+ * Creating component
+ * @Component takes LayoutComponent.html as template url
+ */
+@Component({
+ selector: 'app-layout',
+ templateUrl: './LayoutComponent.html',
+ styleUrls: ['./LayoutComponent.scss']
+})
+/** Exporting a class @exports LayoutComponent */
+export class LayoutComponent {
+ /** Contains all methods related to shared @private */
+ public sharedService: SharedService;
+
+ constructor(sharedService: SharedService) {
+ this.sharedService = sharedService;
+ }
+ /** method to handle go to top event @public */
+ public gotoTop(): void {
+ window.scroll({ behavior: 'smooth', top: 0, left: 0 });
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<nav aria-label="breadcrumb" class="breadcrumb-holder">
+ <ul class="breadcrumb-custom pl-0">
+ <li class="breadcrumb-item-custom" [routerLink]="item.url" *ngFor="let item of menuItems; let i = index" [class.active]="i===menuItems.length-1">
+ <a *ngIf="i!==menuItems.length-1">
+ <i *ngIf="i==0" class="fas fa-th-large"></i> {{item.title | translate}}
+ </a>
+ <span *ngIf="i===menuItems.length-1"><i *ngIf="i==0" class="fas fa-th-large"></i> {{item.title | translate}}</span>
+ </li>
+ </ul>
+</nav>
\ No newline at end of file
--- /dev/null
+/*
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+@import "../../../assets/scss/mixins/mixin";
+@import "../../../assets/scss/variable";
+.breadcrumb-holder {
+ .breadcrumb-custom {
+ @include box-shadow(0, 2px, 5px, 0, rgba(0, 0, 0, 0.25));
+ @include roundedCorners(5);
+ @include background(null, $white, null, null, null);
+ @include margin-value(0, 0, 0, 0);
+ @include flexbox(inline-block, null, null, null, null, null);
+ overflow: hidden;
+ .breadcrumb-item-custom {
+ @include flexbox(block, null, null, null, null, null);
+ @include line-height(35px);
+ @include font(null, 12px, null);
+ @include padding-value(0, 10, 0, 30);
+ @include position_value(relative, null, null, null, null);
+ float: left;
+ cursor: pointer;
+ &:hover {
+ @include background(null, $secondary, null, null, null);
+ a {
+ color: $white;
+ }
+ &::after {
+ @include background(null, $secondary, null, null, null);
+ }
+ }
+ a {
+ color: $primary;
+ }
+ &:first-child {
+ padding-left: 20px;
+ @include roundedTopLeftRadius(5);
+ @include roundedBottomLeftRadius(5);
+ &::before {
+ @include position_value(null, null, null, null, 14px);
+ }
+ }
+ &:last-child {
+ @include roundedTopRightRadius(5);
+ @include roundedBottomRightRadius(5);
+ padding-right: 20px;
+ &::after {
+ content: none;
+ }
+ }
+ &::after {
+ content: "";
+ @include position_value(absolute, 0, -18px, null, null);
+ @include wh-value(36px, 36px);
+ @include background(null, $white, null, null, null);
+ @include box-shadow(2px, -2px, 0, 1px, $breadcrumb-after-color);
+ transform: scale(0.707) rotate(45deg);
+ z-index: 1;
+ @include roundedTopRightRadius(5);
+ @include roundedBottomLeftRadius(50);
+ }
+ &.active {
+ @include background(null, $primary, null, null, null);
+ color: $white;
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file Bread Crumb component.
+ */
+import { Component, Injector, OnInit } from '@angular/core';
+import { ActivatedRoute, NavigationEnd, Router, RouterEvent, UrlSegment } from '@angular/router';
+import { TranslateService } from '@ngx-translate/core';
+import { BREADCRUMBITEM } from 'CommonModel';
+import { filter, startWith } from 'rxjs/operators';
+import { isNullOrUndefined } from 'util';
+
+/**
+ * Creating component
+ * @Component takes BreadcrumbComponent.html as template url
+ */
+@Component({
+ selector: 'app-breadcrumb',
+ templateUrl: './BreadcrumbComponent.html',
+ styleUrls: ['./BreadcrumbComponent.scss']
+})
+
+/** Exporting a class @exports BreadcrumbComponent */
+export class BreadcrumbComponent implements OnInit {
+ /** To inject breadCrumb @public */
+ public static readonly ROUTE_DATA_BREADCRUMB: string = 'breadcrumb';
+
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** To inject breadCrumb Default icon and url @public */
+ public readonly home: {} = { icon: 'pi pi-th-large', url: '/' };
+
+ /** To inject breadCrumb Menus @public */
+ public menuItems: BREADCRUMBITEM[];
+
+ /** Service holds the router information @private */
+ private router: Router;
+
+ /** Holds teh instance of AuthService class of type AuthService @private */
+ private activatedRoute: ActivatedRoute;
+
+ /** handle translate service @private */
+ private translateService: TranslateService;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.router = this.injector.get(Router);
+ this.activatedRoute = this.injector.get(ActivatedRoute);
+ this.translateService = this.injector.get(TranslateService);
+ }
+ /** Lifecyle Hooks the trigger before component is instantiate @public */
+ public ngOnInit(): void {
+ this.router.events
+ .pipe(filter((event: RouterEvent) => event instanceof NavigationEnd), startWith(undefined))
+ .subscribe(() => this.menuItems = this.createBreadcrumbs(this.activatedRoute.root));
+ }
+
+ /** Generate breadcrumbs from data given the module routes @private */
+ private createBreadcrumbs(route: ActivatedRoute, url: string = '', breadcrumbs: BREADCRUMBITEM[] = []):
+ BREADCRUMBITEM[] {
+ const children: ActivatedRoute[] = route.children;
+ if (children.length === 0) {
+ return breadcrumbs;
+ }
+ for (const child of children) {
+ const routeURL: string = child.snapshot.url.map((segment: UrlSegment) => segment.path).join('/');
+ if (routeURL !== '') {
+ url += `/${routeURL}`;
+ }
+ let menuLIst: BREADCRUMBITEM[] = child.snapshot.data[BreadcrumbComponent.ROUTE_DATA_BREADCRUMB];
+ if (!isNullOrUndefined(menuLIst)) {
+ menuLIst = JSON.parse(JSON.stringify(menuLIst));
+ menuLIst.forEach((item: BREADCRUMBITEM) => {
+ if (!isNullOrUndefined(item.title)) {
+ item.title = item.title.replace('{type}', this.checkTitle(item, child.snapshot.params.type));
+ item.title = item.title.replace('{id}', child.snapshot.params.id);
+ item.title = item.title.replace('{project}', localStorage.getItem('project'));
+ }
+ if (!isNullOrUndefined(item.url)) {
+ item.url = item.url.replace('{type}', child.snapshot.params.type);
+ item.url = item.url.replace('{id}', child.snapshot.params.id);
+ }
+ breadcrumbs.push(item);
+ });
+ }
+ return this.createBreadcrumbs(child, url, breadcrumbs);
+ }
+ }
+ /** Check and update title based on type of operations @private */
+ private checkTitle(breadcrumbItem: BREADCRUMBITEM, opertionType: string): string {
+ if (!isNullOrUndefined(breadcrumbItem.url)) {
+ if (breadcrumbItem.url.indexOf('packages') !== -1) {
+ return this.matchPackageTitle(opertionType);
+ }
+ if (breadcrumbItem.url.indexOf('instances') !== -1) {
+ return this.matchInstanceTitle(opertionType);
+ }
+ return breadcrumbItem.title;
+ }
+ }
+ /** check and update package title based on package type @private */
+ private matchPackageTitle(opertionType: string): string {
+ if (opertionType === 'ns') {
+ return this.translateService.instant('NSPACKAGES');
+ } else if (opertionType === 'vnf') {
+ return this.translateService.instant('VNFPACKAGES');
+ } else {
+ return this.translateService.instant('PAGE.DASHBOARD.NETSLICETEMPLATE');
+ }
+ }
+ /** check and update package title based on instance type @private */
+ private matchInstanceTitle(opertionType: string): string {
+ if (opertionType === 'ns') {
+ return this.translateService.instant('NSINSTANCES');
+ } else if (opertionType === 'vnf') {
+ return this.translateService.instant('VNFINSTANCES');
+ } else if (opertionType === 'pdu') {
+ return this.translateService.instant('PDUINSTANCES');
+ } else {
+ return this.translateService.instant('PAGE.DASHBOARD.NETSLICEINSTANCE');
+ }
+ }
+
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<span class="d-none px-3 py-2 text-center text-bold bg-primary text-white">Here is a newer {{'APPVERSION' | translate}} {{PACKAGEVERSION}}
+ of OSM!</span>
+
+<nav class="navbar navbar-expand-md sticky-top bg-white" role="navigation">
+ <a class="navbar-brand">
+ <img routerLink="/" src="assets/images/logo.png" class="osm-logo"
+ alt="OPEN SOURCE MANO" draggable="false">
+ </a>
+ <div class="nav navbar-nav nav-flex-icons ml-auto">
+ <ul class="navbar-nav cursor-pointer" ngbDropdown display="dynamic" placement="bottom-right">
+ <li class="nav-item dropdown">
+ <a class="nav-link dropdown-toggle" id="navbarDropdownProject" ngbDropdownToggle>
+ <i class="fas fa-folder-open"></i> {{'PAGE.DASHBOARD.PROJECTS' | translate}}
+ ({{selectedProject | async}})
+ </a>
+ <div class="dropdown-menu custom-dropdown-menu m-0 p-0" ngbDropdownMenu *ngIf="getSelectedProject"
+ aria-labelledby="navbarDropdownProject">
+ <a ngbDropdownItem class="dropdown-item project-item"
+ [ngClass]="list.project_name === getSelectedProject ? 'activeProject' : ''"
+ (click)="list.project_name === getSelectedProject ? '' : this.projectService.switchProjectModal(list)"
+ *ngFor="let list of projectList$ | async" placement="left" container="body"
+ ngbTooltip="{{ (list.project_name === getSelectedProject ? 'CURRENTPROJECT' : 'SWITCHPROJECT') | translate}}">
+ <span>{{list.project_name}}</span>
+ <i *ngIf="list.project_name === getSelectedProject"
+ class="fas fa-check-circle text-success"></i>
+ <i *ngIf="list.project_name !== getSelectedProject" class="fas fa-exchange-alt text-danger"></i>
+ </a>
+ </div>
+ </li>
+ </ul>
+ <ul class="navbar-nav cursor-pointer text-right" ngbDropdown display="dynamic" placement="bottom-right">
+ <li class="nav-item dropdown">
+ <a class="nav-link dropdown-toggle" id="navbarDropdown" ngbDropdownToggle>
+ <i class="fas fa-user-circle"></i> {{'USER' | translate}} ({{username$ | async}})
+ </a>
+ <div class="dropdown-menu custom-dropdown-menu m-0 p-0" ngbDropdownMenu
+ aria-labelledby="navbarDropdown">
+ <a ngbDropdownItem class="dropdown-item project-item" (click)="userSettings()">
+ <span>{{'PAGE.DASHBOARD.USERSETTINGS' | translate}}</span>
+ <i class="fas fa-users-cog"></i>
+ </a>
+ <a ngbDropdownItem class="dropdown-item project-item" (click)="logout()">
+ <span>{{'PAGE.DASHBOARD.LOGOUT' | translate}}</span>
+ <i class="fas fa-sign-out-alt"></i>
+ </a>
+ <div class="custom-divider"></div>
+ <a *ngIf="sharedService.osmVersion" ngbDropdownItem class="dropdown-item project-item osm-version" href="javascript:void(0);">
+ <span>{{'OSMVERSION' | translate}} {{sharedService.osmVersion}}</span>
+ </a>
+ </div>
+ </li>
+ </ul>
+ </div>
+</nav>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+@import '../../../assets/scss/mixins/mixin';
+@import '../../../assets/scss/variable';
+
+.navbar{
+ @include box-shadow(0px, 0px, 12px, 0px, rgba($black,0.14));
+ @include border(all, 0, solid, $gray-80);
+ .osm-logo{
+ cursor: pointer;
+ }
+ .custom-dropdown-menu {
+ .dropdown-item{
+ &.project-item{
+ @include flexbox(flex, space-between, row, null, center, null);
+ }
+ &:active, &:hover, &.active{
+ @include background(null, $theme-bg-color, null, null, null);
+ color: $primary;
+ }
+ &.activeProject{
+ cursor: default;
+ }
+ }
+ .custom-divider{
+ @include wh-value(null, 0);
+ @include border(top, 2, solid, $primary);
+ overflow: hidden;
+ }
+ }
+ .osm-version{
+ @include background(null, $theme-bg-color, null, null, null);
+ color: $primary;
+ cursor: default;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+
+/**
+ * @file Header Component
+ */
+import { Component, Injector, OnInit } from '@angular/core';
+import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
+import { AuthenticationService } from 'AuthenticationService';
+import { environment } from 'environment';
+import { ProjectService } from 'ProjectService';
+import { Observable } from 'rxjs';
+import { SharedService } from 'SharedService';
+import { ProjectRoleMappings, UserDetail } from 'UserModel';
+import { UserSettingsComponent } from 'UserSettingsComponent';
+
+/**
+ * Creating component
+ * @Component takes HeaderComponent.html as template url
+ */
+@Component({
+ selector: 'app-header',
+ templateUrl: './HeaderComponent.html',
+ styleUrls: ['./HeaderComponent.scss']
+})
+/** Exporting a class @exports HeaderComponent */
+export class HeaderComponent implements OnInit {
+ /** Invoke service injectors @public */
+ public injector: Injector;
+
+ /** Variables holds all the projects @public */
+ public projectList$: Observable<{}[]>;
+
+ /** Observable holds logined value @public */
+ public username$: Observable<string>;
+
+ /** Variables holds admin is logged or not @public */
+ public isAdmin: boolean;
+
+ /** Variables holds the selected project @public */
+ public selectedProject: Observable<string>;
+
+ /** project @public */
+ public getSelectedProject: string;
+
+ /** Version holds packages version @public */
+ public PACKAGEVERSION: string;
+
+ /** Contains all methods related to shared @public */
+ public sharedService: SharedService;
+
+ /** Utilizes auth service for any auth operations @private */
+ private authService: AuthenticationService;
+
+ /** Holds all project details @private */
+ private projectService: ProjectService;
+
+ /** Utilizes modal service for any modal operations @private */
+ private modalService: NgbModal;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.authService = this.injector.get(AuthenticationService);
+ this.modalService = this.injector.get(NgbModal);
+ this.projectService = this.injector.get(ProjectService);
+ this.sharedService = this.injector.get(SharedService);
+ }
+
+ /** Lifecyle Hooks the trigger before component is instantiate @public */
+ public ngOnInit(): void {
+ this.isAdmin = (localStorage.getItem('isAdmin') === 'true') ? true : false;
+ this.selectedProject = this.authService.ProjectName;
+ this.authService.ProjectName.subscribe((projectNameFinal: string) => {
+ this.getSelectedProject = projectNameFinal;
+ });
+ this.username$ = this.authService.username;
+ this.projectService.setHeaderProjects();
+ this.projectList$ = this.projectService.projectList;
+ this.PACKAGEVERSION = environment.packageVersion;
+ }
+
+ /** Logout function @public */
+ public logout(): void {
+ this.authService.logout();
+ }
+
+ /** Implementation of model for UserSettings options.@public */
+ public userSettings(): void {
+ this.modalService.open(UserSettingsComponent, { backdrop: 'static' });
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div id="sidebar" class="p-2 sidebar-mini" [class.sidebar-collapse]="classAppliedForDesktop" [class.sidebar-open]="classAppliedForMobile">
+ <div class="custom-menu" (click)="sideBarOpenClose()">
+ <button type="button" id="sidebarCollapse" class="btn btn-primary">
+ <i class="fa fa-bars"></i>
+ </button>
+ </div>
+ <nav>
+ <ul class="scrollable-menu">
+ <li *ngFor="let menu of getMenus; let i = index" [ngClass]="{'hasChild': menu.isChildExists }"
+ class="{{menu.liClass}}" id="{{menu.clickFunction}}{{i}}"
+ (click)="handleMenuFunction(i, menu.clickFunction, 'menu-open', menu.isChildExists)"
+ [routerLinkActiveOptions]="{exact: menu.routerLinkActiveOptions !== undefined ? menu.routerLinkActiveOptions : false}"
+ [routerLinkActive]="menu.routerLinkActive !== undefined ? menu.routerLinkActive : ''">
+ <a *ngIf="menu.isChildExists" class="{{menu.anchorTagClass}}">
+ <i class="{{menu.icon}}"></i>
+ <span>{{ menu.menuName | translate}}</span>
+ </a>
+ <a *ngIf="!menu.isChildExists" class="{{menu.anchorTagClass}}" [routerLink]="menu.routerLink">
+ <i class="{{menu.icon}}"></i>
+ <span>{{ menu.menuName | translate}}</span>
+ </a>
+ <ul *ngIf="menu.isChildExists" class="{{menu.ulClass}}">
+ <li *ngFor="let childMenu of menu.childItems"
+ [routerLinkActiveOptions]="{exact: childMenu.routerLinkActiveOptions}"
+ [routerLinkActive]="childMenu.routerLinkActive" (click)="checkAndCloseSideBar(childMenu.isChildExists)">
+ <a class="{{childMenu.anchorTagClass}}" [routerLink]="childMenu.routerLink">
+ <i class="{{childMenu.icon}}"></i>
+ <span>{{childMenu.menuName | translate}}</span>
+ </a>
+ </li>
+ </ul>
+ </li>
+ </ul>
+ </nav>
+</div>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+@import "../../../assets/scss/mixins/mixin";
+@import "../../../assets/scss/variable";
+$active-margin-left: -230;
+$minimize-left: 45px;
+.sidebar-mini {
+ @include transition(all, 0.3s, ease-in-out, 0s);
+ @include position_value(relative, null, null, null, null);
+ z-index: 10;
+ .custom-menu {
+ @include flexbox(inline-block, null, null, null, null, null);
+ @include position_value(absolute, 25px, 4px, null, null);
+ @include margin-value(0, -20, 0, 0);
+ .btn {
+ @include wh-value(55px, 55px);
+ @include roundedCornersPercentage(50%);
+ @include position_value(relative, null, null, null, null);
+ @include background(null, transparent, null, null, null);
+ @include border(all, 0, solid, transparent);
+ i {
+ @include margin-value(0, -40, 0, 0);
+ @include font(null, 14px, null);
+ }
+ &.btn-primary {
+ &:after {
+ content: "";
+ @include position_value(absolute, 0, 0, 0, 0);
+ @include background(null, $secondary, null, null, null);
+ @include roundedCorners(10);
+ @include rotate(45);
+ z-index: -1;
+ }
+ }
+ &:hover,
+ &:focus,
+ &:active {
+ @include background(null, transparent !important, null, null, null);
+ }
+ }
+ }
+ nav {
+ @include wh-value(200px, null);
+ @include transition(width, 0.2s, ease-in-out, 0s);
+ ul {
+ @include padding-value(0, 0, 0, 0);
+ @include margin-value(0, 0, 0, 0);
+ @include wh-value(100%, null);
+ @include background(null, $theme-bg-color, null, null, null);
+ li {
+ @include position_value(relative, null, null, null, null);
+ @include background(null, $secondary, null, null, null);
+ @include line-height(14px);
+ list-style-type: none;
+ cursor: pointer;
+ color: $white;
+ &.round-edge-top-3 {
+ @include roundedTopRightRadius(3);
+ @include roundedTopLeftRadius(3);
+ }
+ &.round-edge-bottom-3 {
+ @include roundedBottomLeftRadius(3);
+ @include roundedBottomRightRadius(3);
+ }
+ &.border-bottom-none {
+ @include border(bottom, 0, !important, null);
+ }
+ &.header-menu {
+ @include background(null, $theme-bg-color, null, null, null);
+ @include padding-value(10, 20, 0, 4);
+ @include font(null, null, bold);
+ cursor: default;
+ .heading {
+ @include border(bottom, 2, solid, $primary);
+ @include font(null, 12px, null);
+ @include line-height(16px);
+ @include flexbox(block, null, null, null, null, null);
+ cursor: default;
+ color: $primary;
+ }
+ }
+ a {
+ &.individual {
+ @include padding-value(12, 5, 12, 15);
+ color: $white;
+ }
+ i {
+ @include wh-value(30px, null);
+ }
+ &.parentlink::after {
+ content: "\f105";
+ @include font("Font Awesome 5 Free", null, 900);
+ @include position_value(absolute, 14px, 15px, null, null);
+ @include transition(all, 0.3s, ease, 0s);
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ }
+ }
+ .sidebar-submenu {
+ opacity: 0;
+ @include transition(opacity, 0.4s, ease-in-out, 0s);
+ li {
+ @include background(null, $secondary, null, null, null);
+ @include wh-value(null, 0);
+ @include transition(height, 200ms, ease-in, 0s);
+ overflow: hidden;
+ &:last-child {
+ @include roundedBottomLeftRadius(4);
+ @include roundedBottomRightRadius(4);
+ }
+ .link {
+ color: $gray-500;
+ }
+ &:hover,
+ &.active {
+ .link {
+ color: $white;
+ }
+ }
+ }
+ }
+ &.menu-open {
+ @include background(null, $primary, null, null, null);
+ a {
+ &::after {
+ @include rotate(90);
+ }
+ }
+ .sidebar-submenu {
+ opacity: 1;
+ li {
+ @include wh-value(null, 45px);
+ }
+ }
+ }
+ &.parentactive {
+ @include background(null, $primary, null, null, null);
+ .parentlink {
+ color: $white;
+ }
+ }
+ .parentlink,
+ .link {
+ @include padding-value(12, 5, 12, 15);
+ @include flexbox(flex, null, null, null, null, null);
+ }
+ }
+ }
+ }
+ &.sidebar-collapse {
+ @include background(null, transparent, null, null, null);
+ nav {
+ transform: translate(0, 0);
+ @include wh-value($minimize-left, null);
+ ul {
+ &.scrollable-menu {
+ li {
+ a {
+ span {
+ @include position_value(null, 0, null, null, null);
+ @include padding-value(12, 5, 12, 20);
+ }
+ &.individual {
+ span {
+ @include roundedBottomRightRadius(4);
+ }
+ }
+ &.parentlink,
+ &.individual {
+ span {
+ @include background(null, $primary, null, null, null);
+ @include roundedTopRightRadius(4);
+ }
+ }
+ }
+ &:hover {
+ .sidebar-submenu {
+ li {
+ @include wh-value(null, 45px);
+ }
+ }
+ .sidebar-submenu,
+ a span {
+ @include flexbox(block !important, null, null, null, null, null);
+ @include position_value(absolute, null, null, null, $minimize-left);
+ @include wh-value(220px, null);
+ opacity: 1;
+ }
+ }
+ &.header-menu,
+ .sidebar-submenu {
+ @include flexbox(none !important, null, null, null, null, null);
+ transform: translateZ(0);
+ }
+ }
+ }
+ li {
+ a::after,
+ span {
+ @include flexbox(none !important, null, null, null, null, null);
+ transform: translateZ(0);
+ }
+ }
+ }
+ }
+ }
+ &.sidebar-open {
+ @include margin-value(0, 0, 0, $active-margin-left);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+
+/**
+ * @file Sidebar Component
+ */
+import { Component, Injector, OnInit } from '@angular/core';
+import { DeviceCheckService } from 'DeviceCheckService';
+import { MENU_ITEMS, MENUITEMS } from 'src/models/MenuModel';
+import { isNullOrUndefined } from 'util';
+
+/**
+ * Creating component
+ * @Component takes SidebarComponent.html as template url
+ */
+@Component({
+ selector: 'app-sidebar',
+ templateUrl: './SidebarComponent.html',
+ styleUrls: ['./SidebarComponent.scss']
+})
+/** Exporting a class @exports SidebarComponent */
+export class SidebarComponent implements OnInit {
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** submenu router endpoints @public */
+ public routerEndpoint: string;
+
+ /** submenu router endpoints @public */
+ public getMenus: MENUITEMS[];
+
+ /** selected Menu @public */
+ public selectedItem: string;
+
+ /** get the classlist @public */
+ public elementCheck: HTMLCollection;
+
+ /** Apply active class for Desktop @public */
+ public classAppliedForDesktop: boolean = false;
+
+ /** Apply active class for mobile @public */
+ public classAppliedForMobile: boolean = false;
+
+ /** Device Check service @public */
+ public deviceCheckService: DeviceCheckService;
+
+ /** Check for the mobile @public */
+ public isMobile$: boolean;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.deviceCheckService = this.injector.get(DeviceCheckService);
+ this.getMenus = MENU_ITEMS;
+ }
+
+ /** Lifecyle Hooks the trigger before component is instantiate @public */
+ public ngOnInit(): void {
+ this.deviceCheckService.checkDeviceType();
+ this.deviceCheckService.isMobile.subscribe((checkIsMobile: boolean) => {
+ this.isMobile$ = checkIsMobile;
+ this.getDeviceType();
+ });
+ }
+ /** method to open sideBarOpen in all the views */
+ public sideBarOpenClose(): void {
+ if (this.isMobile$) {
+ this.classAppliedForMobile = !this.classAppliedForMobile;
+ } else {
+ this.classAppliedForDesktop = !this.classAppliedForDesktop;
+ }
+ this.addClassMainWrapper();
+ }
+ /** Add class for mobile/Desktop in main-wrapper @public */
+ public addClassMainWrapper(): void {
+ const elementMain: HTMLElement = document.querySelector('#main-wrapper');
+ if (!isNullOrUndefined(elementMain)) {
+ if (this.isMobile$) {
+ elementMain.classList.toggle('sidebar-mobile');
+ } else {
+ elementMain.classList.toggle('sidebar-desktop');
+ }
+ }
+ }
+ /** Return the Device type @public */
+ public getDeviceType(): void {
+ if (this.isMobile$) {
+ this.classAppliedForMobile = true;
+ this.classAppliedForDesktop = false;
+ } else {
+ this.classAppliedForMobile = false;
+ this.classAppliedForDesktop = false;
+ }
+ this.addClassMainWrapper();
+ }
+ /** Set the SideBar Menus click function @public */
+ public handleMenuFunction(index: number, method: string, className: string, childExists: boolean): void {
+ this.selectedItem = method;
+ if (!isNullOrUndefined(method)) {
+ this.parentactiveClassAddRemove(index, method, className, childExists);
+ }
+ }
+ /** Removing the parentactive class which is already present and add it to current @public */
+ public parentactiveClassAddRemove(index: number, method: string, className: string, childExists: boolean): void {
+ const element: HTMLElement = document.querySelector('#' + method + '' + index);
+ const checkOpenedelement: boolean = element.classList.contains(className);
+ if (!checkOpenedelement) {
+ this.elementCheck = document.getElementsByClassName(className);
+ if (this.elementCheck.length > 0) {
+ this.removeClasses(className);
+ }
+ }
+ if (method !== 'nosubmenu') {
+ element.classList.toggle(className);
+ }
+ if (this.isMobile$ && !childExists) {
+ this.checkAndCloseSideBar(childExists);
+ }
+ }
+ /** Hide / Show Menus based on the clicking in the menus @public */
+ public checkAndCloseSideBar(childExists: boolean): void {
+ event.stopPropagation();
+ if (this.isMobile$ && !childExists) {
+ this.sideBarOpenClose();
+ }
+ }
+ /** remove existing Class @public */
+ public removeClasses(className: string): void {
+ this.elementCheck[0].classList.remove(className);
+ if (this.elementCheck[0]) {
+ this.removeClasses(className);
+ }
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="login-container">
+ <div class="wrap-login">
+ <div class="login-logo">
+ <img src="assets/images/logo.png" alt="Logo">
+ </div>
+ <form [formGroup]="loginForm" (ngSubmit)="onSubmit()" class="login-form" autocomplete="off">
+ <div class="wrap-input">
+ <input autocomplete="off" class="input-control" type="text" formControlName="userName" placeholder="{{ 'PAGE.LOGIN.USERNAME' | translate }}"
+ />
+ <span class="input-icon">
+ <i class="fa fa-user" aria-hidden="true"></i>
+ </span>
+ </div>
+ <div *ngIf="submitted && loginForm.controls['userName'].errors" class="input-validation-msg">
+ <div *ngIf="loginForm.controls['userName'].errors.required">{{'PAGE.LOGIN.USERNAMEVALIDMESSAGE' | translate}}</div>
+ </div>
+ <div class="wrap-input">
+ <input autocomplete="off" class="input-control" type="password" formControlName="password" placeholder="{{ 'PAGE.LOGIN.PASSWORD' | translate }}"
+ />
+ <span class="input-icon">
+ <i class="fa fa-lock" aria-hidden="true"></i>
+ </span>
+ </div>
+ <div *ngIf="submitted && loginForm.controls['password'].errors" class="input-validation-msg">
+ <div *ngIf="loginForm.controls['password'].errors.required">{{'PAGE.LOGIN.PASSWORDVALIDMESSAGE' | translate}}</div>
+ </div>
+ <button type="submit" class="submit-btn">
+ <i class="fa fa-arrow-right" aria-hidden="true"></i>
+ </button>
+ <div class="signup-text-center">
+ <span class="caret">{{'PAGE.LOGIN.SIGNINMSG' | translate}}</span>
+ </div>
+
+ </form>
+ </div>
+</div>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
+<div class="login-footer">
+ <a href="https://osm.etsi.org" target="_blank">{{'OSMSOURCEMANO' | translate}} {{sharedService.osmVersion}}</a>
+</div>
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+@import "../../assets/scss/mixins/mixin";
+@import "../../assets/scss/variable";
+
+.login-container {
+ @include wh-value(100%, 100vh);
+ @include flexbox(flex, center, null, null, center, null);
+ @include background(url("../../assets/images/login_background.jpg"), null, cover, no-repeat, center);
+ background-attachment: fixed;
+ flex-wrap: wrap;
+ .wrap-login {
+ @include background(
+ linear-gradient(
+ to left bottom,
+ #00c0ef,
+ #00b3f9,
+ #3ea3fd,
+ #7190f8,
+ #9c78e8,
+ #a86cdd,
+ #b25fd1,
+ #bb51c3,
+ #b151c4,
+ #a652c6,
+ #9b53c6,
+ #9053c7
+ ),
+ null,
+ null,
+ null,
+ null
+ );
+ @include roundedCorners(15);
+ @include flexbox(flex, space-between, null, null, null, null);
+ @include position_value(relative, null, null, null, null);
+ @include box-shadow(0px, 3px, 10px, 0px, rgba($black, 0.5));
+ @include padding-value(20, 30, 20, 30);
+ flex-wrap: wrap;
+ color: $white;
+ overflow: visible;
+ .login-logo {
+ @include flexbox(flex, center, null, null, center, null);
+ @include position_value(absolute, -80px, null, null, 95px);
+ @include box-shadow(1px, 2px, 0px, 0px, $cerise-pink);
+ @include margin-value(0, 0, 10, 0);
+ @include wh-value(160px, 150px);
+ @include background(null, $white, null, null, null);
+ @include roundedCornersPercentage(50%);
+ img {
+ @include wh-value(130px, auto);
+ @include position_value(null, 50px, null, null, null);
+ }
+ }
+ .login-form {
+ @include wh-value(290px, null);
+ @include padding-value(70, 0, 0, 0);
+ text-align: center;
+ .wrap-input {
+ @include position_value(relative, null, null, null, null);
+ @include wh-value(100%, null);
+ @include margin-value(0, 0, 10, 0);
+ z-index: 1;
+ .input-control {
+ @include font(null, 15px, null);
+ @include line-height(1.5);
+ @include wh-value(100%, 42px);
+ @include padding-value(0, 30, 0, 65);
+ @include flexbox(block, null, null, null, null, null);
+ @include roundedCorners(25);
+ @include border(all, 0, solid, $gray-80);
+ @include background(null, $white, null, null, null);
+ &:focus + .input-icon {
+ color: $cerise-pink;
+ @include padding-value(0, 0, 0, 25);
+ }
+ }
+ .input-icon {
+ @include font(null, 13px, null);
+ @include flexbox(flex, null, null, null, center, null);
+ @include position_value(absolute, null, null, 0, 0);
+ @include wh-value(100%, 100%);
+ @include padding-value(0, 0, 0, 35);
+ @include roundedCorners(25);
+ @include transition(all, 0.5s, null, null);
+ pointer-events: none;
+ color: $gray-600;
+ }
+ }
+ .submit-btn {
+ @include background(null, $white, null, null, null);
+ @include roundedCornersPercentage(50%);
+ @include border(all, 0, solid, $gray-80);
+ @include transition(all, 0.3s, null, null);
+ @include box-shadow(1px, 5px, 5px, 0px, rgba($black, 0.3), inset);
+ cursor: pointer;
+ @include font(null, 25px, null);
+ @include wh-value(60px, 60px);
+ @include margin-value(0, 0, 10, 0);
+ @include padding-value(0, 0, 0, 0);
+ color: $cerise-pink;
+ &:hover {
+ @include box-shadow(1px, 5px, 10px, 0px, rgba($black, 0.3));
+ }
+ .fa {
+ @include transition(all, 0.4s, null, null);
+ @include flexbox(block, null, null, null, null, null);
+ @include padding-value(18, 18, 18, 18);
+ &:hover {
+ transform: scale(1.2);
+ }
+ }
+ }
+ .input-validation-msg {
+ @include roundedCorners(25);
+ @include background(null, $cerise-pink, null, null, null);
+ @include margin-value(0, 0, 10, 0);
+ @include padding-value(1, 0, 1, 15);
+ @include font(null, 11px, null);
+ color: $white;
+ text-align: left;
+ }
+ }
+ }
+}
+.login-footer {
+ @include flexbox(flex, space-between, null, null, center, null);
+ @include position_value(fixed, null, null, 0px, null);
+ @include background(null, $purple, null, null, null);
+ @include wh-value(100%, 40px);
+ @include padding-value(0, 10, 0, 10);
+ color: $white;
+ opacity: 0.9;
+ a {
+ @include font(null, null, bold);
+ color: $white;
+ &:hover {
+ text-decoration: underline;
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+
+/**
+ * @file Page for Login component
+ */
+import { HttpErrorResponse } from '@angular/common/http';
+import { Component, Injector, OnInit } from '@angular/core';
+import { FormBuilder, FormGroup, Validators } from '@angular/forms';
+import { Router } from '@angular/router';
+import { AuthenticationService } from 'AuthenticationService';
+import { RestService } from 'RestService';
+import { Observable } from 'rxjs';
+import { SharedService } from 'SharedService';
+import { isNullOrUndefined } from 'util';
+
+/**
+ * Creating component
+ * @Component takes LoginComponent.html as template url
+ */
+@Component({
+ selector: 'app-login',
+ templateUrl: './LoginComponent.html',
+ styleUrls: ['./LoginComponent.scss']
+})
+/** Exporting a class @exports LoginComponent */
+export class LoginComponent implements OnInit {
+ /** Invoke service injectors @public */
+ public injector: Injector;
+
+ /** contains loginform group information @public */
+ public loginForm: FormGroup;
+
+ /** submitted set to boolean state @public */
+ public submitted: boolean = false;
+
+ /** contains return URL link @public */
+ public returnUrl: string;
+
+ /** Observable Hold the value of subscription @public */
+ public isLoggedIn$: Observable<boolean>;
+
+ /** contains access token information @public */
+ public accessToken: string;
+
+ /** Utilizes rest service for any CRUD operations @public */
+ public restService: RestService;
+
+ /** Check the loading results @public */
+ public isLoadingResults: boolean = false;
+
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+
+ /** Contains all methods related to shared @public */
+ public sharedService: SharedService;
+
+ /** Utilizes auth service for any auth operations @private */
+ private authService: AuthenticationService;
+
+ /** contians form builder module @private */
+ private formBuilder: FormBuilder;
+
+ /** Holds teh instance of AuthService class of type AuthService @private */
+ private router: Router;
+
+ // creates instance of login component
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.restService = this.injector.get(RestService);
+ this.authService = this.injector.get(AuthenticationService);
+ this.formBuilder = this.injector.get(FormBuilder);
+ this.router = this.injector.get(Router);
+ this.sharedService = this.injector.get(SharedService);
+ }
+
+ /**
+ * Lifecyle Hooks the trigger before component is instantiate
+ */
+ public ngOnInit(): void {
+ this.isLoggedIn$ = this.authService.isLoggedIn;
+ if (this.isLoggedIn$) {
+ this.router.navigate(['/']).catch(() => {
+ // Catch Navigation Error
+ });
+ }
+ this.loginForm = this.formBuilder.group({
+ userName: ['', [Validators.required]],
+ password: ['', [Validators.required]]
+ });
+ this.returnUrl = isNullOrUndefined(localStorage.getItem('returnUrl')) ? '/' : localStorage.getItem('returnUrl');
+ }
+
+ /**
+ * called on form submit @private onSubmit
+ */
+ public onSubmit(): void {
+ this.submitted = true;
+ if (this.loginForm.invalid) {
+ return;
+ }
+ this.isLoadingResults = true;
+ this.sharedService.cleanForm(this.loginForm);
+ this.authService.login(this.loginForm.value.userName, this.loginForm.value.password).subscribe(
+ (data: {}) => {
+ this.isLoadingResults = false;
+ this.router.navigate([this.returnUrl]).catch(() => {
+ // Catch Navigation Error
+ });
+ localStorage.removeItem('returnUrl');
+ }, (err: HttpErrorResponse) => {
+ this.isLoadingResults = false;
+ this.restService.handleError(err, 'post');
+ });
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<router-outlet></router-outlet>
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file Packages-Component.ts.
+ */
+import { Component, Injector } from '@angular/core';
+import { Router, RouterEvent } from '@angular/router';
+/**
+ * Creating Component
+ * @Component takes PackagesComponent.html as template url
+ */
+@Component({
+ selector: 'app-packages',
+ templateUrl: './PackagesComponent.html',
+ styleUrls: ['./PackagesComponent.scss']
+})
+/** Exporting a class @exports PackagesComponent */
+export class PackagesComponent{
+ /** Invoke service injectors @public */
+ public injector: Injector;
+
+ /** Holds teh instance of AuthService class of type AuthService @private */
+ private router: Router;
+
+ // creates packages component
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.router = this.injector.get(Router);
+ this.router.events.subscribe((event: RouterEvent) => {
+ this.redirectToList(event.url);
+ });
+ }
+
+ /** Return to list NS Package List */
+ public redirectToList(getURL: string): void {
+ if (getURL === '/packages') {
+ this.router.navigate(['/packages/ns']).catch();
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file Packages Module.
+ */
+import { CommonModule } from '@angular/common';
+import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
+import { ReactiveFormsModule } from '@angular/forms';
+import { FormsModule } from '@angular/forms';
+import { RouterModule, Routes } from '@angular/router';
+import { CodemirrorModule } from '@ctrl/ngx-codemirror';
+import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
+import { NgSelectModule } from '@ng-select/ng-select';
+import { TranslateModule } from '@ngx-translate/core';
+import { ClonePackageComponent } from 'ClonePackage';
+import { DataService } from 'DataService';
+import { DragDirective } from 'DragDirective';
+import { EditPackagesComponent } from 'EditPackagesComponent';
+import { LoaderModule } from 'LoaderModule';
+import { NetsliceTemplateComponent } from 'NetsliceTemplate';
+import { SidebarModule } from 'ng-sidebar';
+import { Ng2SmartTableModule } from 'ng2-smart-table';
+import { NSComposerComponent } from 'NSComposer';
+import { NSPackagesComponent } from 'NSPackages';
+import { PackagesComponent } from 'Packages';
+import { PagePerRowModule } from 'PagePerRowModule';
+import { PageReloadModule } from 'PageReloadModule';
+import { ShowContentComponent } from 'ShowContent';
+import { VNFComposerComponent } from 'VNFComposer';
+import { VNFPackagesComponent } from 'VNFPackages';
+
+/** To halndle project information */
+const projectInfo: {} = { title: '{project}', url: '/' };
+
+/**
+ * configures routers
+ */
+const routes: Routes = [
+ {
+ path: '',
+ component: PackagesComponent,
+ children: [
+ {
+ path: 'ns',
+ data: {
+ breadcrumb: [{ title: 'PAGE.DASHBOARD.DASHBOARD', url: '/' }, { title: 'PAGE.DASHBOARD.PROJECTS', url: '/projects' },
+ projectInfo, { title: 'NSPACKAGES', url: null }]
+ },
+ component: NSPackagesComponent
+ },
+ {
+ path: 'vnf',
+ data: {
+ breadcrumb: [{ title: 'PAGE.DASHBOARD.DASHBOARD', url: '/' }, { title: 'PAGE.DASHBOARD.PROJECTS', url: '/projects' },
+ projectInfo, { title: 'VNFPACKAGES', url: null }]
+ },
+ component: VNFPackagesComponent
+ },
+ {
+ path: 'netslice',
+ data: {
+ breadcrumb: [{ title: 'PAGE.DASHBOARD.DASHBOARD', url: '/' }, { title: 'PAGE.DASHBOARD.PROJECTS', url: '/projects' }
+ , projectInfo, { title: 'PAGE.DASHBOARD.NETSLICETEMPLATE', url: null }]
+ },
+ component: NetsliceTemplateComponent
+ },
+ {
+ path: ':type/edit/:id',
+ data: {
+ breadcrumb: [{ title: 'PAGE.DASHBOARD.DASHBOARD', url: '/' }, { title: 'PAGE.DASHBOARD.PROJECTS', url: '/projects' }
+ , projectInfo, { title: '{type}', url: '/packages/{type}' }, { title: '{id}', url: null }]
+ },
+ component: EditPackagesComponent
+ },
+ {
+ path: 'ns/compose/:id',
+ data: {
+ breadcrumb: [{ title: 'PAGE.DASHBOARD.DASHBOARD', url: '/' }, { title: 'PAGE.DASHBOARD.PROJECTS', url: '/projects' }
+ , projectInfo, { title: 'NSPACKAGES', url: '/packages/ns' }, { title: '{id}', url: null }]
+ },
+ component: NSComposerComponent
+ },
+ {
+ path: 'vnf/compose/:id',
+ data: {
+ breadcrumb: [{ title: 'PAGE.DASHBOARD.DASHBOARD', url: '/' }, { title: 'PAGE.DASHBOARD.PROJECTS', url: '/projects' },
+ projectInfo, { title: 'VNFPACKAGES', url: '/packages/vnf' }, { title: '{id}', url: null }]
+ },
+ component: VNFComposerComponent
+ }
+ ]
+ }
+];
+
+/**
+ * Creating @NgModule component for Modules
+ */
+@NgModule({
+ imports: [ReactiveFormsModule.withConfig({ warnOnNgModelWithFormControl: 'never' }), FormsModule, CommonModule, Ng2SmartTableModule,
+ CodemirrorModule, TranslateModule, RouterModule.forChild(routes), NgbModule, NgSelectModule,
+ PagePerRowModule, SidebarModule.forRoot(), LoaderModule, PageReloadModule],
+ declarations: [PackagesComponent, NSPackagesComponent, VNFPackagesComponent, NetsliceTemplateComponent,
+ DragDirective, ShowContentComponent, NSComposerComponent, VNFComposerComponent, EditPackagesComponent, ClonePackageComponent],
+ providers: [DataService],
+ schemas: [CUSTOM_ELEMENTS_SCHEMA],
+ entryComponents: [ShowContentComponent, ClonePackageComponent]
+})
+/** Exporting a class @exports PackagesModule */
+export class PackagesModule {
+ /** Variables declared to avoid state-less class */
+ private packagesModule: string;
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<form [formGroup]="netSliceInstantiateForm" (ngSubmit)="instantiateNSTSubmit()">
+ <div class="modal-header">
+ <h4 class="modal-title" id="modal-basic-title">{{'NEW' | translate}} NSI</h4>
+ <button class="button-xs" type="button" class="close" aria-label="Close" (click)="activeModal.close()">
+ <i class="fas fa-times-circle text-danger"></i>
+ </button>
+ </div>
+ <div class="modal-body modal-body-custom-height netsliceinstantiate-ns">
+ <div class="form-group row">
+ <label class="col-sm-12 col-form-label mandatory-label"
+ [ngClass]="{'text-danger': netSliceInstantiateForm.invalid === true && submitted === true}">{{'MANDATORYCHECK' | translate}}</label>
+ <label class="col-sm-4 col-form-label" for="nsiName">{{'PAGE.NSTINSTANCEINSTANTIATE.NSNAME' | translate}}*</label>
+ <div class="col-sm-8">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.NSTINSTANCEINSTANTIATE.NSNAME' | translate}}" type="text" formControlName="nsiName"
+ id="nsiName" [ngClass]="{ 'is-invalid': submitted && f.nsiName.errors }" required>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label"
+ for="nsiDescription">{{'PAGE.NSTINSTANCEINSTANTIATE.DESCRIPTION' | translate}}*</label>
+ <div class="col-sm-8">
+ <textarea class="form-control" placeholder="{{'PAGE.NSTINSTANCEINSTANTIATE.DESCRIPTION' | translate}}"
+ type="text" formControlName="nsiDescription" id="nsiDescription"
+ [ngClass]="{ 'is-invalid': submitted && f.nsiDescription.errors }" required></textarea>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label" for="nstId">{{'PAGE.NSTINSTANCEINSTANTIATE.NSTID' | translate}}*</label>
+ <div class="col-sm-8">
+ <ng-select [items]="netSliceSelect" bindLabel="name" bindValue="_id"
+ placeholder="{{'SELECT' | translate}} {{'PAGE.NSTINSTANCEINSTANTIATE.NSTID' | translate}}"
+ formControlName="nstId" [(ngModel)]="netsliceNstId" id="nstId"
+ [ngClass]="{ 'is-invalid': submitted && f.nstId.errors }" required>
+ </ng-select>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label"
+ for="vimAccountId">{{'PAGE.NSTINSTANCEINSTANTIATE.VIMACCOUNT' | translate}}*</label>
+ <div class="col-sm-8">
+ <ng-select [items]="vimDetailsSelect" bindLabel="name" bindValue="_id"
+ placeholder="{{'SELECT' | translate}} {{'PAGE.NSTINSTANCEINSTANTIATE.VIMACCOUNT' | translate}}"
+ formControlName="vimAccountId" [(ngModel)]="vimAccountId" id="vimAccountId"
+ [ngClass]="{ 'is-invalid': submitted && f.vimAccountId.errors }" required>
+ </ng-select>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label" for="ssh_keys">{{'PAGE.NSTINSTANCEINSTANTIATE.SSHKEY' | translate}}</label>
+ <div class="col-sm-8">
+ <textarea class="form-control" placeholder="{{'PAGE.NSTINSTANCEINSTANTIATE.SSHKEYMSG' | translate}}"
+ formControlName="ssh_keys" id="ssh_keys"></textarea>
+ <div class="fileupload-text mt-1 mb-1">{{'FILEUPLOADLABEL' | translate}}</div>
+ <div class="custom-file">
+ <input type="file" #fileInputSSH class="custom-file-input" (change)="sshFile($event.target.files)"
+ id="customSSHFile">
+ <label class="custom-file-label" #fileInputSSHLabel for="customSSHFile">{{'CHOOSEFILE' | translate}}</label>
+ </div>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label" for="config">{{'CONFIG' | translate}}</label>
+ <div class="col-sm-8">
+ <textarea class="form-control" placeholder="{{'YAMLCONFIG' | translate}}" formControlName="config"
+ id="config"></textarea>
+ <div class="fileupload-text mt-1 mb-1">{{'FILEUPLOADLABEL' | translate}}</div>
+ <div class="custom-file">
+ <input type="file" #fileInputConfig class="custom-file-input" (change)="configFile($event.target.files)"
+ id="customConfigFile">
+ <label class="custom-file-label" #fileInputConfigLabel for="customConfigFile">{{'CHOOSEFILE' | translate}}</label>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-danger" (click)="activeModal.close()">{{'CANCEL' | translate}}</button>
+ <button type="submit" class="btn btn-primary">{{'CREATE' | translate}}</button>
+ </div>
+</form>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @file Instantiate NS Modal Component.
+ */
+import { HttpHeaders } from '@angular/common/http';
+import { Component, ElementRef, Injector, OnInit, ViewChild } from '@angular/core';
+import { FormBuilder, FormGroup, Validators } from '@angular/forms';
+import { Router } from '@angular/router';
+import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateService } from '@ngx-translate/core';
+import { NotifierService } from 'angular-notifier';
+import { APIURLHEADER, ERRORDATA, MODALCLOSERESPONSEDATA } from 'CommonModel';
+import { DataService } from 'DataService';
+import { environment } from 'environment';
+import * as jsyaml from 'js-yaml';
+import { NetworkSliceData } from 'NetworkSliceModel';
+import { NSICREATEPARAMS } from 'NSDModel';
+import { RestService } from 'RestService';
+import { SharedService } from 'SharedService';
+import { isNullOrUndefined } from 'util';
+import { VimAccountDetails } from 'VimAccountModel';
+/**
+ * Creating component
+ * @Component takes InstantiateNetSliceTemplateComponent.html as template url
+ */
+@Component({
+ selector: 'app-instantiate-net-slice-template',
+ templateUrl: './InstantiateNetSliceTemplateComponent.html',
+ styleUrls: ['./InstantiateNetSliceTemplateComponent.scss']
+})
+/** Exporting a class @exports InstantiateNetSliceTemplateComponent */
+export class InstantiateNetSliceTemplateComponent implements OnInit {
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** FormGroup instance added to the form @ html @public */
+ public netSliceInstantiateForm: FormGroup;
+
+ /** Instance for active modal service @public */
+ public activeModal: NgbActiveModal;
+
+ /** Variable set for twoway bindng @public */
+ public vimAccountId: string;
+
+ /** Contains all the net slice data collections */
+ public netSliceSelect: NetworkSliceData;
+
+ /** Contains all the VIM data collections */
+ public vimDetailsSelect: VimAccountDetails;
+
+ /** Variable set for twoway binding @public */
+ public netsliceNstId: string;
+
+ /** Form submission Add */
+ public submitted: boolean = false;
+
+ /** Check the loading results for loader status @public */
+ public isLoadingResults: boolean = false;
+
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+
+ /** Element ref for fileInputConfig @public */
+ @ViewChild('fileInputConfig', { static: true }) public fileInputConfig: ElementRef;
+
+ /** Element ref for fileInputConfigLabel @public */
+ @ViewChild('fileInputConfigLabel', { static: true }) public fileInputConfigLabel: ElementRef;
+
+ /** Element ref for fileInputSSH @public */
+ @ViewChild('fileInputSSH', { static: true }) public fileInputSSH: ElementRef;
+
+ /** Element ref for fileInputSSHLabel @public */
+ @ViewChild('fileInputSSHLabel', { static: true }) public fileInputSSHLabel: ElementRef;
+
+ /** Holds teh instance of AuthService class of type AuthService @private */
+ private router: Router;
+
+ /** FormBuilder instance added to the formBuilder @private */
+ private formBuilder: FormBuilder;
+
+ /** Utilizes rest service for any CRUD operations @private */
+ private restService: RestService;
+
+ /** Utilizes data service for any communication @private */
+ private dataService: DataService;
+
+ /** Controls the header form @private */
+ private headers: HttpHeaders;
+
+ /** Notifier service to popup notification @private */
+ private notifierService: NotifierService;
+
+ /** Contains tranlsate instance @private */
+ private translateService: TranslateService;
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ /** Contains the ssh key to be hosted in dom @private */
+ private copySSHKey: string;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.restService = this.injector.get(RestService);
+ this.activeModal = this.injector.get(NgbActiveModal);
+ this.formBuilder = this.injector.get(FormBuilder);
+ this.dataService = this.injector.get(DataService);
+ this.notifierService = this.injector.get(NotifierService);
+ this.router = this.injector.get(Router);
+ this.translateService = this.injector.get(TranslateService);
+ this.sharedService = this.injector.get(SharedService);
+ }
+
+ /** Lifecyle Hooks the trigger before component is instantiate @public */
+ public ngOnInit(): void {
+ /** Setting up initial value for NSD */
+ this.netsliceNstId = '';
+ this.dataService.currentMessage.subscribe((event: NetworkSliceData) => {
+ if (event.identifier !== undefined || event.identifier !== '' || event.identifier !== null) {
+ this.netsliceNstId = event.identifier;
+ }
+ });
+ this.netSliceInstantiateFormAction();
+ this.headers = new HttpHeaders({
+ 'Content-Type': 'application/json',
+ Accept: 'application/json',
+ 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
+ });
+ /** On Initializing call the methods */
+ this.getNetSliceDetails();
+ this.getVIMDetails();
+ }
+
+ /** Call the netSlice details in the selection options @public */
+ public getNetSliceDetails(): void {
+ this.restService.getResource(environment.NETWORKSLICETEMPLATECONTENT_URL).subscribe((netSlicePackages: NetworkSliceData) => {
+ this.netSliceSelect = netSlicePackages;
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'get');
+ });
+ }
+
+ /** Call the VIM details in the selection options @public */
+ public getVIMDetails(): void {
+ this.restService.getResource(environment.VIMACCOUNTS_URL).subscribe((vimDetails: VimAccountDetails) => {
+ this.vimDetailsSelect = vimDetails;
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'get');
+ });
+ }
+
+ /** On modal initializing forms @public */
+ public netSliceInstantiateFormAction(): void {
+ this.netSliceInstantiateForm = this.formBuilder.group({
+ nsiName: ['', [Validators.required]],
+ nsiDescription: ['', [Validators.required]],
+ nstId: ['', [Validators.required]],
+ vimAccountId: ['', [Validators.required]],
+ ssh_keys: [null],
+ config: [null]
+ });
+ }
+ /** convenience getter for easy access to form fields */
+ get f(): FormGroup['controls'] { return this.netSliceInstantiateForm.controls; }
+
+ /** On modal submit instantiateNsSubmit will called @public */
+ public instantiateNSTSubmit(): void {
+ this.submitted = true;
+ this.sharedService.cleanForm(this.netSliceInstantiateForm);
+ if (this.netSliceInstantiateForm.invalid) {
+ return;
+ }
+ const modalData: MODALCLOSERESPONSEDATA = {
+ message: 'Done'
+ };
+ if (isNullOrUndefined(this.netSliceInstantiateForm.value.ssh_keys) || this.netSliceInstantiateForm.value.ssh_keys === '') {
+ delete this.netSliceInstantiateForm.value.ssh_keys;
+ } else {
+ this.copySSHKey = JSON.parse(JSON.stringify(this.netSliceInstantiateForm.value.ssh_keys));
+ // tslint:disable-next-line: no-backbone-get-set-outside-model
+ this.netSliceInstantiateForm.get('ssh_keys').setValue(this.copySSHKey);
+ }
+ if (isNullOrUndefined(this.netSliceInstantiateForm.value.config) || this.netSliceInstantiateForm.value.config === '') {
+ delete this.netSliceInstantiateForm.value.config;
+ } else {
+ const validJSON: boolean = this.sharedService.checkJson(this.netSliceInstantiateForm.value.config);
+ if (validJSON) {
+ this.netSliceInstantiateForm.value.config = JSON.parse(this.netSliceInstantiateForm.value.config);
+ Object.keys(this.netSliceInstantiateForm.value.config).forEach((item: string) => {
+ this.netSliceInstantiateForm.value[item] = this.netSliceInstantiateForm.value.config[item];
+ });
+ delete this.netSliceInstantiateForm.value.config;
+ } else {
+ this.notifierService.notify('error', this.translateService.instant('INVALIDCONFIG'));
+ return;
+ }
+ }
+ this.isLoadingResults = true;
+ const apiURLHeader: APIURLHEADER = {
+ url: environment.NETWORKSLICEINSTANCESCONTENT_URL,
+ httpOptions: { headers: this.headers }
+ };
+ this.restService.postResource(apiURLHeader, this.netSliceInstantiateForm.value)
+ .subscribe((result: {}) => {
+ this.activeModal.close(modalData);
+ this.isLoadingResults = false;
+ this.notifierService.notify('success', this.netSliceInstantiateForm.value.nsiName +
+ this.translateService.instant('PAGE.NETSLICE.CREATEDSUCCESSFULLY'));
+ this.router.navigate(['/instances/netslice']).catch();
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'post');
+ if (!isNullOrUndefined(this.copySSHKey)) {
+ // tslint:disable-next-line: no-backbone-get-set-outside-model
+ this.netSliceInstantiateForm.get('ssh_keys').setValue(this.copySSHKey);
+ }
+ this.isLoadingResults = false;
+ });
+ }
+
+ /** ssh file process @private */
+ public sshFile(files: FileList): void {
+ if (files && files.length === 1) {
+ this.sharedService.getFileString(files, 'pub').then((fileContent: string): void => {
+ const getSSHJson: string = jsyaml.load(fileContent, { json: true });
+ // tslint:disable-next-line: no-backbone-get-set-outside-model
+ this.netSliceInstantiateForm.get('ssh_keys').setValue(getSSHJson);
+ }).catch((err: string): void => {
+ if (err === 'typeError') {
+ this.notifierService.notify('error', this.translateService.instant('PUBFILETYPEERRROR'));
+ } else {
+ this.notifierService.notify('error', this.translateService.instant('ERROR'));
+ }
+ this.fileInputSSHLabel.nativeElement.innerText = this.translateService.instant('CHOOSEFILE');
+ this.fileInputSSH.nativeElement.value = null;
+ });
+ } else if (files && files.length > 1) {
+ this.notifierService.notify('error', this.translateService.instant('DROPFILESVALIDATION'));
+ }
+ this.fileInputSSHLabel.nativeElement.innerText = files[0].name;
+ this.fileInputSSH.nativeElement.value = null;
+ }
+
+ /** Config file process @private */
+ public configFile(files: FileList): void {
+ if (files && files.length === 1) {
+ this.sharedService.getFileString(files, 'yaml').then((fileContent: string): void => {
+ const getConfigJson: string = jsyaml.load(fileContent, { json: true });
+ // tslint:disable-next-line: no-backbone-get-set-outside-model
+ this.netSliceInstantiateForm.get('config').setValue(JSON.stringify(getConfigJson));
+ }).catch((err: string): void => {
+ if (err === 'typeError') {
+ this.notifierService.notify('error', this.translateService.instant('YAMLFILETYPEERRROR'));
+ } else {
+ this.notifierService.notify('error', this.translateService.instant('ERROR'));
+ }
+ this.fileInputConfigLabel.nativeElement.innerText = this.translateService.instant('CHOOSEFILE');
+ this.fileInputConfig.nativeElement.value = null;
+ });
+ } else if (files && files.length > 1) {
+ this.notifierService.notify('error', this.translateService.instant('DROPFILESVALIDATION'));
+ }
+ this.fileInputConfigLabel.nativeElement.innerText = files[0].name;
+ this.fileInputConfig.nativeElement.value = null;
+ }
+
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<form [formGroup]="instantiateForm" (ngSubmit)="instantiateNsSubmit();">
+ <div class="modal-header">
+ <h4 class="modal-title" id="modal-basic-title">{{'PAGE.INSTANCEINSTANTIATE.NEWINSTANCE' | translate}}</h4>
+ <button class="button-xs" type="button" class="close" aria-label="Close" (click)="activeModal.close()">
+ <i class="fas fa-times-circle text-danger"></i>
+ </button>
+ </div>
+ <div class="modal-body modal-body-custom-height instantiate-ns">
+ <div class="form-group row">
+ <label class="col-sm-12 col-form-label mandatory-label"
+ [ngClass]="{'text-danger': instantiateForm.invalid === true && submitted === true}">{{'MANDATORYCHECK' | translate}}</label>
+ <label class="col-sm-4 col-form-label"
+ for="nsName">{{'PAGE.INSTANCEINSTANTIATE.NSNAME' | translate}}*</label>
+ <div class="col-sm-8">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.INSTANCEINSTANTIATE.NSNAME' | translate}}" type="text" formControlName="nsName"
+ id="nsName" (keydown.space)="$event.preventDefault();"
+ [ngClass]="{ 'is-invalid': submitted && f.nsName.errors }" required>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label"
+ for="nsDescription">{{'PAGE.INSTANCEINSTANTIATE.DESCRIPTION' | translate}}*</label>
+ <div class="col-sm-8">
+ <textarea class="form-control" placeholder="{{'PAGE.INSTANCEINSTANTIATE.DESCRIPTION' | translate}}"
+ type="text" formControlName="nsDescription" id="nsDescription"
+ [ngClass]="{ 'is-invalid': submitted && f.nsDescription.errors }" required></textarea>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label" for="nsdId">{{'PAGE.INSTANCEINSTANTIATE.NSID' | translate}}*</label>
+ <div class="col-sm-8">
+ <ng-select [items]="nsdSelect" bindLabel="name" bindValue="_id"
+ placeholder="{{'SELECT' | translate}} {{'PAGE.INSTANCEINSTANTIATE.NSID' | translate}}"
+ formControlName="nsdId" [(ngModel)]="nsdId" id="nsdId"
+ [ngClass]="{ 'is-invalid': submitted && f.nsdId.errors }" required>
+ </ng-select>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label"
+ for="vimAccountId">{{'PAGE.INSTANCEINSTANTIATE.VIMACCOUNT' | translate}}*</label>
+ <div class="col-sm-8">
+ <ng-select [items]="vimAccountSelect" bindLabel="name" bindValue="_id"
+ placeholder="{{'SELECT' | translate}} {{'PAGE.INSTANCEINSTANTIATE.VIMACCOUNT' | translate}}"
+ formControlName="vimAccountId" [(ngModel)]="vimAccountId" id="vimAccountId"
+ [ngClass]="{ 'is-invalid': submitted && f.vimAccountId.errors }" required>
+ </ng-select>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label"
+ for="ssh_keys">{{'PAGE.INSTANCEINSTANTIATE.SSHKEY' | translate}}</label>
+ <div class="col-sm-8">
+ <textarea class="form-control" placeholder="{{'PAGE.INSTANCEINSTANTIATE.SSHKEYMSG' | translate}}"
+ formControlName="ssh_keys" id="ssh_keys"></textarea>
+ <div class="fileupload-text mt-1 mb-1">{{'FILEUPLOADLABEL' | translate}}</div>
+ <div class="custom-file">
+ <input type="file" #fileInputSSH class="custom-file-input" (change)="sshFile($event.target.files)"
+ id="customSSHFile">
+ <label class="custom-file-label" #fileInputSSHLabel
+ for="customSSHFile">{{'CHOOSEFILE' | translate}}</label>
+ </div>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label" for="config">{{'CONFIG' | translate}}</label>
+ <div class="col-sm-8">
+ <textarea class="form-control" placeholder="{{'YAMLCONFIG' | translate}}" formControlName="config"
+ id="config"></textarea>
+ <div class="fileupload-text mt-1 mb-1">{{'FILEUPLOADLABEL' | translate}}</div>
+ <div class="custom-file">
+ <input type="file" #fileInputConfig class="custom-file-input"
+ (change)="configFile($event.target.files)" id="customConfigFile">
+ <label class="custom-file-label" #fileInputConfigLabel
+ for="customConfigFile">{{'CHOOSEFILE' | translate}}</label>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-danger" (click)="activeModal.close()">{{'CANCEL' | translate}}</button>
+ <button type="submit" class="btn btn-primary">{{'CREATE' | translate}}</button>
+ </div>
+</form>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file Instantiate NS Modal Component.
+ */
+import { Component, ElementRef, Injector, OnInit, ViewChild } from '@angular/core';
+import { FormBuilder, FormGroup, Validators } from '@angular/forms';
+import { Router } from '@angular/router';
+import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateService } from '@ngx-translate/core';
+import { NotifierService } from 'angular-notifier';
+import { APIURLHEADER, ERRORDATA, MODALCLOSERESPONSEDATA } from 'CommonModel';
+import { DataService } from 'DataService';
+import { environment } from 'environment';
+import * as jsyaml from 'js-yaml';
+import { NSCREATEPARAMS, NSData, NSDDetails } from 'NSDModel';
+import { RestService } from 'RestService';
+import { SharedService } from 'SharedService';
+import { isNullOrUndefined } from 'util';
+import { VimAccountDetails } from 'VimAccountModel';
+
+/**
+ * Creating component
+ * @Component takes InstantiateNsComponent.html as template url
+ */
+@Component({
+ selector: 'app-instantiate-ns',
+ templateUrl: './InstantiateNsComponent.html',
+ styleUrls: ['./InstantiateNsComponent.scss']
+})
+/** Exporting a class @exports InstantiateNsComponent */
+export class InstantiateNsComponent implements OnInit {
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** Contains all the nsd data collections */
+ public nsdSelect: NSDDetails;
+
+ /** FormGroup instance added to the form @ html @public */
+ public instantiateForm: FormGroup;
+
+ /** Contains all vim account collections */
+ public vimAccountSelect: VimAccountDetails;
+
+ /** Instance for active modal service @public */
+ public activeModal: NgbActiveModal;
+
+ /** Variable set for twoway binding @public */
+ public nsdId: string;
+
+ /** Variable set for twoway bindng @public */
+ public vimAccountId: string;
+
+ /** Form submission Add */
+ public submitted: boolean = false;
+
+ /** Check the loading results @public */
+ public isLoadingResults: boolean = false;
+
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+
+ /** Element ref for fileInputConfig @public */
+ @ViewChild('fileInputConfig', { static: true }) public fileInputConfig: ElementRef;
+
+ /** Element ref for fileInputConfigLabel @public */
+ @ViewChild('fileInputConfigLabel', { static: true }) public fileInputConfigLabel: ElementRef;
+
+ /** Element ref for fileInputSSH @public */
+ @ViewChild('fileInputSSH', { static: true }) public fileInputSSH: ElementRef;
+
+ /** Element ref for fileInputSSHLabel @public */
+ @ViewChild('fileInputSSHLabel', { static: true }) public fileInputSSHLabel: ElementRef;
+
+ /** Holds teh instance of AuthService class of type AuthService @private */
+ private router: Router;
+
+ /** FormBuilder instance added to the formBuilder @private */
+ private formBuilder: FormBuilder;
+
+ /** Utilizes rest service for any CRUD operations @private */
+ private restService: RestService;
+
+ /** Utilizes data service for any communication @private */
+ private dataService: DataService;
+
+ /** Notifier service to popup notification @private */
+ private notifierService: NotifierService;
+
+ /** Contains tranlsate instance @private */
+ private translateService: TranslateService;
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ /** Contains the ssh key to be hosted in dom @private */
+ private copySSHKey: string;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.restService = this.injector.get(RestService);
+ this.activeModal = this.injector.get(NgbActiveModal);
+ this.formBuilder = this.injector.get(FormBuilder);
+ this.dataService = this.injector.get(DataService);
+ this.notifierService = this.injector.get(NotifierService);
+ this.router = this.injector.get(Router);
+ this.translateService = this.injector.get(TranslateService);
+ this.sharedService = this.injector.get(SharedService);
+ }
+
+ public ngOnInit(): void {
+ /** Setting up initial value for NSD */
+ this.dataService.currentMessage.subscribe((event: NSData) => {
+ if (event.identifier !== undefined || event.identifier !== '' || event.identifier !== null) {
+ this.nsdId = event.identifier;
+ }
+ });
+ /** On Initializing call the methods */
+ this.instantiateFormAction();
+ this.getDetailsnsd();
+ this.getDetailsvimAccount();
+ }
+
+ /** On modal initializing forms @public */
+ public instantiateFormAction(): void {
+ this.instantiateForm = this.formBuilder.group({
+ nsName: ['', [Validators.required]],
+ nsDescription: ['', [Validators.required]],
+ nsdId: ['', [Validators.required]],
+ vimAccountId: ['', [Validators.required]],
+ ssh_keys: [null],
+ config: [null]
+ });
+ }
+
+ /** Convenience getter for easy access to form fields */
+ get f(): FormGroup['controls'] { return this.instantiateForm.controls; }
+
+ /** Call the nsd details in the selection options @public */
+ public getDetailsnsd(): void {
+ this.restService.getResource(environment.NSDESCRIPTORSCONTENT_URL).subscribe((nsPackages: NSDDetails) => {
+ this.nsdSelect = nsPackages;
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'get');
+ });
+ }
+
+ /** Call the vimAccount details in the selection options @public */
+ public getDetailsvimAccount(): void {
+ this.restService.getResource(environment.VIMACCOUNTS_URL).subscribe((vimAccounts: VimAccountDetails) => {
+ this.vimAccountSelect = vimAccounts;
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'get');
+ });
+ }
+
+ /** On modal submit instantiateNsSubmit will called @public */
+ public instantiateNsSubmit(): void {
+ this.submitted = true;
+ this.sharedService.cleanForm(this.instantiateForm);
+ if (this.instantiateForm.invalid) {
+ return;
+ }
+ const modalData: MODALCLOSERESPONSEDATA = {
+ message: 'Done'
+ };
+ if (isNullOrUndefined(this.instantiateForm.value.ssh_keys) || this.instantiateForm.value.ssh_keys === '') {
+ delete this.instantiateForm.value.ssh_keys;
+ } else {
+ this.copySSHKey = JSON.parse(JSON.stringify(this.instantiateForm.value.ssh_keys));
+ // tslint:disable-next-line: no-backbone-get-set-outside-model
+ this.instantiateForm.get('ssh_keys').setValue([this.copySSHKey]);
+ }
+ if (isNullOrUndefined(this.instantiateForm.value.config) || this.instantiateForm.value.config === '') {
+ delete this.instantiateForm.value.config;
+ } else {
+ const validJSON: boolean = this.sharedService.checkJson(this.instantiateForm.value.config);
+ if (validJSON) {
+ this.instantiateForm.value.config = JSON.parse(this.instantiateForm.value.config);
+ Object.keys(this.instantiateForm.value.config).forEach((item: string) => {
+ this.instantiateForm.value[item] = this.instantiateForm.value.config[item];
+ });
+ delete this.instantiateForm.value.config;
+ } else {
+ this.notifierService.notify('error', this.translateService.instant('INVALIDCONFIG'));
+ return;
+ }
+ }
+ const apiURLHeader: APIURLHEADER = {
+ url: environment.NSINSTANCESCONTENT_URL
+ };
+ this.isLoadingResults = true;
+ this.restService.postResource(apiURLHeader, this.instantiateForm.value).subscribe((result: {}) => {
+ this.activeModal.close(modalData);
+ this.notifierService.notify('success', this.instantiateForm.value.nsName +
+ this.translateService.instant('PAGE.NSINSTANCE.CREATEDSUCCESSFULLY'));
+ this.router.navigate(['/instances/ns']).catch();
+ }, (error: ERRORDATA) => {
+ this.isLoadingResults = false;
+ this.restService.handleError(error, 'post');
+ if (!isNullOrUndefined(this.copySSHKey)) {
+ // tslint:disable-next-line: no-backbone-get-set-outside-model
+ this.instantiateForm.get('ssh_keys').setValue(this.copySSHKey);
+ }
+ });
+ }
+
+ /** ssh file process @private */
+ public sshFile(files: FileList): void {
+ if (files && files.length === 1) {
+ this.sharedService.getFileString(files, 'pub').then((fileContent: string): void => {
+ const getSSHJson: string = jsyaml.load(fileContent, { json: true });
+ // tslint:disable-next-line: no-backbone-get-set-outside-model
+ this.instantiateForm.get('ssh_keys').setValue(getSSHJson);
+ }).catch((err: string): void => {
+ if (err === 'typeError') {
+ this.notifierService.notify('error', this.translateService.instant('PUBFILETYPEERRROR'));
+ } else {
+ this.notifierService.notify('error', this.translateService.instant('ERROR'));
+ }
+ this.fileInputSSHLabel.nativeElement.innerText = this.translateService.instant('CHOOSEFILE');
+ this.fileInputSSH.nativeElement.value = null;
+ });
+ } else if (files && files.length > 1) {
+ this.notifierService.notify('error', this.translateService.instant('DROPFILESVALIDATION'));
+ }
+ this.fileInputSSHLabel.nativeElement.innerText = files[0].name;
+ this.fileInputSSH.nativeElement.value = null;
+ }
+
+ /** Config file process @private */
+ public configFile(files: FileList): void {
+ if (files && files.length === 1) {
+ this.sharedService.getFileString(files, 'yaml').then((fileContent: string): void => {
+ const getConfigJson: string = jsyaml.load(fileContent, { json: true });
+ // tslint:disable-next-line: no-backbone-get-set-outside-model
+ this.instantiateForm.get('config').setValue(JSON.stringify(getConfigJson));
+ }).catch((err: string): void => {
+ if (err === 'typeError') {
+ this.notifierService.notify('error', this.translateService.instant('YAMLFILETYPEERRROR'));
+ } else {
+ this.notifierService.notify('error', this.translateService.instant('ERROR'));
+ }
+ this.fileInputConfigLabel.nativeElement.innerText = this.translateService.instant('CHOOSEFILE');
+ this.fileInputConfig.nativeElement.value = null;
+ });
+ } else if (files && files.length > 1) {
+ this.notifierService.notify('error', this.translateService.instant('DROPFILESVALIDATION'));
+ }
+ this.fileInputConfigLabel.nativeElement.innerText = files[0].name;
+ this.fileInputConfig.nativeElement.value = null;
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="row d-flex flex-row justify-content-between">
+ <div class="d-flex align-items-center header-style">{{'PAGE.DASHBOARD.NETSLICETEMPLATE' | translate}}</div>
+</div>
+<div class="row">
+ <div class="dropzone mt-2" appDrag (click)="fileInput.click()" (files)="filesDropped($event)">
+ <input hidden type="file" #fileInput (change)="filesDropped($event.target.files)">
+ <div class="text-wrapper">
+ <div class="text-center file-drop-title">
+ <i class="fas fa-upload"></i> {{'DROPFILES' | translate}}</div>
+ </div>
+ </div>
+</div>
+<div class="row mt-2 mb-0 form-group justify-content-end list-utilites-actions">
+ <page-per-row class="mr-2" (pagePerRow)="onChange($event)"></page-per-row>
+ <page-reload></page-reload>
+</div>
+<div class="smarttable-style bg-white mt-1">
+ <ng2-smart-table [ngClass]="checkDataClass" [settings]="settings" [source]="dataSource" (userRowSelect)="onUserRowSelect($event)">
+ </ng2-smart-table>
+</div>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+.ng2-smart-th.identifier{
+ width:40% !important;
+}
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file Netslice-Template.
+ */
+import { HttpHeaders } from '@angular/common/http';
+import { Component, ElementRef, Injector, ViewChild } from '@angular/core';
+import { TranslateService } from '@ngx-translate/core';
+import { NotifierService } from 'angular-notifier';
+import { APIURLHEADER, ERRORDATA } from 'CommonModel';
+import { DataService } from 'DataService';
+import { environment } from 'environment';
+import { NetslicePackagesActionComponent } from 'NetslicePackagesAction';
+import { NetworkSliceData, NetworkSliceModel } from 'NetworkSliceModel';
+import { LocalDataSource } from 'ng2-smart-table';
+import { RestService } from 'RestService';
+import { Subscription } from 'rxjs';
+import { SharedService } from 'SharedService';
+
+/**
+ * Creating component
+ * @Component takes NetsliceTemplateComponent.html as template url
+ */
+@Component({
+ selector: 'app-netslice-template',
+ templateUrl: './NetsliceTemplateComponent.html',
+ styleUrls: ['./NetsliceTemplateComponent.scss']
+})
+/** Exporting a class @exports NetsliceTemplateComponent */
+export class NetsliceTemplateComponent {
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** Values for map config @public */
+ public selectedRows: object[] = [];
+
+ /** To consume REST API calls @public */
+ public dataSource: LocalDataSource = new LocalDataSource();
+
+ /** handle translate @public */
+ public translateService: TranslateService;
+
+ /** Columns list of the smart table @public */
+ public columnLists: object = {};
+
+ /** Settings for smarttable to populate the table with columns @public */
+ public settings: object = {};
+
+ /** Values for map config @public */
+ public selectList: object[] = [];
+
+ /** Check the loading results @public */
+ public isLoadingResults: boolean = true;
+
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+
+ /** Class for empty and present data @public */
+ public checkDataClass: string;
+
+ /** Element ref for fileInput @public */
+ @ViewChild('fileInput', { static: true }) public fileInput: ElementRef;
+
+ /** To consume REST API calls @private */
+ private dataService: DataService;
+
+ /** To consume REST API calls @private */
+ private restService: RestService;
+
+ /** Formation of appropriate Data for LocalDatasource @private */
+ private networkSliceData: NetworkSliceData[] = [];
+
+ /** variables holds file information @private */
+ private fileData: string | ArrayBuffer;
+
+ /** Controls the header form @private */
+ private headers: HttpHeaders;
+
+ /** Notifier service to popup notification @private */
+ private notifierService: NotifierService;
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ /** Instance of subscriptions @private */
+ private generateDataSub: Subscription;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.restService = this.injector.get(RestService);
+ this.dataService = this.injector.get(DataService);
+ this.translateService = this.injector.get(TranslateService);
+ this.notifierService = this.injector.get(NotifierService);
+ this.sharedService = this.injector.get(SharedService);
+ }
+
+ /** Lifecyle Hooks the trigger before component is instantiate @public */
+ public ngOnInit(): void {
+ this.generateColumns();
+ this.generateSettings();
+ this.generateData();
+ this.headers = new HttpHeaders({
+ 'Content-Type': 'application/x-yaml',
+ Accept: 'application/json',
+ 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
+ });
+ this.generateDataSub = this.sharedService.dataEvent.subscribe(() => { this.generateData(); });
+ }
+
+ /** smart table Header Colums @public */
+ public generateColumns(): void {
+ this.columnLists = {
+ name: { title: this.translateService.instant('NAME'), width: '20%', sortDirection: 'asc' },
+ identifier: { title: this.translateService.instant('IDENTIFIER'), width: '50%' },
+ usageState: { title: this.translateService.instant('USAGESTATE'), width: '20%' },
+ Actions: {
+ name: 'Actions', width: '10%', filter: false, sort: false, type: 'custom',
+ title: this.translateService.instant('ACTIONS'),
+ valuePrepareFunction: (cell: NetworkSliceData, row: NetworkSliceData): NetworkSliceData => row,
+ renderComponent: NetslicePackagesActionComponent
+ }
+ };
+ }
+
+ /** smart table Data Settings @public */
+ public generateSettings(): void {
+ this.settings = {
+ edit: {
+ editButtonContent: '<i class="fa fa-edit" title="Edit"></i>',
+ confirmSave: true
+ },
+ delete: {
+ deleteButtonContent: '<i class="far fa-trash-alt" title="delete"></i>',
+ confirmDelete: true
+ },
+ columns: this.columnLists,
+ actions: {
+ add: false,
+ edit: false,
+ delete: false,
+ position: 'right'
+ },
+ attr: this.sharedService.tableClassConfig(),
+ pager: this.sharedService.paginationPagerConfig(),
+ noDataMessage: this.translateService.instant('NODATAMSG')
+ };
+ }
+
+ /** smart table listing manipulation @private */
+ public onChange(perPageValue: number): void {
+ this.dataSource.setPaging(1, perPageValue, true);
+ }
+
+ /** smart table listing manipulation @private */
+ public onUserRowSelect(event: MessageEvent): void {
+ Object.assign(event.data, { page: 'network-slice' });
+ this.dataService.changeMessage(event.data);
+ }
+
+ /** Drag and drop feature and fetchind the details of files @private */
+ public filesDropped(files: FileList): void {
+ if (files && files.length === 1) {
+ this.isLoadingResults = true;
+ this.sharedService.getFileString(files, 'yaml').then((fileContent: String | ArrayBuffer): void => {
+ const apiURLHeader: APIURLHEADER = {
+ url: environment.NETWORKSLICETEMPLATECONTENT_URL,
+ httpOptions: { headers: this.headers }
+ };
+ this.saveFileData(apiURLHeader, fileContent);
+ }).catch((err: string): void => {
+ this.isLoadingResults = false;
+ if (err === 'typeError') {
+ this.notifierService.notify('error', this.translateService.instant('YAMLFILETYPEERRROR'));
+ } else {
+ this.notifierService.notify('error', this.translateService.instant('ERROR'));
+ }
+ });
+ } else if (files && files.length > 1) {
+ this.notifierService.notify('error', this.translateService.instant('DROPFILESVALIDATION'));
+ }
+ }
+
+ /** Post the droped files and reload the page @public */
+ public saveFileData(urlHeader: APIURLHEADER, fileData: {}): void {
+ this.fileInput.nativeElement.value = null;
+ this.restService.postResource(urlHeader, fileData).subscribe((result: {}) => {
+ this.notifierService.notify('success', this.translateService.instant('PAGE.NETSLICE.TEMPLATECREATEDSUCCESSFULLY'));
+ this.generateData();
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'post');
+ this.isLoadingResults = false;
+ });
+ }
+
+ /** Generate nsData object from loop and return for the datasource @public */
+ public generateNetworkSliceData(networkSlicePackageData: NetworkSliceModel): NetworkSliceData {
+ return {
+ name: networkSlicePackageData.name,
+ identifier: networkSlicePackageData._id,
+ usageState: networkSlicePackageData._admin.usageState
+ };
+ }
+
+ /**
+ * Lifecyle hook which get trigger on component destruction
+ */
+ public ngOnDestroy(): void {
+ this.generateDataSub.unsubscribe();
+ }
+
+ /** Fetching the data from server to Load in the smarttable @protected */
+ protected generateData(): void {
+ this.isLoadingResults = true;
+ this.restService.getResource(environment.NETWORKSLICETEMPLATECONTENT_URL).subscribe((networkSliceList: NetworkSliceModel[]) => {
+ this.networkSliceData = [];
+ networkSliceList.forEach((networkSlicePackageData: NetworkSliceModel) => {
+ const networkSliceDataObj: NetworkSliceData = this.generateNetworkSliceData(networkSlicePackageData);
+ this.networkSliceData.push(networkSliceDataObj);
+ });
+ if (this.networkSliceData.length > 0) {
+ this.checkDataClass = 'dataTables_present';
+ } else {
+ this.checkDataClass = 'dataTables_empty';
+ }
+ this.dataSource.load(this.networkSliceData).then((data: boolean) => {
+ this.isLoadingResults = false;
+ }).catch(() => {
+ this.isLoadingResults = false;
+ });
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'get');
+ this.isLoadingResults = false;
+ });
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="row d-flex flex-row justify-content-between">
+ <div class="d-flex align-items-center header-style">NS {{'PACKAGES' | translate}}</div>
+ <span class="button">
+ <button class="btn btn-primary" type="button" placement="top" container="body" ngbTooltip="{{'PAGE.NSPACKAGE.ADDNSPACKAGE' | translate}}"
+ (click)="composeNSPackage()">
+ <i class="fas fa-plus-circle" aria-hidden="true"></i> {{'PAGE.NSPACKAGE.ADDNSPACKAGE' | translate}}
+ </button>
+ </span>
+</div>
+<div class="row">
+ <div class="dropzone mt-2" appDrag (click)="fileInput.click()" (files)="filesDropped($event)">
+ <input hidden type="file" #fileInput (change)="filesDropped($event.target.files)">
+ <div class="text-wrapper">
+ <div class="text-center file-drop-title">
+ <i class="fas fa-upload"></i> {{'DROPFILES' | translate}}</div>
+ </div>
+ </div>
+</div>
+<div class="row mt-2 mb-0 form-group justify-content-end list-utilites-actions">
+ <page-per-row class="mr-2" (pagePerRow)="onChange($event)"></page-per-row>
+ <page-reload></page-reload>
+</div>
+<div class="smarttable-style bg-white mt-1">
+ <ng2-smart-table [ngClass]="checkDataClass" [settings]="settings" [source]="dataSource" (userRowSelect)="onUserRowSelect($event)">
+ </ng2-smart-table>
+</div>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @file NS-Packages component.
+ */
+import { HttpHeaders } from '@angular/common/http';
+import { Component, ElementRef, Injector, OnInit, ViewChild } from '@angular/core';
+import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateService } from '@ngx-translate/core';
+import { NotifierService } from 'angular-notifier';
+import { APIURLHEADER, ERRORDATA } from 'CommonModel';
+import { ComposePackages } from 'ComposePackages';
+import { DataService } from 'DataService';
+import { environment } from 'environment';
+import { LocalDataSource } from 'ng2-smart-table';
+import { NSData, NSDDetails } from 'NSDModel';
+import { NsPackagesActionComponent } from 'NsPackagesAction';
+import { RestService } from 'RestService';
+import { Subscription } from 'rxjs';
+import { SharedService } from 'SharedService';
+
+/**
+ * Creating component
+ * @Component takes NSPackagesComponent.html as template url
+ */
+@Component({
+ selector: 'app-ns-packages',
+ templateUrl: './NSPackagesComponent.html',
+ styleUrls: ['./NSPackagesComponent.scss']
+})
+
+/** Exporting a class @exports NSPackagesComponent */
+export class NSPackagesComponent implements OnInit {
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** Formation of appropriate Data for LocalDatasource @public */
+ public dataSource: LocalDataSource = new LocalDataSource();
+
+ /** handle translate @public */
+ public translateService: TranslateService;
+
+ /** Columns list of the smart table @public */
+ public columnLists: object = {};
+
+ /** Settings for smarttable to populate the table with columns @public */
+ public settings: object = {};
+
+ /** Check the loading results @public */
+ public isLoadingResults: boolean = true;
+
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+
+ /** Class for empty and present data @public */
+ public checkDataClass: string;
+
+ /** Element ref for fileInput @public */
+ @ViewChild('fileInput', { static: true }) public fileInput: ElementRef;
+
+ /** Instance of the rest service @private */
+ private restService: RestService;
+
+ /** dataService to pass the data from one component to another @private */
+ private dataService: DataService;
+
+ /** Formation of appropriate Data for LocalDatasource @private */
+ private nsData: NSData[] = [];
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ /** variables holds file information @private */
+ private fileData: string | ArrayBuffer;
+
+ /** Controls the header form @private */
+ private headers: HttpHeaders;
+
+ /** Notifier service to popup notification @private */
+ private notifierService: NotifierService;
+
+ /** Instance of the modal service @private */
+ private modalService: NgbModal;
+
+ /** Instance of subscriptions @private */
+ private generateDataSub: Subscription;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.restService = this.injector.get(RestService);
+ this.dataService = this.injector.get(DataService);
+ this.sharedService = this.injector.get(SharedService);
+ this.translateService = this.injector.get(TranslateService);
+ this.notifierService = this.injector.get(NotifierService);
+ this.modalService = this.injector.get(NgbModal);
+ }
+
+ /** Lifecyle Hooks the trigger before component is instantiate @public */
+ public ngOnInit(): void {
+ this.generateColumns();
+ this.generateSettings();
+ this.generateData();
+ this.headers = new HttpHeaders({
+ 'Content-Type': 'application/gzip',
+ Accept: 'application/json',
+ 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
+ });
+ this.generateDataSub = this.sharedService.dataEvent.subscribe(() => { this.generateData(); });
+ }
+
+ /** smart table Header Colums @public */
+ public generateColumns(): void {
+ this.columnLists = {
+ shortName: { title: this.translateService.instant('SHORTNAME'), width: '15%', sortDirection: 'asc' },
+ identifier: { title: this.translateService.instant('IDENTIFIER'), width: '20%' },
+ description: { title: this.translateService.instant('DESCRIPTION'), width: '25%' },
+ vendor: { title: this.translateService.instant('VENDOR'), width: '15%' },
+ version: { title: this.translateService.instant('VERSION'), width: '10%' },
+ Actions: {
+ name: 'Actions', width: '15%', filter: false, sort: false, type: 'custom',
+ title: this.translateService.instant('ACTIONS'),
+ valuePrepareFunction: (cell: NSData, row: NSData): NSData => row, renderComponent: NsPackagesActionComponent
+ }
+ };
+ }
+
+ /** smart table Data Settings @public */
+ public generateSettings(): void {
+ this.settings = {
+ edit: {
+ editButtonContent: '<i class="fa fa-edit" title="Edit"></i>',
+ confirmSave: true
+ },
+ delete: {
+ deleteButtonContent: '<i class="far fa-trash-alt" title="delete"></i>',
+ confirmDelete: true
+ },
+ columns: this.columnLists,
+ actions: {
+ add: false,
+ edit: false,
+ delete: false,
+ position: 'right'
+ },
+ attr: this.sharedService.tableClassConfig(),
+ pager: this.sharedService.paginationPagerConfig(),
+ noDataMessage: this.translateService.instant('NODATAMSG')
+ };
+ }
+
+ /** smart table listing manipulation @public */
+ public onChange(perPageValue: number): void {
+ this.dataSource.setPaging(1, perPageValue, true);
+ }
+
+ /** smart table listing manipulation @public */
+ public onUserRowSelect(event: MessageEvent): void {
+ Object.assign(event.data, { page: 'ns-package' });
+ this.dataService.changeMessage(event.data);
+ }
+
+ /** Drag and drop feature and fetchind the details of files @public */
+ public filesDropped(files: FileList): void {
+ if (files && files.length === 1) {
+ this.isLoadingResults = true;
+ this.sharedService.getFileString(files, 'gz').then((fileContent: ArrayBuffer): void => {
+ const apiURLHeader: APIURLHEADER = {
+ url: environment.NSDESCRIPTORSCONTENT_URL,
+ httpOptions: { headers: this.headers }
+ };
+ this.saveFileData(apiURLHeader, fileContent);
+ }).catch((err: string): void => {
+ this.isLoadingResults = false;
+ if (err === 'typeError') {
+ this.notifierService.notify('error', this.translateService.instant('GZFILETYPEERRROR'));
+ } else {
+ this.notifierService.notify('error', this.translateService.instant('ERROR'));
+ }
+ });
+ } else if (files && files.length > 1) {
+ this.notifierService.notify('error', this.translateService.instant('DROPFILESVALIDATION'));
+ }
+ }
+
+ /** Post the droped files and reload the page @public */
+ public saveFileData(urlHeader: APIURLHEADER, fileData: {}): void {
+ this.fileInput.nativeElement.value = null;
+ this.restService.postResource(urlHeader, fileData).subscribe((result: {}) => {
+ this.notifierService.notify('success', this.translateService.instant('PAGE.NSPACKAGE.CREATEDSUCCESSFULLY'));
+ this.generateData();
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'post');
+ this.isLoadingResults = false;
+ });
+ }
+
+ /** Generate nsData object from loop and return for the datasource @public */
+ public generateNSData(nsdpackagedata: NSDDetails): NSData {
+ return {
+ shortName: nsdpackagedata['short-name'],
+ identifier: nsdpackagedata._id,
+ description: nsdpackagedata.description,
+ vendor: nsdpackagedata.vendor,
+ version: nsdpackagedata.version
+ };
+ }
+
+ /** Fetching the data from server to Load in the smarttable @public */
+ public generateData(): void {
+ this.isLoadingResults = true;
+ this.restService.getResource(environment.NSDESCRIPTORSCONTENT_URL).subscribe((nsdPackageData: NSDDetails[]) => {
+ this.nsData = [];
+ nsdPackageData.forEach((nsdpackagedata: NSDDetails) => {
+ const nsDataObj: NSData = this.generateNSData(nsdpackagedata);
+ this.nsData.push(nsDataObj);
+ });
+ if (this.nsData.length > 0) {
+ this.checkDataClass = 'dataTables_present';
+ } else {
+ this.checkDataClass = 'dataTables_empty';
+ }
+ this.dataSource.load(this.nsData).then((data: boolean) => {
+ this.isLoadingResults = false;
+ }).catch(() => {
+ this.isLoadingResults = false;
+ });
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'get');
+ this.isLoadingResults = false;
+ });
+ }
+ /** Handle compose new ns package method @public */
+ public composeNSPackage(): void {
+ this.modalService.open(ComposePackages, { backdrop: 'static' }).componentInstance.params = { page: 'ns-package' };
+ }
+
+ /**
+ * Lifecyle hook which get trigger on component destruction
+ */
+ public ngOnDestroy(): void {
+ this.generateDataSub.unsubscribe();
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<ng-sidebar-container class="ns-topology-sidebar-container">
+ <!-- A sidebar -->
+ <ng-sidebar [(opened)]="sideBarOpened" position="left">
+ <div class="sidebar-header">
+ <span class="topology_title" *ngIf="isShowNSDDetails">{{'PAGE.TOPOLOGY.NSD' | translate}}</span>
+ <span class="topology_title" *ngIf="isShowVLDetails">{{'PAGE.TOPOLOGY.VIRTUALLINK' | translate}}</span>
+ <span class="topology_title" *ngIf="isShowVNFDetails">{{'PAGE.TOPOLOGY.VNF' | translate}}</span>
+ <span class="topology_title" *ngIf="isShowCPDetails">{{'PAGE.TOPOLOGY.CONNECTIONPOINT' | translate}}</span>
+ <button (click)="toggleSidebar()" class="close" type="button">
+ <i class="fas fa-times-circle text-danger" aria-hidden="true"></i>
+ </button>
+ </div>
+ <div class="sidebar-body">
+ <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 mb-2" *ngIf="isShowNSDDetails">
+ <div class="row">
+ <div class="col-12 p-0">
+ <form autocomplete="off">
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label">{{ 'SHORTNAME' | translate }}</label>
+ <div class="col-sm-8 p-0">
+ <input type="text" class="form-control" placeholder="{{ 'SHORTNAME' | translate }}" name="shortName"
+ [(ngModel)]="vnfdPackageDetails.shortName">
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label">{{ 'VENDOR' | translate }}</label>
+ <div class="col-sm-8 p-0">
+ <input type="text" class="form-control" placeholder="{{ 'VENDOR' | translate }}" name="vendor"
+ [(ngModel)]="vnfdPackageDetails.vendor">
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label">{{ 'DESCRIPTION' | translate }}</label>
+ <div class="col-sm-8 p-0">
+ <textarea type="text" class="form-control" placeholder="{{ 'DESCRIPTION' | translate }}"
+ name="description" [(ngModel)]="vnfdPackageDetails.description"></textarea>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label">{{ 'VERSION' | translate }}</label>
+ <div class="col-sm-8 p-0">
+ <input type="text" class="form-control" placeholder="{{ 'VERSION' | translate }}" name="version"
+ [(ngModel)]="vnfdPackageDetails.version">
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label">{{ 'ID' | translate }}</label>
+ <div class="col-sm-8 p-0">
+ <input type="text" class="form-control" placeholder="{{ 'ID' | translate }}" name="id"
+ [(ngModel)]="vnfdPackageDetails.id">
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label">{{ 'NAME' | translate }}</label>
+ <div class="col-sm-8 p-0">
+ <input type="text" class="form-control" placeholder="{{ 'NAME' | translate }}" name="name"
+ [(ngModel)]="vnfdPackageDetails.name">
+ </div>
+ </div>
+ <button type="button" class="btn btn-primary" (click)="saveNSD()" placement="top"
+ ngbTooltip="Save">
+ <i class="fas fa-save"></i> {{'SAVE' | translate}}
+ </button>
+ </form>
+ </div>
+ </div>
+ </div>
+ <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 mb-2" *ngIf="isShowVLDetails">
+ <div class="row">
+ <div class="col-12 p-0">
+ <form autocomplete="off">
+ <div class="form-group row">
+ <label class="col-sm-4 p-0 col-form-label">{{ 'NAME' | translate }}</label>
+ <div class="col-sm-8 p-0">
+ <input type="text" class="form-control" placeholder="{{ 'NAME' | translate }}" name="name"
+ [(ngModel)]="vlDetails.name">
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 p-0 col-form-label">{{'PAGE.NSPACKAGE.NSCOMPOSE.MGMTNETWORK' | translate}}</label>
+ <div class="col-sm-8 p-0">
+ <select class="form-control custom-select" name="mgmt-network" [(ngModel)]="vlDetails['mgmt-network']">
+ <option [value]="true">True</option>
+ <option [value]="false">False</option>
+ </select>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 p-0 col-form-label">{{'PAGE.NSPACKAGE.NSCOMPOSE.VIMNETWORKNAME' | translate}}</label>
+ <div class="col-sm-8 p-0">
+ <input type="text" class="form-control" placeholder="Vim network name" name="vim-network-name"
+ [(ngModel)]="vlDetails['vim-network-name']">
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 p-0 col-form-label">{{'TYPE' | translate}}</label>
+ <div class="col-sm-8 p-0">
+ <input type="text" class="form-control" placeholder="Type" name="type" [(ngModel)]="vlDetails.type">
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 p-0 col-form-label">{{ 'ID' | translate }}</label>
+ <div class="col-sm-8 p-0">
+ <input type="text" class="form-control" placeholder="{{ 'ID' | translate }}" name="id"
+ [(ngModel)]="vlDetails.id">
+ </div>
+ </div>
+ <button type="button" class="btn btn-primary" placement="top" ngbTooltip="Save"
+ (click)="saveVL(vlDetails.id)">
+ <i class="fas fa-save"></i> {{'SAVE' | translate}}
+ </button>
+ </form>
+ </div>
+ </div>
+ </div>
+ <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 mb-2" *ngIf="isShowVNFDetails">
+ <div class="row">
+ <div class="col-12 p-0">
+ <table class="table table-bordered text-dark custom-table">
+ <tbody>
+ <tr>
+ <td>{{'PAGE.NSPACKAGE.NSCOMPOSE.MEMBER-VNF-INDEX' | translate}}</td>
+ <td>{{ vnfData['member-vnf-index'] }}</td>
+ </tr>
+ <tr>
+ <td>{{'PAGE.NSPACKAGE.NSCOMPOSE.VNFD-ID-REF' | translate}}</td>
+ <td>{{ vnfData['vnfd-id-ref'] }}</td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ </div>
+ <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 mb-2" *ngIf="isShowCPDetails">
+ <div class="row">
+ <div class="col-12 p-0">
+ <table class="table table-bordered text-dark custom-table">
+ <tbody>
+ <tr>
+ <td>{{'PAGE.NSPACKAGE.NSCOMPOSE.VLD-ID' | translate}}</td>
+ <td>{{ vlDetails['name'] }}</td>
+ </tr>
+ <tr>
+ <td>{{'PAGE.NSPACKAGE.NSCOMPOSE.VNFD-CP-REF' | translate}}</td>
+ <td>{{ cpData['vnfd-connection-point-ref'] }}</td>
+ </tr>
+ <tr>
+ <td>{{'MEMBERINDEX' | translate}}</td>
+ <td>{{ cpData['member-vnf-index-ref'] }}</td>
+ </tr>
+ <tr>
+ <td>{{'PAGE.NSPACKAGE.NSCOMPOSE.VNFD-ID-REF' | translate}}</td>
+ <td>{{ cpData['vnfd-id-ref'] }}</td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ </div>
+ </div>
+ </ng-sidebar>
+ <!-- Page content -->
+ <div ng-sidebar-content>
+ <button (click)="toggleSidebar()" class="btn btn-default" placement="right" ngbTooltip="{{'OPEN' | translate }}">
+ <i class="fa fa-arrow-right detail-sidebar" aria-hidden="true"></i>
+ </button>
+ </div>
+</ng-sidebar-container>
+<div class="container-fluid text-dark">
+ <div class="row bg-white ns-composer-form">
+ <div class="col-xs-3 col-sm-3 col-md-3 col-lg-3 pl-0 px-0">
+ <div class="row">
+ <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 mb-2">
+ <fieldset class="p-2">
+ <legend class="vl-legend">
+ {{'PAGE.TOPOLOGY.SELECTELEMENT' | translate}}
+ </legend>
+ <ul class="list-group list-group-flush dragable">
+ <li class="list-group-item" draggable="true" (dragstart)="drag($event)" id="vl">
+ <img src="assets/images/VL.svg" class="ns-svg" draggable="false"/>
+ <span class="span-overflow-text font-weight-bold">{{'PAGE.TOPOLOGY.VL' | translate}}</span>
+ <span class="drag-icon pull-right"><i class="fas fa-arrows-alt"></i></span>
+ </li>
+ </ul>
+ </fieldset>
+ </div>
+ </div>
+ <div class="row">
+ <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
+ <fieldset class="p-2">
+ <legend class="vnfd-legend">
+ {{'PAGE.TOPOLOGY.VNFD' | translate}}
+ </legend>
+ <ul class="list-group list-group-flush dragable scroll-box">
+ <li id="list['id']" class="list-group-item" draggable="true" (dragstart)="drag($event)"
+ [attr.data-id]="list['id']" *ngFor="let list of vnfList" placement="top"
+ container="body" ngbTooltip="{{ list['short-name'] }}">
+ <img src="assets/images/VNFD.svg" class="ns-svg" draggable="false"/>
+ <span class="span-overflow-text font-weight-bold">{{ list['short-name'] }}</span>
+ <span class="drag-icon pull-right"><i class="fas fa-arrows-alt"></i></span>
+ </li>
+ </ul>
+ </fieldset>
+ </div>
+ </div>
+ </div>
+ <div class="col-xs-9 col-sm-9 col-md-9 col-lg-9">
+ <div class="row">
+ <div class="col-xs-6 col-sm-6 col-md-6 col-lg-6 pl-0">
+ <div class="btn-group list" role="group" aria-label="Basic example">
+ <button type="button" class="btn btn-primary topology-btn" (click)="onFreeze()"
+ [class.pinned]="classApplied" placement="top" container="body" ngbTooltip="{{(classApplied ? 'UNFREEZE' : 'FREEZE') | translate}}">
+ <i class="fas fa-thumbtack"></i>
+ </button>
+ <button type="button" class="btn btn-primary topology-btn" (click)="onEdit()" placement="top"
+ container="body" ngbTooltip="{{'EDIT' | translate}}">
+ <i class="fa fa-edit"></i>
+ </button>
+ <button type="button" class="btn btn-primary topology-btn" (click)="showInfo()" placement="top"
+ container="body" ngbTooltip="{{'PAGE.TOPOLOGY.HELP' | translate}}">
+ <i class="fas fa-info"></i>
+ </button>
+ </div>
+ </div>
+ <div class="col-xs-6 col-sm-6 col-md-6 col-lg-6 text-right pr-0 badgegroup">
+ <span class="badge badge-primary badge-pill bg-white text-body font-weight-bold">
+ <img src="assets/images/VNFD.svg" class="ns-svg" draggable="false"/>
+ <br>{{'PAGE.TOPOLOGY.VNF' | translate}}</span>
+ <span class="badge badge-primary badge-pill bg-white text-body font-weight-bold">
+ <img src="assets/images/VL.svg" class="ns-svg" draggable="false"/>
+ <br>{{'PAGE.TOPOLOGY.VL' | translate}}</span>
+ <span class="badge badge-primary badge-pill bg-white text-body font-weight-bold">
+ <img src="assets/images/CP.svg" class="ns-svg" draggable="false"/>
+ <br>{{'PAGE.TOPOLOGY.CP' | translate}}</span>
+ </div>
+ </div>
+ <div class="row border-all">
+ <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 svg-container">
+ <svg preserveAspectRatio="xMidYMin slice" (drop)="drop($event)" (dragover)="allowDrop($event)"
+ id="graphContainer" #graphContainer>
+ </svg>
+ </div>
+ </div>
+ </div>
+ </div>
+</div>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file NS Compose Component
+ */
+// tslint:disable: no-increment-decrement
+import { HttpHeaders } from '@angular/common/http';
+import { Component, ElementRef, Injector, ViewChild, ViewEncapsulation } from '@angular/core';
+import { ActivatedRoute, Router } from '@angular/router';
+import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateService } from '@ngx-translate/core';
+import { NotifierService } from 'angular-notifier';
+import { APIURLHEADER, CONSTANTNUMBER, ERRORDATA, MODALCLOSERESPONSEDATA, MODALCLOSERESPONSEWITHCP } from 'CommonModel';
+import { ConfirmationTopologyComponent } from 'ConfirmationTopology';
+import * as d3 from 'd3';
+import { DataService } from 'DataService';
+import { environment } from 'environment';
+import * as HttpStatus from 'http-status-codes';
+import * as jsyaml from 'js-yaml';
+import { COMPOSERNODES, CONSTITUENTVNFD, GRAPHDETAILS, NSDDetails, Tick, TickPath, VLD, VNFDCONNECTIONPOINTREF } from 'NSDModel';
+import { RestService } from 'RestService';
+import { SharedService } from 'SharedService';
+import { isNullOrUndefined } from 'util';
+import { VNFData, VNFDDetails } from 'VNFDModel';
+
+/**
+ * Creating component
+ * @Component takes NSComposerComponent.html as template url
+ */
+@Component({
+ selector: 'app-ns-composer',
+ templateUrl: './NSComposerComponent.html',
+ styleUrls: ['./NSComposerComponent.scss'],
+ encapsulation: ViewEncapsulation.None
+})
+/** Exporting a class @exports NSComposerComponent */
+export class NSComposerComponent {
+ /** To inject services @public */
+ public injector: Injector;
+ /** View child contains graphContainer ref @public */
+ @ViewChild('graphContainer', { static: true }) public graphContainer: ElementRef;
+ /** dataService to pass the data from one component to another @public */
+ public dataService: DataService;
+ /** Contains VNFD Informations @public */
+ public vnfdPackageDetails: VNFData = { identifier: '', shortName: '', vendor: '', description: '', version: '', id: '', name: '' };
+ /** Contains VL Details @public */
+ public vlDetails: VLD = {
+ name: '',
+ 'mgmt-network': true,
+ 'vim-network-name': '',
+ type: '',
+ id: ''
+ };
+ /** Contains the information of the type of modification @public */
+ public putType: string;
+ /** Conatins mousedown action @public */
+ public mousedownNode: COMPOSERNODES = null;
+ /** Conatins mouseup action @public */
+ public mouseupNode: COMPOSERNODES = null;
+ /** Conatins mousedownLink action @public */
+ public mousedownLink: COMPOSERNODES = null;
+ /** Conatins current Selection node action @public */
+ public currentSelectedNode: COMPOSERNODES = null;
+ /** Conatins current Selection node action @public */
+ public currentSelectedLink: COMPOSERNODES = null;
+ /** Need to show the NSD Details @public */
+ public isShowNSDDetails: boolean = true;
+ /** Contains the node information of VL @public */
+ public vlNodes: {}[] = [];
+ /** Need to show the VL Details @public */
+ public isShowVLDetails: boolean = false;
+ /** Contains the node information of VNF @public */
+ public vnfNodes: {}[] = [];
+ /** contains the VNF Details @public */
+ public vnfData: CONSTITUENTVNFD;
+ /** Need to show the VNF Details @public */
+ public isShowVNFDetails: boolean = false;
+ /** Contains the node information of CP @public */
+ public cpNodes: {}[] = [];
+ /** Need to show the CP Details */
+ public cpData: VNFDCONNECTIONPOINTREF;
+ /** Need to show the VNF Details @public */
+ public isShowCPDetails: boolean = false;
+ /** random number count @public */
+ public randomNumberLength: number;
+ /** Contains the vnfd information @public */
+ public vnfList: VNFDDetails[] = [];
+ /** Add the activeclass for the selected @public */
+ public activeClass: string = 'active';
+ /** Add the fixed class for the freeze @public */
+ public fixedClass: string = 'fixed';
+ /** Check the loading results @public */
+ public isLoadingResults: boolean = true;
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+ /** Get VNF selected node @public */
+ public getVNFSelectedData: VNFDDetails[];
+ /** Assign the forcesimulation active @public */
+ public forceSimulationActive: boolean = false;
+ /** Assign pinned class for the button when freezed @public */
+ public classApplied: boolean = false;
+ /** Contains sidebar open status @public */
+ public sideBarOpened: boolean = false;
+ /** Contains SVG attributes @private */
+ // tslint:disable-next-line:no-any
+ private svg: any;
+ /** Contains the Drag line */
+ // tslint:disable-next-line: no-any
+ private dragLine: any;
+ /** Contains VL node @private */
+ // tslint:disable-next-line:no-any
+ private vlNode: any;
+ /** Contains VNFD node @private */
+ // tslint:disable-next-line:no-any
+ private vnfdnode: any;
+ /** Contains CP node @private */
+ // tslint:disable-next-line:no-any
+ private cpnode: any;
+ /** Rendered nodes represent VL @private */
+ // tslint:disable-next-line:no-any
+ private gvlNode: any;
+ /** Rendered nodes represent VL @private */
+ // tslint:disable-next-line:no-any
+ private gvnfdNode: any;
+ /** Rendered nodes represent VL @private */
+ // tslint:disable-next-line:no-any
+ private gcpNode: any;
+ /** Contains forced node animations @private */
+ // tslint:disable-next-line:no-any
+ private force: any;
+ /** Contains all the selected node @private */
+ private selectedNode: COMPOSERNODES[] = [];
+ /** variables used for CP @private */
+ private iConnectionPointRef: number = 0;
+ /** Contains the connected point @private */
+ private connectionPoint: string;
+ /** Contains all the NSD information @private */
+ private nsd: string;
+ /** Contains all the VNFD information @private */
+ private vnfd: string;
+ /** Contains id of the node @private */
+ private identifier: string;
+ /** Variables used for cp @private */
+ private jConnectionPointRef: number = 0;
+ /** Contains copy of NSD information @private */
+ private nsdCopy: string;
+ /** Contains the VNFD copy @private */
+ private vnfdCopy: string;
+ /** Contains name of the node @private */
+ private name: string;
+ /** Contains member vnf index value of the node @private */
+ private memberVnfIndexValue: number = 0;
+ /** Contains path information of the node */
+ // tslint:disable-next-line:no-any
+ private path: any;
+ /** Contains the node information @private */
+ private nodes: COMPOSERNODES[] = [];
+ /** Contains the link information of nodes @private */
+ private links: {}[] = [];
+ /** Contains the NS information @private */
+ private nsData: NSDDetails;
+ /** Instance of the rest service @private */
+ private restService: RestService;
+ /** Service holds the router information @private */
+ private router: Router;
+ /** Holds teh instance of AuthService class of type AuthService @private */
+ private activatedRoute: ActivatedRoute;
+ /** Notifier service to popup notification @private */
+ private notifierService: NotifierService;
+ /** Controls the header form @private */
+ private headers: HttpHeaders;
+ /** Contains tranlsate instance @private */
+ private translateService: TranslateService;
+ /** Contains lastkeypressed instance @private */
+ private lastKeyDown: number = -1;
+ /** Instance of the modal service @private */
+ private modalService: NgbModal;
+ /** Setting the Value of connection point refrence of the CP @private */
+ private setVnfdConnectionPointRef: string;
+ /** Setting the Value of VL name for confirmation @private */
+ private vlName: string;
+ /** Setting the Value of VNFD name for confirmation @private */
+ private setVnfdName: string;
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+ /** Contains selected node VLD objects @private */
+ private selectedVLDResult: VLD;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.restService = this.injector.get(RestService);
+ this.dataService = this.injector.get(DataService);
+ this.router = this.injector.get(Router);
+ this.activatedRoute = this.injector.get(ActivatedRoute);
+ this.notifierService = this.injector.get(NotifierService);
+ this.translateService = this.injector.get(TranslateService);
+ this.modalService = this.injector.get(NgbModal);
+ this.sharedService = this.injector.get(SharedService);
+ }
+ /** Lifecyle Hooks the trigger before component is instantiate @public */
+ public ngOnInit(): void {
+ // tslint:disable-next-line:no-backbone-get-set-outside-model
+ this.identifier = this.activatedRoute.snapshot.paramMap.get('id');
+ this.generateData();
+ this.headers = new HttpHeaders({
+ 'Content-Type': 'application/zip',
+ Accept: 'application/json',
+ 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
+ });
+ }
+ /** Events handles at drag on D3 region @public */
+ // tslint:disable-next-line:no-any
+ public drag(ev: any): void {
+ if (ev.target.id === 'vl') {
+ ev.dataTransfer.setData('text', ev.target.id);
+ } else {
+ ev.dataTransfer.setData('text', ev.target.attributes['data-id'].value);
+ }
+ }
+ /** On clicking redirect to NS edit page @public */
+ public onEdit(): void {
+ this.router.navigate(['/packages/ns/edit/', this.identifier]).catch(() => {
+ // Catch Navigation Error
+ });
+ }
+ /** Events handles drop at D3 region @public */
+ public drop(ev: DragEvent): void {
+ event.preventDefault();
+ this.name = ev.dataTransfer.getData('text');
+ if (this.name === 'vl') {
+ this.svg.selectAll('*').remove();
+ this.vldropComposer();
+ } else {
+ this.svg.selectAll('*').remove();
+ this.vnfd = ev.dataTransfer.getData('text');
+ this.vnfdropComposer();
+ }
+ }
+ /** Drop VL Composer Data @public */
+ public vldropComposer(): void {
+ this.randomNumberLength = CONSTANTNUMBER.randomNumber;
+ const generateId: string = 'ns_vl_' + this.randomString(
+ this.randomNumberLength,
+ '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
+ );
+ if (this.nsData.vld !== undefined) {
+ this.nsData.vld.push({
+ 'vim-network-name': 'PUBLIC',
+ name: generateId,
+ 'mgmt-network': true,
+ type: 'ELAN',
+ id: generateId
+ });
+ } else {
+ Object.assign(this.nsData, {
+ vld: [{
+ 'vim-network-name': 'PUBLIC',
+ name: generateId,
+ 'mgmt-network': true,
+ type: 'ELAN',
+ id: generateId
+ }]
+ });
+ }
+ this.putType = 'nsdadd';
+ this.addData(environment.NSDESCRIPTORS_URL, this.identifier, this.nsData, this.putType);
+ }
+ /** Drop VNFD Composer Data @public */
+ public vnfdropComposer(): void {
+ if (this.nsData['constituent-vnfd'] !== undefined) {
+ this.nsData['constituent-vnfd'].push({
+ 'vnfd-id-ref': this.vnfd,
+ 'member-vnf-index': ++this.memberVnfIndexValue
+ });
+ } else {
+ Object.assign(this.nsData, {
+ 'constituent-vnfd': [{
+ 'vnfd-id-ref': this.vnfd,
+ 'member-vnf-index': ++this.memberVnfIndexValue
+ }]
+ });
+ }
+ this.putType = 'vnfdadd';
+ this.addData(environment.NSDESCRIPTORS_URL, this.identifier, this.nsData, this.putType);
+ }
+ /** Events handles allow drop on D3 region @public */
+ public allowDrop(ev: DragEvent): void {
+ ev.preventDefault();
+ }
+ /** Save NSD Information @public */
+ public saveNSD(): void {
+ if (this.vnfdPackageDetails.shortName !== undefined) {
+ this.nsData['short-name'] = this.vnfdPackageDetails.shortName;
+ }
+ if (this.vnfdPackageDetails.vendor !== undefined) {
+ this.nsData.vendor = this.vnfdPackageDetails.vendor;
+ }
+ if (this.vnfdPackageDetails.description !== undefined) {
+ this.nsData.description = this.vnfdPackageDetails.description;
+ }
+ if (this.vnfdPackageDetails.version !== undefined) {
+ this.nsData.version = this.vnfdPackageDetails.version;
+ }
+ if (this.vnfdPackageDetails.id !== undefined) {
+ this.nsData.id = this.vnfdPackageDetails.id;
+ }
+ if (this.vnfdPackageDetails.name !== undefined) {
+ this.nsData.name = this.vnfdPackageDetails.name;
+ }
+ this.putType = 'nsdUpdate';
+ this.addData(environment.NSDESCRIPTORS_URL, this.identifier, this.nsData, this.putType);
+ }
+ /** Save Virtual Link @public */
+ public saveVL(vlid: string): void {
+ this.nsData.vld.forEach((result: VLD) => {
+ if (result.id === vlid) {
+ result.name = this.vlDetails.name;
+ result['mgmt-network'] = !isNullOrUndefined(this.vlDetails['mgmt-network']) ? this.vlDetails['mgmt-network'] : true;
+ result['vim-network-name'] = !isNullOrUndefined(this.vlDetails['vim-network-name']) ? this.vlDetails['vim-network-name'] : '';
+ result.type = this.vlDetails.type;
+ result.id = this.vlDetails.id;
+ }
+ });
+ this.putType = 'vlUpdate';
+ this.addData(environment.NSDESCRIPTORS_URL, this.identifier, this.nsData, this.putType);
+ }
+ /** Add the new Data @public */
+ public addData(apiURL: string, identifier: string, data: NSDDetails, putType: string): void {
+ this.isLoadingResults = true;
+ let successMessage: string = '';
+ if (putType === 'nsdadd') {
+ successMessage = 'PAGE.NSPACKAGE.NSCOMPOSE.ADDNSD';
+ } else if (putType === 'vnfdadd') {
+ successMessage = 'PAGE.NSPACKAGE.NSCOMPOSE.ADDVNFD';
+ } else if (putType === 'cpAdded') {
+ successMessage = 'PAGE.NSPACKAGE.NSCOMPOSE.ADDNS';
+ } else if (putType === 'nsdUpdate') {
+ successMessage = 'PAGE.NSPACKAGE.NSCOMPOSE.UPDATEDSUCCESSFULLY';
+ } else if (putType === 'vlUpdate') {
+ successMessage = 'PAGE.NSPACKAGE.NSCOMPOSE.UPDATEDSUCCESSFULLY';
+ } else if (putType === 'nsddelete') {
+ successMessage = 'PAGE.NSPACKAGE.NSCOMPOSE.DELETENSD';
+ } else if (putType === 'vnfddelete') {
+ successMessage = 'PAGE.NSPACKAGE.NSCOMPOSE.DELETEVNFD';
+ } else if (putType === 'nsdelete') {
+ successMessage = 'PAGE.NSPACKAGE.NSCOMPOSE.DELETENS';
+ } else if (putType === 'linkdelete') {
+ successMessage = 'PAGE.NSPACKAGE.NSCOMPOSE.DELETELINK';
+ }
+ /** Below hide for conflicts with light weight UI */
+ const apiURLHeader: APIURLHEADER = {
+ url: apiURL + '/' + identifier + '/nsd_content',
+ httpOptions: { headers: this.headers }
+ };
+ const nsData: {} = {};
+ nsData['nsd:nsd-catalog'] = {};
+ nsData['nsd:nsd-catalog'].nsd = [];
+ nsData['nsd:nsd-catalog'].nsd.push(data);
+ const descriptorInfo: string = jsyaml.dump(nsData, {sortKeys: true});
+ this.sharedService.targzFile({ packageType: 'nsd', id: this.identifier, descriptor: descriptorInfo })
+ .then((content: ArrayBuffer): void => {
+ this.restService.putResource(apiURLHeader, content).subscribe((res: {}) => {
+ this.generateData();
+ this.notifierService.notify('success', this.translateService.instant(successMessage));
+ this.isLoadingResults = false;
+ }, (error: ERRORDATA) => {
+ this.generateData();
+ this.restService.handleError(error, 'put');
+ this.isLoadingResults = false;
+ });
+ }).catch((): void => {
+ this.notifierService.notify('error', this.translateService.instant('ERROR'));
+ this.isLoadingResults = false;
+ });
+ }
+ /** Show Info @public */
+ public showInfo(): void {
+ const modalRef: NgbModalRef = this.modalService.open(ConfirmationTopologyComponent, { backdrop: 'static' });
+ modalRef.componentInstance.topologyType = 'Info';
+ modalRef.componentInstance.topologytitle = this.translateService.instant('PAGE.TOPOLOGY.INFO');
+ modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
+ if (result) {
+ // empty
+ }
+ }).catch();
+ }
+ /** Event to freeze the animation @public */
+ public onFreeze(): void {
+ this.classApplied = !this.classApplied;
+ const alreadyFixedIsActive: boolean = d3.select('svg#graphContainer').classed(this.fixedClass);
+ d3.select('svg#graphContainer').classed(this.fixedClass, !alreadyFixedIsActive);
+ if (alreadyFixedIsActive) {
+ this.force.stop();
+ }
+ this.forceSimulationActive = alreadyFixedIsActive;
+ this.nodes.forEach((d: COMPOSERNODES) => {
+ d.fx = (alreadyFixedIsActive) ? null : d.x;
+ d.fy = (alreadyFixedIsActive) ? null : d.y;
+ });
+ if (alreadyFixedIsActive) {
+ this.force.restart();
+ }
+ }
+ /** Events handles when dragended @public */
+ public toggleSidebar(): void {
+ this.sideBarOpened = !this.sideBarOpened;
+ this.deselectAllNodes();
+ this.showRightSideInfo(true, false, false, false);
+ }
+ /** Prepare information for node creation of VNFD @private */
+ private generateData(): void {
+ this.generateVNFData();
+ this.generateDataNSDTopology();
+ this.sideBarOpened = false;
+ }
+ /** Prepare the information of the VNFD @private */
+ private generateVNFData(): void {
+ this.restService.getResource(environment.VNFPACKAGESCONTENT_URL).subscribe((vnfdPackageData: VNFDDetails[]) => {
+ this.vnfList = vnfdPackageData;
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'get');
+ });
+ }
+ /** Prepare information for node creation of NSD Topology @private */
+ private generateDataNSDTopology(): void {
+ this.nodes = [];
+ this.links = [];
+ this.iConnectionPointRef = 0;
+ this.jConnectionPointRef = 0;
+ this.restService.getResource(environment.NSDESCRIPTORSCONTENT_URL + '/' + this.identifier).subscribe((nsData: NSDDetails) => {
+ delete nsData._admin;
+ delete nsData._id;
+ this.nsData = nsData;
+ this.vnfdPackageDetails.shortName = nsData['short-name'];
+ this.vnfdPackageDetails.vendor = nsData.vendor;
+ this.vnfdPackageDetails.description = nsData.description;
+ this.vnfdPackageDetails.version = nsData.version;
+ this.vnfdPackageDetails.id = nsData.id;
+ this.vnfdPackageDetails.name = nsData.name;
+ if (nsData.vld !== undefined) {
+ /** Details of the VL */
+ this.nsDataVLD(nsData);
+ }
+ if (nsData['constituent-vnfd'] !== undefined) {
+ /** Details of the VNFD */
+ this.nsDataConstituentVNFD(nsData);
+ }
+ if (nsData.vld !== undefined) {
+ this.nsDataVLDLinkCreation(nsData);
+ }
+ this.separateAndCreatenode();
+ }, (error: ERRORDATA) => {
+ if (error.error.status === HttpStatus.NOT_FOUND || error.error.status === HttpStatus.UNAUTHORIZED) {
+ this.router.navigateByUrl('404', { skipLocationChange: true }).catch();
+ } else {
+ this.restService.handleError(error, 'get');
+ }
+ this.isLoadingResults = false;
+ this.isShowNSDDetails = false;
+ });
+ }
+ /** nsData-vld undefined Call this function @private */
+ private nsDataVLD(nsData: NSDDetails): void {
+ nsData.vld.forEach((res: VLD) => {
+ this.nodes.push({ id: res.id, reflexive: false, type: 'vld', name: res.id, selectorId: res.id });
+ this.nsd = res.id;
+ if (res['vnfd-connection-point-ref'] !== undefined) {
+ res['vnfd-connection-point-ref'].forEach((result: VNFDCONNECTIONPOINTREF) => {
+ this.nodes.push(
+ {
+ id: this.nsd + ++this.iConnectionPointRef + ':' + result['vnfd-connection-point-ref'],
+ reflexive: false,
+ type: 'ns',
+ name: result['vnfd-connection-point-ref'],
+ nodeIndex: result['member-vnf-index-ref'],
+ selectorId: result['vnfd-connection-point-ref'] + '_' + result['member-vnf-index-ref'] + '-osm-' + this.nsd
+ });
+ });
+ }
+ });
+ }
+ /** nsData constituent-vnfd undefined Call this function @private */
+ private nsDataConstituentVNFD(nsData: NSDDetails): void {
+ nsData['constituent-vnfd'].forEach((res: CONSTITUENTVNFD) => {
+ this.nodes.push(
+ {
+ id: res['vnfd-id-ref'] + ':' + res['member-vnf-index'],
+ reflexive: false,
+ type: 'vnfd',
+ name: res['vnfd-id-ref'],
+ nodeIndex: res['member-vnf-index'],
+ selectorId: res['vnfd-id-ref'] + '_' + res['member-vnf-index']
+ });
+ this.vnfd = res['vnfd-id-ref'];
+ this.memberVnfIndexValue = res['member-vnf-index'];
+ });
+ }
+
+ /** nsData-vld undefined Call this function @private */
+ private nsDataVLDLinkCreation(nsData: NSDDetails): void {
+ nsData.vld.forEach((res: VLD) => {
+ this.nsdCopy = res.id;
+ if (res['vnfd-connection-point-ref'] !== undefined) {
+ this.nsDataVNFDConnectionPointRefrence(res);
+ }
+ });
+ }
+ /** nsData-vnfd-connection-point-ref undefined Call this function @private */
+ private nsDataVNFDConnectionPointRefrence(res: VLD): void {
+ res['vnfd-connection-point-ref'].forEach((result: VNFDCONNECTIONPOINTREF) => {
+ this.connectionPoint = this.nsdCopy + ++this.jConnectionPointRef + ':' + result['vnfd-connection-point-ref'];
+ this.vnfdCopy = result['vnfd-id-ref'] + ':' + result['member-vnf-index-ref'];
+ const connectionPointPos: number = this.nodes.map((e: COMPOSERNODES) => { return e.id; }).indexOf(this.connectionPoint);
+ const nsdPos: number = this.nodes.map((e: COMPOSERNODES) => { return e.id; }).indexOf(this.nsdCopy);
+ const vnfdPos: number = this.nodes.map((e: COMPOSERNODES) => { return e.id; }).indexOf(this.vnfdCopy);
+ this.links.push(
+ {
+ source: this.nodes[connectionPointPos],
+ target: this.nodes[nsdPos]
+ },
+ {
+ source: this.nodes[connectionPointPos],
+ target: this.nodes[vnfdPos]
+ });
+ });
+ }
+ /** Generate random string @private */
+ private randomString(length: number, chars: string): string {
+ let result: string = '';
+ for (let randomStringRef: number = length; randomStringRef > 0; --randomStringRef) {
+ result += chars[Math.floor(Math.random() * chars.length)];
+ }
+ return result;
+ }
+ /** Separate and create node @private */
+ private separateAndCreatenode(): void {
+ this.seprateNodes(this.nodes);
+ this.createnode(this.nodes);
+ this.isLoadingResults = false;
+ }
+ /** Get the default Configuration of containers @private */
+ private getGraphContainerAttr(): GRAPHDETAILS {
+ return {
+ width: 700,
+ height: 400,
+ nodeHeight: 50,
+ nodeWidth: 35,
+ textX: -35,
+ textY: 30,
+ radius: 5,
+ distance: 50,
+ strength: -500,
+ forcex: 2,
+ forcey: 2,
+ sourcePaddingYes: 17,
+ sourcePaddingNo: 12,
+ targetPaddingYes: 4,
+ targetPaddingNo: 3,
+ alphaTarget: 0.3,
+ imageX: -25,
+ imageY: -25,
+ shiftKeyCode: 17
+ };
+ }
+ /** Separate the nodes along with its tyep @private */
+ private seprateNodes(node: COMPOSERNODES[]): void {
+ this.vlNodes = []; this.vnfNodes = []; this.cpNodes = [];
+ node.forEach((nodeList: COMPOSERNODES) => {
+ if (nodeList.type === 'vld') {
+ this.vlNodes.push(nodeList);
+ } else if (nodeList.type === 'vnfd') {
+ this.vnfNodes.push(nodeList);
+ } else if (nodeList.type === 'ns') {
+ this.cpNodes.push(nodeList);
+ }
+ });
+ }
+ /** Node is created and render at D3 region @private */
+ private createnode(node: COMPOSERNODES[]): void {
+ const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
+ d3.selectAll('svg#graphContainer > *').remove();
+ d3.select(window).on('keydown', () => { this.keyDown(); });
+ d3.select(window).on('keyup', () => { this.keyUp(); });
+ this.svg = d3.select('#graphContainer')
+ .attr('oncontextmenu', 'return false;')
+ .attr('width', graphContainerAttr.width)
+ .attr('height', graphContainerAttr.height)
+ .on('mousemove', () => { this.mousemove(); });
+ this.force = d3.forceSimulation()
+ .force('charge', d3.forceManyBody().strength(graphContainerAttr.strength))
+ .force('link', d3.forceLink().id((d: TickPath) => d.id).distance(graphContainerAttr.distance))
+ .force('center', d3.forceCenter(graphContainerAttr.width / graphContainerAttr.forcex,
+ graphContainerAttr.height / graphContainerAttr.forcey))
+ .force('x', d3.forceX(graphContainerAttr.width / graphContainerAttr.forcex))
+ .force('y', d3.forceY(graphContainerAttr.height / graphContainerAttr.forcey))
+ .on('tick', () => { this.tick(); });
+ this.dragLine = this.svg.append('svg:path').attr('class', 'link dragline hidden').attr('d', 'M0,0L0,0');
+ this.path = this.svg.append('svg:g').selectAll('path');
+ this.vlNode = this.svg.append('svg:g').selectAll('vlnode');
+ this.vnfdnode = this.svg.append('svg:g').selectAll('vnfdnode');
+ this.cpnode = this.svg.append('svg:g').selectAll('cpnode');
+ // app starts here
+ this.restart(node);
+ }
+ /** update force layout (called automatically each iteration) @private */
+ private tick(): void {
+ const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
+ // draw directed edges with proper padding from node centers
+ this.path.attr('class', 'link').attr('d', (d: Tick) => {
+ const deltaX: number = d.target.x - d.source.x;
+ const deltaY: number = d.target.y - d.source.y;
+ const dist: number = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
+ const normX: number = deltaX / dist;
+ const normY: number = deltaY / dist;
+ const sourcePadding: number = d.left ? graphContainerAttr.sourcePaddingYes : graphContainerAttr.sourcePaddingNo;
+ const targetPadding: number = d.right ? graphContainerAttr.targetPaddingYes : graphContainerAttr.targetPaddingNo;
+ const sourceX: number = d.source.x + (sourcePadding * normX);
+ const sourceY: number = d.source.y + (sourcePadding * normY);
+ const targetX: number = d.target.x - (targetPadding * normX);
+ const targetY: number = d.target.y - (targetPadding * normY);
+ return `M${sourceX},${sourceY}L${targetX},${targetY}`;
+ }).on('dblclick', (d: Tick) => { this.getDeleteLinkConfirmation(d); });
+ this.vlNode.attr('transform', (t: TickPath) => `translate(${t.x},${t.y})`);
+ this.vnfdnode.attr('transform', (t: TickPath) => `translate(${t.x},${t.y})`);
+ this.cpnode.attr('transform', (t: TickPath) => `translate(${t.x},${t.y})`);
+ }
+ /** Update graph (called when needed) at D3 region @private */
+ private restart(node: COMPOSERNODES[]): void {
+ const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
+ this.path = this.path.data(this.links);
+ this.vlNode = this.vlNode.data(this.vlNodes, (d: COMPOSERNODES) => d.id);
+ this.vnfdnode = this.vnfdnode.data(this.vnfNodes, (d: COMPOSERNODES) => d.id);
+ this.cpnode = this.cpnode.data(this.cpNodes, (d: COMPOSERNODES) => d.id);
+ this.resetAndCreateNodes();
+ this.force.nodes(node).force('link').links(this.links);
+ this.force.alphaTarget(graphContainerAttr.alphaTarget).restart();
+ }
+ /** Rest and create nodes @private */
+ private resetAndCreateNodes(): void {
+ this.path.exit().remove();
+ this.vlNode.exit().remove();
+ this.vnfdnode.exit().remove();
+ this.cpnode.exit().remove();
+ this.getPathNodes();
+ this.getVLNodes();
+ this.getVNFDNodes();
+ this.getCPNodes();
+ this.path.merge(this.path);
+ this.vlNode = this.gvlNode.merge(this.vlNode);
+ this.vnfdnode = this.gvnfdNode.merge(this.vnfdnode);
+ this.cpnode = this.gcpNode.merge(this.cpnode);
+ }
+ /** setting the Path @private */
+ private getPathNodes(): void {
+ this.path = this.path.enter().append('svg:path');
+ }
+ /** Setting all the VL nodes @private */
+ private getVLNodes(): void {
+ const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
+ this.gvlNode = this.vlNode.enter().append('svg:g');
+ this.gvlNode.append('svg:circle').attr('r', graphContainerAttr.radius).style('fill', '#eeeeee');
+ this.gvlNode.append('svg:image')
+ .style('opacity', 1)
+ .attr('x', graphContainerAttr.imageX)
+ .attr('y', graphContainerAttr.imageY)
+ .attr('id', (d: COMPOSERNODES) => { return d.selectorId; })
+ .attr('class', 'node').attr('width', graphContainerAttr.nodeWidth).attr('height', graphContainerAttr.nodeHeight)
+ .attr('xlink:href', 'assets/images/VL.svg')
+ .on('mousedown', (d: COMPOSERNODES) => { this.mouseDown(d); })
+ .on('mouseup', (d: COMPOSERNODES) => { this.mouseUp(d); })
+ .on('click', (d: COMPOSERNODES) => { this.singleClick(this.vlNode, d); this.onNodeClickToggleSidebar(); })
+ .on('dblclick', (d: COMPOSERNODES) => { this.getDeleteConfirmation(d); this.onNodedblClickToggleSidebar(); });
+ this.gvlNode.append('svg:text')
+ .attr('class', 'node_text')
+ .attr('y', graphContainerAttr.textY)
+ .text((d: COMPOSERNODES) => d.id);
+ }
+ /** Setting all the VNFD nodes @private */
+ private getVNFDNodes(): void {
+ const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
+ this.gvnfdNode = this.vnfdnode.enter().append('svg:g');
+ this.gvnfdNode.append('svg:circle').attr('r', graphContainerAttr.radius).style('fill', '#eeeeee');
+ this.gvnfdNode.append('svg:image')
+ .style('opacity', 1)
+ .attr('x', graphContainerAttr.imageX)
+ .attr('y', graphContainerAttr.imageY)
+ .attr('id', (d: COMPOSERNODES) => { return d.selectorId; })
+ .attr('class', 'node').attr('width', graphContainerAttr.nodeWidth).attr('height', graphContainerAttr.nodeHeight)
+ .attr('xlink:href', 'assets/images/VNFD.svg')
+ .on('mousedown', (d: COMPOSERNODES) => { this.mouseDown(d); })
+ .on('mouseup', (d: COMPOSERNODES) => { this.mouseUp(d); })
+ .on('click', (d: COMPOSERNODES) => { this.singleClick(this.vnfdnode, d); this.onNodeClickToggleSidebar(); })
+ .on('dblclick', (d: COMPOSERNODES) => { this.getDeleteConfirmation(d); this.onNodedblClickToggleSidebar(); });
+ this.gvnfdNode.append('svg:text')
+ .attr('class', 'node_text')
+ .attr('y', graphContainerAttr.textY)
+ .text((d: COMPOSERNODES) => d.id);
+ }
+ /** Setting all the CP nodes @private */
+ private getCPNodes(): void {
+ const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
+ this.gcpNode = this.cpnode.enter().append('svg:g');
+ this.gcpNode.append('svg:circle').attr('r', graphContainerAttr.radius).style('fill', '#eeeeee');
+ this.gcpNode.append('svg:image')
+ .style('opacity', 1)
+ .attr('x', graphContainerAttr.imageX)
+ .attr('y', graphContainerAttr.imageY)
+ .attr('id', (d: COMPOSERNODES) => { return d.selectorId; })
+ .attr('class', 'node').attr('width', graphContainerAttr.nodeWidth).attr('height', graphContainerAttr.nodeHeight)
+ .attr('xlink:href', 'assets/images/CP.svg')
+ .on('mousedown', (d: COMPOSERNODES) => { this.mouseDown(d); })
+ .on('mouseup', (d: COMPOSERNODES) => { this.mouseUp(d); })
+ .on('click', (d: COMPOSERNODES) => { this.singleClick(this.cpnode, d); this.onNodeClickToggleSidebar(); })
+ .on('dblclick', (d: COMPOSERNODES) => { this.getDeleteConfirmation(d); this.onNodedblClickToggleSidebar(); });
+ this.gcpNode.append('svg:text')
+ .attr('class', 'node_text')
+ .attr('y', graphContainerAttr.textY)
+ .text((d: COMPOSERNODES) => d.id);
+ }
+ /** Events handles when mousemove it will capture the selected node data @private */
+ private mousemove(): void {
+ if (!this.mousedownNode) { return; }
+ this.dragLine.attr('d',
+ `M${this.mousedownNode.x},${this.mousedownNode.y}L${d3.mouse(d3.event.currentTarget)[0]},${d3.mouse(d3.event.currentTarget)[1]}`);
+ }
+ /** Get confirmation Before Deleting the Link in Topology @private */
+ private getAddConfirmation(mouseData: COMPOSERNODES, getNsData: NSDDetails, addType: string, getVLDIndex: number): void {
+ let findVNFName: string = '';
+ let findVLDID: string = '';
+ if (mouseData.type === 'vld') {
+ findVNFName = this.mouseupNode.name;
+ findVLDID = this.mousedownNode.id;
+ } else {
+ findVNFName = this.mousedownNode.name;
+ findVLDID = this.mouseupNode.id;
+ }
+ getNsData.vld.forEach((result: VLD) => {
+ if (result.id === findVLDID) {
+ this.vlName = result.name;
+ this.getVNFSelectedData = this.vnfList.filter((vnfList: VNFDDetails) => vnfList.id === findVNFName);
+ this.setVnfdConnectionPointRef = this.getVNFSelectedData[0]['mgmt-interface'].cp;
+ this.setVnfdName = this.getVNFSelectedData[0].name;
+ this.selectedVLDResult = result;
+ }
+ });
+ if (this.vlName !== undefined && this.setVnfdName !== undefined && this.setVnfdConnectionPointRef !== undefined) {
+ const modalRef: NgbModalRef = this.modalService.open(ConfirmationTopologyComponent, { backdrop: 'static' });
+ modalRef.componentInstance.topologyType = 'Add';
+ modalRef.componentInstance.cpDetails = this.getVNFSelectedData[0]['connection-point'];
+ this.translateService.get('PAGE.TOPOLOGY.ADDINGCP', {
+ vlname: '<b>' + this.vlName + '</b>',
+ vnfdname: '<b>' + this.setVnfdName + '</b>',
+ cpname: '<b>' + this.setVnfdConnectionPointRef + '</b>'
+ }).subscribe((res: string) => {
+ modalRef.componentInstance.topologyname = res;
+ });
+ modalRef.componentInstance.topologytitle = this.translateService.instant('PAGE.TOPOLOGY.CONNECTIONPOINT');
+ modalRef.result.then((result: MODALCLOSERESPONSEWITHCP) => {
+ if (result) {
+ this.nsData = getNsData;
+ this.generateCPForVNF(this.selectedVLDResult, result.connection_point, getVLDIndex);
+ this.addData(environment.NSDESCRIPTORS_URL, this.identifier, getNsData, addType);
+ } else {
+ this.deselectPath();
+ }
+ }).catch();
+ } else {
+ this.deselectPath();
+ this.notifierService.notify('error', this.translateService.instant('ERROR'));
+ }
+ }
+
+ /** Generate connection point for vnf using vld @private */
+ private generateCPForVNF(result: VLD, cp: string, getVLDIndex: number): void {
+ if (result['vnfd-connection-point-ref'] !== undefined) {
+ result['vnfd-connection-point-ref'].push({
+ 'member-vnf-index-ref': getVLDIndex,
+ 'vnfd-connection-point-ref': cp,
+ 'vnfd-id-ref': this.getVNFSelectedData[0].name
+ });
+ } else {
+ Object.assign(result, {
+ 'vnfd-connection-point-ref': [{
+ 'member-vnf-index-ref': getVLDIndex,
+ 'vnfd-connection-point-ref': cp,
+ 'vnfd-id-ref': this.getVNFSelectedData[0].name
+ }]
+ });
+ }
+ }
+
+ /** Events handles when mousedown click it will capture the selected node data @private */
+ private mouseDown(d: COMPOSERNODES): void {
+ event.preventDefault();
+ if (d3.event.ctrlKey) { return; }
+ if (d3.event.shiftKey) {
+ if (d.type === 'vnfd') {
+ this.selectedNode.push(d);
+ }
+ this.mousedownNode = d;
+ this.currentSelectedNode = (this.mousedownNode === this.currentSelectedNode) ? null : this.mousedownNode;
+ this.currentSelectedLink = null;
+ this.dragLine.style('marker-end', 'url(#end-arrow)').classed('hidden', false)
+ .attr('d', `M${this.mousedownNode.x},${this.mousedownNode.y}L${this.mousedownNode.x},${this.mousedownNode.y}`);
+ }
+ }
+ /** Event handles when mouseup event occures @private */
+ private mouseUp(d: COMPOSERNODES): void {
+ if (!this.mousedownNode) { return; }
+ this.dragLine.classed('hidden', true).style('marker-end', '');
+ this.mouseupNode = d;
+ if (this.mousedownNode.type === 'vld' && this.mouseupNode.type === 'vnfd') {
+ const getOldVLDIndex: string[] = this.mouseupNode.id.split(':');
+ const setOldVLDindex: number = +getOldVLDIndex[1];
+ this.putType = 'cpAdded';
+ this.getAddConfirmation(this.mousedownNode, this.nsData, this.putType, setOldVLDindex);
+ } else if (this.mousedownNode.type === 'vnfd' && this.mouseupNode.type === 'vld') {
+ const getOldVLDIndex: string[] = this.mousedownNode.id.split(':');
+ const setOldVLDindex: number = +getOldVLDIndex[1];
+ this.putType = 'cpAdded';
+ this.getAddConfirmation(this.mousedownNode, this.nsData, this.putType, setOldVLDindex);
+ } else if (this.mousedownNode.type === 'vnfd' && this.mouseupNode.type === 'ns') {
+ this.deselectPath();
+ this.notifierService.notify('warning', this.translateService.instant('PAGE.NSPACKAGE.NSCOMPOSE.CANNOTLINKVNFCP'));
+ } else if (this.mousedownNode.type === 'vld' && this.mouseupNode.type === 'ns') {
+ this.deselectPath();
+ this.notifierService.notify('warning', this.translateService.instant('PAGE.NSPACKAGE.NSCOMPOSE.CANNOTLINKVNFCP'));
+ } else if (this.mousedownNode.type === 'vld' && this.mouseupNode.type === 'vld') {
+ this.deselectPath();
+ this.notifierService.notify('warning', this.translateService.instant('PAGE.NSPACKAGE.NSCOMPOSE.CANNOTLINKVL'));
+ } else if (this.mousedownNode.type === 'vnfd' && this.mouseupNode.type === 'vnfd') {
+ this.deselectPath();
+ this.notifierService.notify('warning', this.translateService.instant('PAGE.NSPACKAGE.NSCOMPOSE.CANNOTLINKVNF'));
+ } else if (this.mousedownNode.type === 'ns' && this.mouseupNode.type === 'ns') {
+ this.deselectPath();
+ this.notifierService.notify('warning', this.translateService.instant('PAGE.NSPACKAGE.NSCOMPOSE.CANNOTLINKCP'));
+ } else {
+ this.deselectPath();
+ this.notifierService.notify('warning', this.translateService.instant('PAGE.NSPACKAGE.NSCOMPOSE.CANNOTLINKVLVNF'));
+ }
+ this.resetMouseVars();
+ // select new link
+ this.currentSelectedLink = d;
+ this.currentSelectedNode = null;
+ }
+ /** Mosue Drag Line false if it is not satisfied @private */
+ private deselectPath(): void {
+ this.dragLine.classed('hidden', true).style('marker-end', '').attr('d', 'M0,0L0,0');
+ }
+ /** reset Mouse varaibles @private */
+ private resetMouseVars(): void {
+ this.mousedownNode = null;
+ this.mouseupNode = null;
+ this.mousedownLink = null;
+ }
+ /** De-select all the selected nodes @private */
+ private deselectAllNodes(): void {
+ this.vlNode.select('image').classed(this.activeClass, false);
+ this.vnfdnode.select('image').classed(this.activeClass, false);
+ this.cpnode.select('image').classed(this.activeClass, false);
+ }
+ /** Show the right-side information @private */
+ private showRightSideInfo(nsdDetails: boolean, vldDetails: boolean, vnfDeails: boolean, cpDetails: boolean): void {
+ this.isShowNSDDetails = nsdDetails;
+ this.isShowVLDetails = vldDetails;
+ this.isShowVNFDetails = vnfDeails;
+ this.isShowCPDetails = cpDetails;
+ }
+ /** Events handles when Shift Click to perform create cp @private */
+ // tslint:disable-next-line: no-any
+ private singleClick(nodeSelected: any, d: COMPOSERNODES): void {
+ this.selectNodeExclusive(nodeSelected, d);
+ }
+ /** Selected nodes @private */
+ // tslint:disable-next-line: no-any
+ private selectNodeExclusive(nodeSeleced: any, d: COMPOSERNODES): void {
+ const alreadyIsActive: boolean = nodeSeleced.select('#' + d.selectorId).classed(this.activeClass);
+ this.deselectAllNodes();
+ nodeSeleced.select('#' + d.selectorId).classed(this.activeClass, !alreadyIsActive);
+ if (d.type === 'vld' && !alreadyIsActive) {
+ this.nsData.vld.forEach((result: VLD) => {
+ if (result.id === d.id) {
+ this.showRightSideInfo(false, true, false, false);
+ this.vlDetails = result;
+ }
+ });
+ } else if (d.type === 'vnfd' && !alreadyIsActive) {
+ this.nsData['constituent-vnfd'].forEach((result: CONSTITUENTVNFD) => {
+ if (result['member-vnf-index'] === d.nodeIndex && result['vnfd-id-ref'] === d.name) {
+ this.showRightSideInfo(false, false, true, false);
+ this.vnfData = result;
+ }
+ });
+ } else if (d.type === 'ns' && !alreadyIsActive) {
+ this.nsData.vld.forEach((result: VLD) => {
+ if (result['vnfd-connection-point-ref'] !== undefined) {
+ result['vnfd-connection-point-ref'].forEach((resultCP: VNFDCONNECTIONPOINTREF) => {
+ if (resultCP['member-vnf-index-ref'] === d.nodeIndex && resultCP['vnfd-connection-point-ref'] === d.name) {
+ this.cpData = resultCP;
+ this.vlDetails = result;
+ this.showRightSideInfo(false, false, false, true);
+ }
+ });
+ }
+ });
+ } else {
+ this.showRightSideInfo(true, false, false, false);
+ }
+ }
+ /** Get confirmation Before Deleting the Link in Topology @private */
+ private getDeleteLinkConfirmation(d: Tick): void {
+ const modalRef: NgbModalRef = this.modalService.open(ConfirmationTopologyComponent, { backdrop: 'static' });
+ modalRef.componentInstance.topologyType = 'Delete';
+ modalRef.componentInstance.topologyname = this.translateService.instant('PAGE.TOPOLOGY.LINK');
+ modalRef.componentInstance.topologytitle = 'PAGE.TOPOLOGY.LINK';
+ modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
+ if (result) {
+ this.doubleClickLink(d);
+ }
+ }).catch();
+ }
+ /** Events handles when Double Click to Delete the link @private */
+ private doubleClickLink(d: Tick): void {
+ let getID: string = '';
+ if (d.target.type === 'vld') {
+ getID = d.target.id;
+ } else if (d.source.type === 'vld') {
+ getID = d.source.id;
+ }
+ this.nodes.forEach((res: COMPOSERNODES) => {
+ if (res.id === getID) {
+ if (this.nsData.vld !== undefined) {
+ this.nsData.vld.forEach((vldresult: VLD) => {
+ if (vldresult.id === getID) {
+ delete vldresult['vnfd-connection-point-ref'];
+ }
+ });
+ }
+ }
+ });
+ this.putType = 'linkdelete';
+ this.addData(environment.NSDESCRIPTORS_URL, this.identifier, this.nsData, this.putType);
+ }
+ /** Get confirmation Before Deleting the Node in Topology @private */
+ private getDeleteConfirmation(d: COMPOSERNODES): void {
+ const modalRef: NgbModalRef = this.modalService.open(ConfirmationTopologyComponent, { backdrop: 'static' });
+ modalRef.componentInstance.topologyType = 'Delete';
+ modalRef.componentInstance.topologyname = d.name;
+ if (d.type === 'vld') {
+ modalRef.componentInstance.topologytitle = 'PAGE.TOPOLOGY.VIRTUALLINK';
+ } else if (d.type === 'vnfd') {
+ modalRef.componentInstance.topologytitle = 'PAGE.TOPOLOGY.VNF';
+ } else if (d.type === 'ns') {
+ modalRef.componentInstance.topologytitle = 'PAGE.TOPOLOGY.CONNECTIONPOINT';
+ }
+ modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
+ if (result) {
+ this.doubleClick(d);
+ }
+ }).catch();
+ }
+ /** Events handles when Double Click to Delete @private */
+ private doubleClick(d: COMPOSERNODES): void {
+ const deletedNode: COMPOSERNODES = d;
+ this.nodes.forEach((res: COMPOSERNODES) => {
+ if (res.id === d.id) {
+ if (deletedNode.type === 'vld') {
+ const pos: number = this.nsData.vld.map((e: VLD) => { return e.id; }).indexOf(d.id);
+ this.nsData.vld.splice(pos, 1);
+ this.putType = 'nsddelete';
+ } else if (deletedNode.type === 'vnfd') {
+ const constituentVNFD: string[] = [];
+ if (this.nsData['constituent-vnfd'] !== undefined) {
+ this.nsData['constituent-vnfd'].forEach((ref: CONSTITUENTVNFD) => {
+ constituentVNFD.push(ref['vnfd-id-ref'] + ':' + ref['member-vnf-index']);
+ });
+ }
+ const pos: number = constituentVNFD.map((e: string) => { return e; }).indexOf(d.id);
+ this.nsData['constituent-vnfd'].splice(pos, 1);
+ const getCP: string[] = d.id.split(':');
+ const memberVnfIndexRef: number = +getCP[1];
+ const vnfdIDRef: string = getCP[0];
+ if (this.nsData.vld !== undefined) {
+ this.nsData.vld.forEach((resf: VLD) => {
+ if (resf['vnfd-connection-point-ref'] !== undefined) {
+ resf['vnfd-connection-point-ref'].forEach((connectionPoint: VNFDCONNECTIONPOINTREF, index: number) => {
+ if (+connectionPoint['member-vnf-index-ref'] === memberVnfIndexRef && connectionPoint['vnfd-id-ref'] === vnfdIDRef) {
+ resf['vnfd-connection-point-ref'].splice(index, 1);
+ }
+ });
+ }
+ });
+ }
+ this.putType = 'vnfddelete';
+ } else if (deletedNode.type === 'ns') {
+ const getCP: string[] = d.selectorId.split('-osm-');
+ const memberVnfIndexRef: number = d.nodeIndex;
+ const vnfdIDRef: string = getCP[getCP.length - 1];
+ if (this.nsData.vld !== undefined) {
+ this.nsData.vld.forEach((resf: VLD) => {
+ if (resf['vnfd-connection-point-ref'] !== undefined && resf.id === vnfdIDRef) {
+ resf['vnfd-connection-point-ref'].forEach((connectionPoint: VNFDCONNECTIONPOINTREF, index: number) => {
+ if (connectionPoint['member-vnf-index-ref'] === memberVnfIndexRef) {
+ resf['vnfd-connection-point-ref'].splice(index, 1);
+ }
+ });
+ }
+ });
+ }
+ this.putType = 'nsdelete';
+ }
+ this.addData(environment.NSDESCRIPTORS_URL, this.identifier, this.nsData, this.putType);
+ }
+ });
+ }
+ /** Key press event @private */
+ private keyDown(): void {
+ const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
+ if (this.lastKeyDown !== -1) { return; }
+ this.lastKeyDown = d3.event.keyCode;
+ if (d3.event.keyCode === graphContainerAttr.shiftKeyCode) {
+ this.gvlNode.call(d3.drag()
+ .on('start', this.dragstarted).on('drag', this.dragged).on('end', this.dragended)
+ );
+ this.gvnfdNode.call(d3.drag()
+ .on('start', this.dragstarted).on('drag', this.dragged).on('end', this.dragended)
+ );
+ this.gcpNode.call(d3.drag()
+ .on('start', this.dragstarted).on('drag', this.dragged).on('end', this.dragended)
+ );
+ this.svg.classed('ctrl', true);
+ }
+ }
+ /** Key realse event @private */
+ private keyUp(): void {
+ const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
+ this.lastKeyDown = -1;
+ if (d3.event.keyCode === graphContainerAttr.shiftKeyCode) {
+ this.gvlNode.on('.drag', null);
+ this.gvnfdNode.on('.drag', null);
+ this.gcpNode.on('.drag', null);
+ this.svg.classed('ctrl', false);
+ }
+ }
+ /** Events handles when dragstarted @private */
+ private dragstarted(d: COMPOSERNODES): void {
+ d.fx = d.x;
+ d.fy = d.y;
+ }
+ /** Events handles when dragged @private */
+ private dragged(d: COMPOSERNODES): void {
+ d.fx = d.x = d3.event.x;
+ d.fy = d.y = d3.event.y;
+ }
+ /** Events handles when dragended @private */
+ private dragended(d: COMPOSERNODES): void {
+ if (this.forceSimulationActive) {
+ d.fx = null;
+ d.fy = null;
+ } else {
+ d.fx = d.x;
+ d.fy = d.y;
+ this.forceSimulationActive = false;
+ }
+ }
+ /** Events handles when node double click @private */
+ private onNodedblClickToggleSidebar(): void {
+ this.sideBarOpened = false;
+ }
+ /** Events handles when node single click @private */
+ private onNodeClickToggleSidebar(): void {
+ this.sideBarOpened = true;
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<ng-sidebar-container class="vnf-topology-sidebar-container">
+ <!-- A sidebar -->
+ <ng-sidebar [(opened)]="sideBarOpened" position="left">
+ <div class="sidebar-header">
+ <span class="topology_title" *ngIf="showRightSideInfo === 'vnfdInfo'">{{'PAGE.TOPOLOGY.VNFD' | translate}}</span>
+ <span class="topology_title" *ngIf="showRightSideInfo === 'vduInfo'">{{'PAGE.TOPOLOGY.VDU' | translate}}</span>
+ <span class="topology_title" *ngIf="showRightSideInfo === 'intvlInfo'">{{'PAGE.TOPOLOGY.VIRTUALLINK' | translate}}</span>
+ <span class="topology_title" *ngIf="showRightSideInfo === 'cpInfo'">{{'PAGE.TOPOLOGY.CONNECTIONPOINT' | translate}}</span>
+ <span class="topology_title" *ngIf="showRightSideInfo === 'intcpInfo'">{{'PAGE.TOPOLOGY.INTCONNECTIONPOINT' | translate}}</span>
+ <button (click)="toggleSidebar()" class="close" type="button">
+ <i class="fas fa-times-circle text-danger" aria-hidden="true"></i>
+ </button>
+ </div>
+ <div class="sidebar-body">
+ <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 mb-2" *ngIf="showRightSideInfo === 'vnfdInfo'">
+ <div class="row">
+ <div class="col-12 p-0">
+ <form>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label">{{ 'SHORTNAME' | translate }}</label>
+ <div class="col-sm-8">
+ <input type="text" class="form-control" placeholder="{{ 'SHORTNAME' | translate }}" name="shortName"
+ [(ngModel)]="vnfdInfo.shortName">
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label">{{ 'DESCRIPTION' | translate }}</label>
+ <div class="col-sm-8">
+ <input type="text" class="form-control" placeholder="{{ 'DESCRIPTION' | translate }}" name="description"
+ [(ngModel)]="vnfdInfo.description">
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label">{{ 'VERSION' | translate }}</label>
+ <div class="col-sm-8">
+ <input type="text" class="form-control" placeholder="{{ 'VERSION' | translate }}" name="version"
+ [(ngModel)]="vnfdInfo.version">
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label">{{ 'ID' | translate }}</label>
+ <div class="col-sm-8">
+ <input type="text" class="form-control" placeholder="{{ 'ID' | translate }}" name="id"
+ [(ngModel)]="vnfdInfo.id">
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label">{{ 'NAME' | translate }}</label>
+ <div class="col-sm-8">
+ <input type="text" class="form-control" placeholder="{{ 'NAME' | translate }}" name="name"
+ [(ngModel)]="vnfdInfo.name">
+ </div>
+ </div>
+ <button type="button" class="btn btn-primary btn-sm pull-right" (click)="saveVNFD()" placement="top" ngbTooltip="Save">
+ <i class="fas fa-save"></i> {{'SAVE' | translate}}
+ </button>
+ </form>
+ </div>
+ </div>
+ </div>
+ <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 mb-2" *ngIf="showRightSideInfo === 'vduInfo'">
+ <div class="row">
+ <div class="col-12 p-0">
+ <form>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label">{{ 'COUNT' | translate }}</label>
+ <div class="col-sm-8">
+ <input type="text" class="form-control" placeholder="{{ 'COUNT' | translate }}" name="count"
+ [(ngModel)]="vduInfo.count">
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label">{{ 'DESCRIPTION' | translate }}</label>
+ <div class="col-sm-8">
+ <input type="text" class="form-control" placeholder="{{ 'DESCRIPTION' | translate }}" name="description"
+ [(ngModel)]="vduInfo.description">
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label">{{ 'IMAGE' | translate }}</label>
+ <div class="col-sm-8">
+ <input type="text" class="form-control" placeholder="{{ 'IMAGE' | translate }}" name="image"
+ [(ngModel)]="vduInfo.image">
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label">{{ 'ID' | translate }}</label>
+ <div class="col-sm-8">
+ <input type="text" class="form-control" placeholder="{{ 'ID' | translate }}" name="id"
+ [(ngModel)]="vduInfo.id">
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label">{{ 'NAME' | translate }}</label>
+ <div class="col-sm-8">
+ <input type="text" class="form-control" placeholder="{{ 'NAME' | translate }}" name="name"
+ [(ngModel)]="vduInfo.name">
+ </div>
+ </div>
+ <button type="button" class="btn btn-primary btn-sm pull-right" (click)="saveVDU(vduInfo.id)" placement="top"
+ ngbTooltip="Save">
+ <i class="fas fa-save"></i> {{'SAVE' | translate}}
+ </button>
+ </form>
+ </div>
+ </div>
+ </div>
+ <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 mb-2" *ngIf="showRightSideInfo === 'intvlInfo'">
+ <div class="row">
+ <div class="col-12 p-0">
+ <form>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label">{{ 'SHORTNAME' | translate }}</label>
+ <div class="col-sm-8">
+ <input type="text" class="form-control" placeholder="{{ 'SHORTNAME' | translate }}" name="shortName"
+ [(ngModel)]="intvlInfo.shortName">
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label">{{ 'NAME' | translate }}</label>
+ <div class="col-sm-8">
+ <input type="text" class="form-control" placeholder="{{ 'NAME' | translate }}" name="name"
+ [(ngModel)]="intvlInfo.name">
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label">{{ 'TYPE' | translate }}</label>
+ <div class="col-sm-8">
+ <input type="text" class="form-control" placeholder="{{ 'TYPE' | translate }}" name="type"
+ [(ngModel)]="intvlInfo.type">
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label">{{ 'IPPROFILEREF' | translate }}</label>
+ <div class="col-sm-8">
+ <input type="text" class="form-control" placeholder="{{ 'IP Profile Ref' | translate }}"
+ name="ipProfileRef" [(ngModel)]="intvlInfo.ipProfileRef">
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label">{{ 'ID' | translate }}</label>
+ <div class="col-sm-8">
+ <input type="text" class="form-control" placeholder="{{ 'ID' | translate }}" name="id"
+ [(ngModel)]="intvlInfo.id">
+ </div>
+ </div>
+ <button type="button" class="btn btn-primary btn-sm pull-right" (click)="saveIntVL(intvlInfo.id)" placement="top"
+ ngbTooltip="Save">
+ <i class="fas fa-save"></i> {{'SAVE' | translate}}
+ </button>
+ </form>
+ </div>
+ </div>
+ </div>
+ <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 mb-2" *ngIf="showRightSideInfo === 'cpInfo'">
+ <div class="row">
+ <div class="col-12 p-0">
+ <form>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label">{{ 'TYPE' | translate }}</label>
+ <div class="col-sm-8">
+ <input type="text" class="form-control" placeholder="{{ 'TYPE' | translate }}" name="type"
+ [(ngModel)]="cpInfo.type">
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label">{{ 'NAME' | translate }}</label>
+ <div class="col-sm-8">
+ <input type="text" class="form-control" placeholder="{{ 'NAME' | translate }}" name="name"
+ [(ngModel)]="cpInfo.name">
+ </div>
+ </div>
+ <button type="button" class="btn btn-primary btn-sm pull-right" (click)="saveCP(cpInfo.name)" placement="top"
+ ngbTooltip="Save">
+ <i class="fas fa-save"></i> {{'SAVE' | translate}}
+ </button>
+ </form>
+ </div>
+ </div>
+ </div>
+ <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 mb-2" *ngIf="showRightSideInfo === 'intcpInfo'">
+ <div class="row">
+ <div class="col-12 p-0">
+ <form>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label">{{ 'SHORTNAME' | translate }}</label>
+ <div class="col-sm-8">
+ <input type="text" class="form-control" name="shortName" [(ngModel)]="intcpInfo.shortName" disabled>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label">{{ 'TYPE' | translate }}</label>
+ <div class="col-sm-8">
+ <input type="text" class="form-control" name="type" [(ngModel)]="intcpInfo.type" disabled>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label">{{ 'ID' | translate }}</label>
+ <div class="col-sm-8">
+ <input type="text" class="form-control" name="id" [(ngModel)]="intcpInfo.id" disabled>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label">{{ 'NAME' | translate }}</label>
+ <div class="col-sm-8">
+ <input type="text" class="form-control" name="name" [(ngModel)]="intcpInfo.name" disabled>
+ </div>
+ </div>
+ </form>
+ </div>
+ </div>
+ </div>
+ </div>
+ </ng-sidebar>
+ <!-- Page content -->
+ <div ng-sidebar-content>
+ <button (click)="toggleSidebar()" class="btn btn-default" placement="right" ngbTooltip="{{'OPEN' | translate }}">
+ <i class="fa fa-arrow-right detail-sidebar" aria-hidden="true"></i>
+ </button>
+ </div>
+</ng-sidebar-container>
+<div class="container-fluid text-dark">
+ <div class="row bg-white vnf-composer-form">
+ <div class="col-xs-3 col-sm-3 col-md-3 col-lg-3 pl-0 px-0">
+ <div class="row">
+ <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 mb-2">
+ <fieldset class="p-2">
+ <legend class="element-legend">
+ {{'PAGE.TOPOLOGY.SELECTELEMENT' | translate}}
+ </legend>
+ <ul class="list-group list-group-flush dragable">
+ <li class="list-group-item" draggable="true" (dragstart)="drag($event)" id="vdu">
+ <img src="assets/images/VDU.svg" class="vnf-svg" draggable="false"/>
+ <span class="span-overflow-text font-weight-bold">{{'PAGE.TOPOLOGY.VDU' | translate}}</span>
+ <span class="drag-icon pull-right"><i class="fas fa-arrows-alt"></i></span>
+ </li>
+ <li class="list-group-item" draggable="true" (dragstart)="drag($event)" id="cp">
+ <img src="assets/images/CP-VNF.svg" class="vnf-svg" draggable="false"/>
+ <span class="span-overflow-text font-weight-bold">{{'PAGE.TOPOLOGY.CP' | translate}}</span>
+ <span class="drag-icon pull-right"><i class="fas fa-arrows-alt"></i></span>
+ </li>
+ <li class="list-group-item" draggable="true" (dragstart)="drag($event)" id="intvl">
+ <img src="assets/images/INTVL.svg" class="vnf-svg" draggable="false"/>
+ <span class="span-overflow-text font-weight-bold">{{'PAGE.TOPOLOGY.INTVL' | translate}}</span>
+ <span class="drag-icon pull-right"><i class="fas fa-arrows-alt"></i></span>
+ </li>
+ </ul>
+ </fieldset>
+ </div>
+ </div>
+ </div>
+ <div class="col-xs-9 col-sm-9 col-md-9 col-lg-9">
+ <div class="row">
+ <div class="col-xs-6 col-sm-6 col-md-6 col-lg-6 pl-0">
+ <div class="btn-group list" role="group" aria-label="Basic example">
+ <button type="button" class="btn btn-primary topology-btn" (click)="onFreeze()"
+ [class.pinned]="classApplied" placement="top" container="body" ngbTooltip="{{(classApplied ? 'UNFREEZE' : 'FREEZE') | translate}}">
+ <i class="fas fa-thumbtack"></i>
+ </button>
+ <button type="button" class="btn btn-primary topology-btn" (click)="onEdit()" placement="top"
+ container="body" ngbTooltip="{{'EDIT' | translate}}">
+ <i class="fas fa-edit"></i>
+ </button>
+ <button type="button" class="btn btn-primary topology-btn" (click)="showInfo()" placement="top"
+ container="body" ngbTooltip="{{'PAGE.TOPOLOGY.HELP' | translate}}">
+ <i class="fas fa-info"></i>
+ </button>
+ </div>
+ </div>
+ <div class="col-xs-6 col-sm-6 col-md-6 col-lg-6 text-right pr-0 badgegroup">
+ <span class="badge badge-primary badge-pill bg-white text-body font-weight-bold">
+ <img src="assets/images/VDU.svg" class="vnf-svg" draggable="false"/>
+ <br>{{'PAGE.TOPOLOGY.VDU' | translate}}</span>
+ <span class="badge badge-primary badge-pill bg-white text-body font-weight-bold">
+ <img src="assets/images/CP-VNF.svg" class="vnf-svg" draggable="false"/>
+ <br>{{'PAGE.TOPOLOGY.CP' | translate}}</span>
+ <span class="badge badge-primary badge-pill bg-white text-body font-weight-bold">
+ <img src="assets/images/INTVL.svg" class="vnf-svg" draggable="false"/>
+ <br>{{'PAGE.TOPOLOGY.INTVL' | translate}}</span>
+ <span class="badge badge-primary badge-pill bg-white text-body font-weight-bold">
+ <img src="assets/images/INTCP.svg" class="vnf-svg" draggable="false"/>
+ <br>{{'PAGE.TOPOLOGY.INTCP' | translate}}</span>
+ </div>
+ </div>
+ <div class="row border-all">
+ <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 svg-container">
+ <svg preserveAspectRatio="xMidYMin slice" (drop)="drop($event)" (dragover)="allowDrop($event)"
+ id="graphContainer" #graphContainer>
+ </svg>
+ </div>
+ </div>
+ </div>
+ </div>
+</div>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @file VNFComposerComponent
+ */
+import { HttpHeaders } from '@angular/common/http';
+import { Component, ElementRef, Injector, ViewChild, ViewEncapsulation } from '@angular/core';
+import { ActivatedRoute, Router } from '@angular/router';
+import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateService } from '@ngx-translate/core';
+import { NotifierService } from 'angular-notifier';
+import { APIURLHEADER, ERRORDATA, GETAPIURLHEADER, MODALCLOSERESPONSEDATA } from 'CommonModel';
+import { ConfirmationTopologyComponent } from 'ConfirmationTopology';
+import * as d3 from 'd3';
+import { DataService } from 'DataService';
+import { environment } from 'environment';
+import * as HttpStatus from 'http-status-codes';
+import * as jsyaml from 'js-yaml';
+import { RestService } from 'RestService';
+import { SharedService } from 'SharedService';
+import { isNullOrUndefined } from 'util';
+import {
+ COMPOSERNODES, CONNECTIONPOINT, GRAPHDETAILS, InternalVLD, Tick, TickPath,
+ VDU, VDUInternalConnectionPoint, VLDInternalConnectionPoint, VNFDInterface, VNFDNODE
+} from 'VNFDModel';
+
+/**
+ * Creating component
+ * @Component takes VNFComposerComponent.html as template url
+ */
+@Component({
+ templateUrl: './VNFComposerComponent.html',
+ styleUrls: ['./VNFComposerComponent.scss'],
+ encapsulation: ViewEncapsulation.None
+})
+/** Exporting a class @exports VNFComposerComponent */
+export class VNFComposerComponent {
+ /** To inject services @public */
+ public injector: Injector;
+ /** View child contains graphContainer ref @public */
+ @ViewChild('graphContainer', { static: true }) public graphContainer: ElementRef;
+ /** dataService to pass the data from one component to another @public */
+ public dataService: DataService;
+ /** random number count @public */
+ public randomNumberLength: number;
+ /** Contains the vnfd information @public */
+ public vnfList: string[] = [];
+ /** Contains node type @public */
+ public nodeTypeRef: string;
+ /** Contains VNFD Information @public */
+ public vnfdInfo: VNFDNODE = { shortName: '', description: '', version: '', id: '', name: '' };
+ /** Contains right panel box information @public */
+ public showRightSideInfo: string = '';
+ /** Add the fixed class for the freeze @public */
+ public fixedClass: string = 'fixed';
+ /** Check the loading results @public */
+ public isLoadingResults: boolean = true;
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+ /** Assign the forcesimulation active @public */
+ public forceSimulationActive: boolean = false;
+ /** Assign pinned class for the button when freezed @public */
+ public classApplied: boolean = false;
+ /** Contains sidebar open status @public */
+ public sideBarOpened: boolean = false;
+
+ /** Contains SVG attributes @private */
+ // tslint:disable-next-line:no-any
+ private svg: any;
+ /** Contains forced node animations @private */
+ // tslint:disable-next-line:no-any
+ private force: any;
+ /** Contains the Drag line */
+ // tslint:disable-next-line: no-any
+ private dragLine: any;
+ /** Contains id of the node @private */
+ private identifier: string;
+ /** Contains path information of the node */
+ // tslint:disable-next-line:no-any
+ private path: any;
+ /** Contains node network @private */
+ // tslint:disable-next-line:no-any
+ private network: any;
+ /** Contains node network @private */
+ // tslint:disable-next-line:no-any
+ private virutualDeploymentUnit: any;
+ /** Contains node connectionPoint @private */
+ // tslint:disable-next-line:no-any
+ private connectionPoint: any;
+ /** Contains node intConnectionPoint @private */
+ // tslint:disable-next-line:no-any
+ private intConnectionPoint: any;
+ /** Contains the node information @private */
+ private nodes: VNFDNODE[] = [];
+ /** Contains the link information of nodes @private */
+ private links: {}[] = [];
+ /** Instance of the rest service @private */
+ private restService: RestService;
+ /** Service holds the router information @private */
+ private router: Router;
+ /** Service contails all the shared service information @private */
+ private sharedService: SharedService;
+ /** Holds teh instance of AuthService class of type AuthService @private */
+ private activatedRoute: ActivatedRoute;
+ /** Notifier service to popup notification @private */
+ private notifierService: NotifierService;
+ /** Controls the header form @private */
+ private headers: HttpHeaders;
+ /** Contains tranlsate instance @private */
+ private translateService: TranslateService;
+ /** Rendered nodes represent network @private */
+ // tslint:disable-next-line:no-any
+ private gNetwork: any;
+ /** Rendered nodes represent VDU @private */
+ // tslint:disable-next-line:no-any
+ private gVirutualDeploymentUnit: any;
+ /** Rendered nodes represent connection point @private */
+ // tslint:disable-next-line:no-any
+ private gConnectionPoint: any;
+ /** Rendered nodes represent internal connection point @private */
+ // tslint:disable-next-line:no-any
+ private gIntConnectionPoint: any;
+ /** Contains all the information about VNF Details @private */
+ private vnfdPackageDetails: VNFDNODE;
+ /** Conatins mousedown action @private */
+ private mousedownNode: COMPOSERNODES = null;
+ /** Conatins mouseup action @private */
+ private mouseupNode: COMPOSERNODES = null;
+ /** Conatins current Selection node action @private */
+ private currentSelectedNode: COMPOSERNODES = null;
+ /** Add the activeNode for the selected @private */
+ private activeNode: string = 'active';
+ /** Contains lastkeypressed instance @private */
+ private lastKeyDown: number = -1;
+ /** Contains VDU Information @private */
+ private vduInfo: VDU;
+ /** Contains Internal VL Information @private */
+ private intvlInfo: InternalVLD;
+ /** Contains Connection Point Information @private */
+ private cpInfo: CONNECTIONPOINT;
+ /** Contains Internal Connection Point Information @private */
+ private intcpInfo: VLDInternalConnectionPoint;
+ /** Instance of the modal service @private */
+ private modalService: NgbModal;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.restService = this.injector.get(RestService);
+ this.dataService = this.injector.get(DataService);
+ this.router = this.injector.get(Router);
+ this.activatedRoute = this.injector.get(ActivatedRoute);
+ this.notifierService = this.injector.get(NotifierService);
+ this.translateService = this.injector.get(TranslateService);
+ this.sharedService = this.injector.get(SharedService);
+ this.modalService = this.injector.get(NgbModal);
+ }
+ /**
+ * Lifecyle Hooks the trigger before component is instantiate
+ */
+ public ngOnInit(): void {
+ // tslint:disable-next-line:no-backbone-get-set-outside-model
+ this.identifier = this.activatedRoute.snapshot.paramMap.get('id');
+ this.generateData();
+ this.headers = new HttpHeaders({
+ 'Content-Type': 'application/zip',
+ Accept: 'application/json',
+ 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
+ });
+ }
+
+ /** Prepare information for node creation of VNFD @public */
+ public generateData(): void {
+ this.nodes = []; this.links = []; this.vnfdPackageDetails = null;
+ this.showRightSideInfo = 'vnfdInfo';
+ const httpOptions: GETAPIURLHEADER = {
+ headers: new HttpHeaders({
+ 'Content-Type': 'application/zip',
+ Accept: 'text/plain',
+ 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
+ }),
+ responseType: 'text'
+ };
+ this.restService.getResource(environment.VNFPACKAGES_URL + '/' + this.identifier + '/vnfd', httpOptions)
+ .subscribe((vnfdPackageDetails: VNFDNODE) => {
+ try {
+ const getJson: string = jsyaml.load(vnfdPackageDetails.toString(), { json: true });
+ if (getJson.hasOwnProperty('vnfd-catalog')) {
+ this.vnfdPackageDetails = getJson['vnfd-catalog'].vnfd[0];
+ } else if (getJson.hasOwnProperty('vnfd:vnfd-catalog')) {
+ this.vnfdPackageDetails = getJson['vnfd:vnfd-catalog'].vnfd[0];
+ } else if (getJson.hasOwnProperty('vnfd')) {
+ // tslint:disable-next-line: no-string-literal
+ this.vnfdPackageDetails = getJson['vnfd'][0];
+ }
+ this.generateCPPoint(this.vnfdPackageDetails);
+ this.generateVDU(this.vnfdPackageDetails);
+ this.generateInternalVLD(this.vnfdPackageDetails);
+ this.generateInternalCP(this.vnfdPackageDetails);
+ this.generateIntVLCPLinks(this.vnfdPackageDetails);
+ this.generateVDUCPLinks(this.vnfdPackageDetails);
+ this.createNode(this.nodes);
+ this.vnfdInfo.shortName = this.vnfdPackageDetails['short-name'];
+ this.vnfdInfo.description = this.vnfdPackageDetails.description;
+ this.vnfdInfo.version = this.vnfdPackageDetails.version;
+ this.vnfdInfo.id = this.vnfdPackageDetails.id;
+ this.vnfdInfo.name = this.vnfdPackageDetails.name;
+ } catch (e) {
+ this.notifierService.notify('error', this.translateService.instant('ERROR'));
+ }
+ this.isLoadingResults = false;
+ }, (error: ERRORDATA) => {
+ error.error = typeof error.error === 'string' ? jsyaml.load(error.error) : error.error;
+ if (error.error.status === HttpStatus.NOT_FOUND || error.error.status === HttpStatus.UNAUTHORIZED) {
+ this.router.navigateByUrl('404', { skipLocationChange: true }).catch();
+ } else {
+ this.restService.handleError(error, 'get');
+ }
+ this.isLoadingResults = false;
+ this.showRightSideInfo = '';
+ });
+ }
+ /** Events handles at drag on D3 region @public */
+ // tslint:disable-next-line:no-any
+ public drag(ev: any): void {
+ ev.dataTransfer.setData('text', ev.target.id);
+ }
+ /** Events handles drop at D3 region @public */
+ public drop(ev: DragEvent): void {
+ ev.preventDefault();
+ this.nodeTypeRef = ev.dataTransfer.getData('text');
+ if (this.nodeTypeRef === 'vdu') {
+ this.svg.selectAll('*').remove();
+ this.vduDropCompose();
+ } else if (this.nodeTypeRef === 'cp') {
+ this.svg.selectAll('*').remove();
+ this.cpDropCompose();
+ } else if (this.nodeTypeRef === 'intvl') {
+ this.svg.selectAll('*').remove();
+ this.intvlDropCompose();
+ }
+ }
+ /** Events handles allow drop on D3 region @public */
+ public allowDrop(ev: DragEvent): void {
+ ev.preventDefault();
+ }
+ /** Generate and list CP points @public */
+ public generateCPPoint(vnfdPackageDetails: VNFDNODE): void {
+ if (vnfdPackageDetails['connection-point'] !== undefined) {
+ vnfdPackageDetails['connection-point'].forEach((cp: CONNECTIONPOINT) => {
+ this.nodes.push({ id: cp.name, nodeTypeRef: 'cp', name: cp.name, type: cp.type });
+ });
+ }
+ }
+ /** Generate and list VDU @public */
+ public generateVDU(vnfdPackageDetails: VNFDNODE): void {
+ if (vnfdPackageDetails.vdu !== undefined) {
+ vnfdPackageDetails.vdu.forEach((vdu: VDU) => {
+ this.nodes.push({
+ id: vdu.name, nodeTypeRef: 'vdu', 'cloud-init-file': vdu['cloud-init-file'], count: vdu.count, description: vdu.description,
+ vduID: vdu.id, name: vdu.name, interface: vdu.interface, 'vm-flavor': vdu['vm-flavor']
+ });
+ });
+ }
+ }
+ /** Generate and list Internal VLD @public */
+ public generateInternalVLD(vnfdPackageDetails: VNFDNODE): void {
+ if (vnfdPackageDetails['internal-vld'] !== undefined) {
+ vnfdPackageDetails['internal-vld'].forEach((internalVLD: InternalVLD) => {
+ this.nodes.push({
+ id: internalVLD.name, nodeTypeRef: 'intvl', intVLID: internalVLD.id,
+ 'internal-connection-point': internalVLD['internal-connection-point'],
+ 'ip-profile-ref': internalVLD['ip-profile-ref'], name: internalVLD.name, 'short-name': internalVLD['short-name'],
+ type: internalVLD.type
+ });
+ });
+ }
+ }
+ /** Generate and list Internal CP @public */
+ public generateInternalCP(vnfdPackageDetails: VNFDNODE): void {
+ if (vnfdPackageDetails.vdu !== undefined) {
+ vnfdPackageDetails.vdu.forEach((intCP: VDUInternalConnectionPoint) => {
+ if (intCP['internal-connection-point'] !== undefined) {
+ intCP['internal-connection-point'].forEach((internalCP: VDUInternalConnectionPoint) => {
+ this.nodes.push({
+ id: internalCP.name, nodeTypeRef: 'intcp', name: internalCP.name,
+ 'short-name': internalCP['short-name'], type: internalCP.type
+ });
+ });
+ }
+ });
+ }
+ }
+ /** Generate VDU External and Internal CP Links @public */
+ public generateVDUCPLinks(vnfdPackageDetails: VNFDNODE): void {
+ if (vnfdPackageDetails.vdu !== undefined) {
+ vnfdPackageDetails.vdu.forEach((vdu: VDU) => {
+ const vduLink: string = vdu.name;
+ if (vdu.interface !== undefined) {
+ vdu.interface.forEach((interfaceDetails: VNFDInterface) => {
+ if (interfaceDetails['external-connection-point-ref'] !== undefined) {
+ this.links.push({ source: vduLink, target: interfaceDetails['external-connection-point-ref'] });
+ }
+ if (interfaceDetails['internal-connection-point-ref'] !== undefined) {
+ this.links.push({ source: vduLink, target: interfaceDetails['internal-connection-point-ref'] });
+ }
+ });
+ }
+ });
+ }
+ }
+ /** Generate Network/VLD/Internal VirtualLink, CP Links @public */
+ public generateIntVLCPLinks(vnfdPackageDetails: VNFDNODE): void {
+ if (vnfdPackageDetails['internal-vld'] !== undefined) {
+ vnfdPackageDetails['internal-vld'].forEach((internalVLD: InternalVLD) => {
+ const vldName: string = internalVLD.name;
+ if (internalVLD['internal-connection-point'] !== undefined) {
+ internalVLD['internal-connection-point'].forEach((intCP: VLDInternalConnectionPoint) => {
+ this.links.push({ source: vldName, target: intCP['id-ref'] });
+ });
+ }
+ });
+ }
+ }
+ /** VNFD details can be saved on users inputs @public */
+ public saveVNFD(): void {
+ this.vnfdPackageDetails['short-name'] = this.vnfdInfo.shortName;
+ this.vnfdPackageDetails.description = this.vnfdInfo.description;
+ this.vnfdPackageDetails.version = this.vnfdInfo.version;
+ this.vnfdPackageDetails.id = this.vnfdInfo.id;
+ this.vnfdPackageDetails.name = this.vnfdInfo.name;
+ this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
+ delete this.vnfdPackageDetails.shortName;
+ }
+ /** VDU details can be saved on users inputs @public */
+ public saveVDU(vduID: string): void {
+ this.vnfdPackageDetails.vdu.forEach((ref: VDU) => {
+ if (ref.id === vduID) {
+ ref.count = this.vduInfo.count;
+ ref.description = this.vduInfo.description;
+ ref.image = this.vduInfo.image;
+ ref.id = this.vduInfo.id;
+ ref.name = this.vduInfo.name;
+ }
+ });
+ this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
+ }
+ /** IntVL details can be saved on users inputs @public */
+ public saveIntVL(intVLID: string): void {
+ this.vnfdPackageDetails['internal-vld'].forEach((ref: InternalVLD) => {
+ if (ref.id === intVLID) {
+ ref['short-name'] = this.intvlInfo.shortName;
+ ref.name = this.intvlInfo.name;
+ ref.type = this.intvlInfo.type;
+ ref['ip-profile-ref'] = !isNullOrUndefined(this.intvlInfo.ipProfileRef) ? this.intvlInfo.ipProfileRef : '';
+ ref.id = this.intvlInfo.id;
+ delete ref.shortName;
+ delete ref.ipProfileRef;
+ }
+ });
+ this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
+ }
+ /** IntVL details can be saved on users inputs @public */
+ public saveCP(cpName: string): void {
+ this.vnfdPackageDetails['connection-point'].forEach((ref: CONNECTIONPOINT) => {
+ if (ref.name === cpName) {
+ if (!isNullOrUndefined(this.cpInfo.type)) {
+ ref.type = this.cpInfo.type;
+ }
+ ref.name = this.cpInfo.name;
+ }
+ });
+ this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
+ }
+ /** Edit topology @public */
+ public onEdit(): void {
+ this.router.navigate(['/packages/vnf/edit/', this.identifier]).catch();
+ }
+ /** Show Info @public */
+ public showInfo(): void {
+ const modalRef: NgbModalRef = this.modalService.open(ConfirmationTopologyComponent, { backdrop: 'static' });
+ modalRef.componentInstance.topologyType = 'Info';
+ modalRef.componentInstance.topologytitle = this.translateService.instant('PAGE.TOPOLOGY.INFO');
+ modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
+ if (result) {
+ // empty
+ }
+ }).catch();
+ }
+ /** Event to freeze the animation @public */
+ public onFreeze(): void {
+ this.classApplied = !this.classApplied;
+ const alreadyFixedIsActive: boolean = d3.select('svg#graphContainer').classed(this.fixedClass);
+ d3.select('svg#graphContainer').classed(this.fixedClass, !alreadyFixedIsActive);
+ if (alreadyFixedIsActive) {
+ this.force.stop();
+ }
+ this.forceSimulationActive = alreadyFixedIsActive;
+ this.nodes.forEach((d: COMPOSERNODES) => {
+ d.fx = (alreadyFixedIsActive) ? null : d.x;
+ d.fy = (alreadyFixedIsActive) ? null : d.y;
+ });
+ if (alreadyFixedIsActive) {
+ this.force.restart();
+ }
+ }
+ /** Events handles when dragended @public */
+ public toggleSidebar(): void {
+ this.sideBarOpened = !this.sideBarOpened;
+ this.deselectAllNodes();
+ this.showRightSideInfo = 'vnfdInfo';
+ }
+ /** Get the default Configuration of containers @private */
+ private getGraphContainerAttr(): GRAPHDETAILS {
+ return {
+ width: 700,
+ height: 400,
+ nodeHeight: 50,
+ nodeWidth: 35,
+ textX: -35,
+ textY: 30,
+ radius: 5,
+ distance: 50,
+ strength: -500,
+ forcex: 2,
+ forcey: 2,
+ sourcePaddingYes: 17,
+ sourcePaddingNo: 12,
+ targetPaddingYes: 4,
+ targetPaddingNo: 3,
+ alphaTarget: 0.3,
+ imageX: -25,
+ imageY: -25,
+ shiftKeyCode: 17
+ };
+ }
+ /** Node is created and render at D3 region @private */
+ private createNode(nodes: VNFDNODE[]): void {
+ const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
+ d3.selectAll('svg#graphContainer > *').remove();
+ d3.select(window).on('keydown', () => { this.keyDown(); });
+ d3.select(window).on('keyup', () => { this.keyUp(); });
+ this.svg = d3.select('#graphContainer').attr('oncontextmenu', 'return false;').attr('width', graphContainerAttr.width)
+ .attr('height', graphContainerAttr.height).on('mousemove', () => { this.mousemove(); });
+ this.force = d3.forceSimulation()
+ .force('link', d3.forceLink().id((d: TickPath) => d.id).distance(graphContainerAttr.distance))
+ .force('charge', d3.forceManyBody().strength(graphContainerAttr.strength))
+ .force('x', d3.forceX(graphContainerAttr.width / graphContainerAttr.forcex))
+ .force('y', d3.forceY(graphContainerAttr.height / graphContainerAttr.forcey))
+ .on('tick', () => { this.tick(); });
+ this.path = this.svg.append('svg:g').selectAll('path');
+ this.dragLine = this.svg.append('svg:path').attr('class', 'link dragline hidden').attr('d', 'M0,0L0,0');
+ this.network = this.svg.append('svg:g').selectAll('network');
+ this.virutualDeploymentUnit = this.svg.append('svg:g').selectAll('virutualDeploymentUnit');
+ this.connectionPoint = this.svg.append('svg:g').selectAll('connectionPoint');
+ this.intConnectionPoint = this.svg.append('svg:g').selectAll('intConnectionPoint');
+ this.restart(nodes);
+ }
+ /** Update force layout (called automatically each iteration) @private */
+ private tick(): void {
+ const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
+ this.path.attr('d', (d: Tick) => {
+ const deltaX: number = d.target.x - d.source.x; const deltaY: number = d.target.y - d.source.y;
+ const dist: number = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
+ const normX: number = deltaX / dist; const normY: number = deltaY / dist;
+ const sourcePadding: number = d.left ? graphContainerAttr.sourcePaddingYes : graphContainerAttr.sourcePaddingNo;
+ const targetPadding: number = d.right ? graphContainerAttr.targetPaddingYes : graphContainerAttr.targetPaddingNo;
+ const sourceX: number = d.source.x + (sourcePadding * normX); const sourceY: number = d.source.y + (sourcePadding * normY);
+ const targetX: number = d.target.x - (targetPadding * normX); const targetY: number = d.target.y - (targetPadding * normY);
+ return `M${sourceX},${sourceY}L${targetX},${targetY}`;
+ }).on('dblclick', (d: Tick) => { this.getDeleteLinkConfirmation(d); });
+ this.network.attr('transform', (d: TickPath) => `translate(${d.x},${d.y})`);
+ this.virutualDeploymentUnit.attr('transform', (d: TickPath) => `translate(${d.x},${d.y})`);
+ this.connectionPoint.attr('transform', (d: TickPath) => `translate(${d.x},${d.y})`);
+ this.intConnectionPoint.attr('transform', (d: TickPath) => `translate(${d.x},${d.y})`);
+ }
+ /** Update graph (called when needed) @private */
+ private restart(nodes: VNFDNODE[]): void {
+ const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
+ this.path = this.path.data(this.links);
+ const cpNodes: {}[] = []; const vduNodes: {}[] = []; const vlNodes: {}[] = []; const intcpNodes: {}[] = []; //Nodes are known by id
+ nodes.forEach((nodeList: VNFDNODE) => {
+ if (nodeList.nodeTypeRef === 'cp') { cpNodes.push(nodeList); }
+ else if (nodeList.nodeTypeRef === 'vdu') { vduNodes.push(nodeList); }
+ else if (nodeList.nodeTypeRef === 'intvl') { vlNodes.push(nodeList); }
+ else if (nodeList.nodeTypeRef === 'intcp') { intcpNodes.push(nodeList); }
+ });
+ this.network = this.network.data(vlNodes, (d: { id: number }) => d.id);
+ this.virutualDeploymentUnit = this.virutualDeploymentUnit.data(vduNodes, (d: { id: number }) => d.id);
+ this.connectionPoint = this.connectionPoint.data(cpNodes, (d: { id: number }) => d.id);
+ this.intConnectionPoint = this.intConnectionPoint.data(intcpNodes, (d: { id: number }) => d.id);
+ this.resetAndCreateNodes();
+ this.force.nodes(nodes).force('link').links(this.links); //Set the graph in motion
+ this.force.alphaTarget(graphContainerAttr.alphaTarget).restart();
+ }
+ /** Rest and create nodes @private */
+ private resetAndCreateNodes(): void {
+ this.path.exit().remove();
+ this.network.exit().remove();
+ this.virutualDeploymentUnit.exit().remove();
+ this.connectionPoint.exit().remove();
+ this.intConnectionPoint.exit().remove();
+ this.getPathNodes();
+ this.getgNetwork();
+ this.getgVirutualDeploymentUnit();
+ this.getgConnectionPoint();
+ this.getgIntConnectionPoint();
+ this.network = this.gNetwork.merge(this.network);
+ this.virutualDeploymentUnit = this.gVirutualDeploymentUnit.merge(this.virutualDeploymentUnit);
+ this.connectionPoint = this.gConnectionPoint.merge(this.connectionPoint);
+ this.intConnectionPoint = this.gIntConnectionPoint.merge(this.intConnectionPoint);
+ this.path.merge(this.path);
+ }
+ /** Setting the Path @private */
+ private getPathNodes(): void {
+ this.path = this.path.enter().append('svg:path').attr('class', 'link');
+ }
+ /** Settings all the network attributes of nodes @private */
+ private getgNetwork(): void {
+ const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
+ this.gNetwork = this.network.enter().append('svg:g');
+ this.gNetwork.append('svg:circle').attr('r', graphContainerAttr.radius).style('fill', '#eeeeee');
+ this.gNetwork.append('svg:image')
+ .style('opacity', 1)
+ .attr('x', graphContainerAttr.imageX)
+ .attr('y', graphContainerAttr.imageY)
+ .attr('id', (d: VNFDNODE) => { return d.id; })
+ .attr('class', 'node').attr('width', graphContainerAttr.nodeWidth).attr('height', graphContainerAttr.nodeHeight)
+ .attr('xlink:href', 'assets/images/INTVL.svg')
+ .on('mousedown', (d: VNFDNODE) => { this.mouseDown(d); })
+ .on('mouseup', (d: VNFDNODE) => { this.mouseUp(d); })
+ .on('click', (d: VNFDNODE) => { this.singleClick(this.network, d); this.onNodeClickToggleSidebar(); })
+ .on('dblclick', (d: VNFDNODE) => { this.getDeleteNodeConfirmation(d); this.onNodedblClickToggleSidebar(); });
+ this.gNetwork.append('svg:text')
+ .attr('class', 'node_text')
+ .attr('y', graphContainerAttr.textY)
+ .text((d: { id: number }) => d.id);
+ }
+ /** Settings all the connection point attributes of nodes @private */
+ private getgVirutualDeploymentUnit(): void {
+ const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
+ this.gVirutualDeploymentUnit = this.virutualDeploymentUnit.enter().append('svg:g');
+ this.gVirutualDeploymentUnit.append('svg:circle').attr('r', graphContainerAttr.radius).style('fill', '#eeeeee');
+ this.gVirutualDeploymentUnit.append('svg:image')
+ .style('opacity', 1)
+ .attr('x', graphContainerAttr.imageX)
+ .attr('y', graphContainerAttr.imageY)
+ .attr('id', (d: VNFDNODE) => { return d.id; })
+ .attr('class', 'node').attr('width', graphContainerAttr.nodeWidth).attr('height', graphContainerAttr.nodeHeight)
+ .attr('xlink:href', 'assets/images/VDU.svg')
+ .on('mousedown', (d: VNFDNODE) => { this.mouseDown(d); })
+ .on('mouseup', (d: VNFDNODE) => { this.mouseUp(d); })
+ .on('click', (d: VNFDNODE) => { this.singleClick(this.virutualDeploymentUnit, d); this.onNodeClickToggleSidebar(); })
+ .on('dblclick', (d: VNFDNODE) => { this.getDeleteNodeConfirmation(d); this.onNodedblClickToggleSidebar(); });
+ this.gVirutualDeploymentUnit.append('svg:text')
+ .attr('class', 'node_text')
+ .attr('y', graphContainerAttr.textY)
+ .text((d: { id: string }) => d.id);
+ }
+ /** Settings all the connection point attributes of nodes @private */
+ private getgConnectionPoint(): void {
+ const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
+ this.gConnectionPoint = this.connectionPoint.enter().append('svg:g');
+ this.gVirutualDeploymentUnit.append('svg:circle').attr('r', graphContainerAttr.radius).style('fill', '#eeeeee');
+ this.gConnectionPoint.append('svg:image')
+ .style('opacity', 1)
+ .attr('x', graphContainerAttr.imageX)
+ .attr('y', graphContainerAttr.imageY)
+ .attr('id', (d: VNFDNODE) => { return d.id; })
+ .attr('class', 'node').attr('width', graphContainerAttr.nodeWidth).attr('height', graphContainerAttr.nodeHeight)
+ .attr('xlink:href', 'assets/images/CP-VNF.svg')
+ .on('mousedown', (d: VNFDNODE) => { this.mouseDown(d); })
+ .on('mouseup', (d: VNFDNODE) => { this.mouseUp(d); })
+ .on('click', (d: VNFDNODE) => { this.singleClick(this.connectionPoint, d); this.onNodeClickToggleSidebar(); })
+ .on('dblclick', (d: VNFDNODE) => { this.getDeleteNodeConfirmation(d); this.onNodedblClickToggleSidebar(); });
+ this.gConnectionPoint.append('svg:text')
+ .attr('class', 'node_text')
+ .attr('y', graphContainerAttr.textY)
+ .text((d: { id: string }) => d.id);
+ }
+ /** Settings all the internal connection point attributes of nodes @private */
+ private getgIntConnectionPoint(): void {
+ const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
+ this.gIntConnectionPoint = this.intConnectionPoint.enter().append('svg:g');
+ this.gIntConnectionPoint.append('svg:circle').attr('r', graphContainerAttr.radius).style('fill', '#eeeeee');
+ this.gIntConnectionPoint.append('svg:image')
+ .style('opacity', 1)
+ .attr('x', graphContainerAttr.imageX)
+ .attr('y', graphContainerAttr.imageY)
+ .attr('id', (d: VNFDNODE) => { return d.id; })
+ .attr('class', 'node').attr('width', graphContainerAttr.nodeWidth).attr('height', graphContainerAttr.nodeHeight)
+ .attr('xlink:href', 'assets/images/INTCP.svg')
+ .on('mousedown', (d: VNFDNODE) => { this.mouseDown(d); })
+ .on('mouseup', (d: VNFDNODE) => { this.mouseUp(d); })
+ .on('click', (d: VNFDNODE) => { this.singleClick(this.intConnectionPoint, d); this.onNodeClickToggleSidebar(); })
+ .on('dblclick', (d: VNFDNODE) => { this.getDeleteNodeConfirmation(d); this.onNodedblClickToggleSidebar(); });
+ this.gIntConnectionPoint.append('svg:text')
+ .attr('class', 'node_text')
+ .attr('y', graphContainerAttr.textY)
+ .text((d: { id: string }) => d.id);
+ }
+ /** Drop VDU Composer Data @private */
+ private vduDropCompose(): void {
+ const randomID: string = this.sharedService.randomString();
+ const vduNode: VNFDNODE[] = [{
+ nodeTypeRef: 'vdu', id: 'vdu_' + randomID, count: 1, description: '', name: 'vdu_' + randomID, image: 'ubuntu',
+ interface: [], 'internal-connection-point': [], 'monitoring-param': [], 'vm-flavor': {}
+ }];
+ const nodeCopy: VNFDNODE[] = this.nodes;
+ Array.prototype.push.apply(vduNode, nodeCopy);
+ this.nodes = vduNode;
+ if (this.vnfdPackageDetails.vdu === undefined) { this.vnfdPackageDetails.vdu = []; }
+ this.vnfdPackageDetails.vdu.push({
+ id: 'vdu_' + randomID, count: 1, description: '', name: 'vdu_' + randomID, image: 'ubuntu',
+ interface: [], 'internal-connection-point': [], 'monitoring-param': [], 'vm-flavor': {}
+ });
+ this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
+ }
+ /** Drop CP Composer Data @private */
+ private cpDropCompose(): void {
+ const randomID: string = this.sharedService.randomString();
+ const cpNode: VNFDNODE[] = [{ nodeTypeRef: 'cp', id: 'cp_' + randomID, name: 'cp_' + randomID }];
+ const nodeCopy: VNFDNODE[] = this.nodes;
+ Array.prototype.push.apply(cpNode, nodeCopy);
+ this.nodes = cpNode;
+ if (this.vnfdPackageDetails['connection-point'] === undefined) {
+ this.vnfdPackageDetails['connection-point'] = [];
+ }
+ this.vnfdPackageDetails['connection-point'].push({
+ id: 'cp_' + randomID, name: 'cp_' + randomID, type: 'VPORT'
+ });
+ this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
+ }
+ /** Drop IntVL Composer Data @private */
+ private intvlDropCompose(): void {
+ const randomID: string = this.sharedService.randomString();
+ const intvlNode: VNFDNODE[] = [{
+ nodeTypeRef: 'intvl', id: 'vnf_vl_' + randomID, name: 'vnf_vl_' + randomID, 'short-name': 'vnf_vl_' + randomID, 'ip-profile-ref': '',
+ type: 'ELAN'
+ }];
+ const nodeCopy: VNFDNODE[] = this.nodes;
+ Array.prototype.push.apply(intvlNode, nodeCopy);
+ this.nodes = intvlNode;
+ if (this.vnfdPackageDetails['internal-vld'] === undefined) { this.vnfdPackageDetails['internal-vld'] = []; }
+ this.vnfdPackageDetails['internal-vld'].push({
+ id: 'vnf_vl_' + randomID, name: 'vnf_vl_' + randomID, 'short-name': 'vnf_vl_' + randomID,
+ 'ip-profile-ref': '', type: 'ELAN', 'internal-connection-point': []
+ });
+ this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
+ }
+ /** Add the Add Nodes Data @private */
+ private addNodes(apiURL: string, identifier: string, data: VNFDNODE): void {
+ this.isLoadingResults = true;
+ const apiURLHeader: APIURLHEADER = {
+ url: apiURL + '/' + identifier + '/package_content',
+ httpOptions: { headers: this.headers }
+ };
+ const vnfData: {} = {};
+ vnfData['vnfd:vnfd-catalog'] = {};
+ vnfData['vnfd:vnfd-catalog'].vnfd = [];
+ vnfData['vnfd:vnfd-catalog'].vnfd.push(data);
+ const descriptorInfo: string = jsyaml.dump(vnfData, { sortKeys: true });
+ this.sharedService.targzFile({ packageType: 'vnfd', id: this.identifier, descriptor: descriptorInfo })
+ .then((content: ArrayBuffer): void => {
+ this.restService.putResource(apiURLHeader, content).subscribe((res: {}) => {
+ this.generateData();
+ this.notifierService.notify('success', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.UPDATEDSUCCESSFULLY'));
+ this.isLoadingResults = false;
+ }, (error: ERRORDATA) => {
+ this.generateData();
+ this.restService.handleError(error, 'put');
+ this.isLoadingResults = false;
+ });
+ }).catch((): void => {
+ this.notifierService.notify('error', this.translateService.instant('ERROR'));
+ this.isLoadingResults = false;
+ });
+ }
+ /** Events handles when mousedown click it will capture the selected node data @private */
+ private mouseDown(d: VNFDNODE): void {
+ event.preventDefault();
+ if (d3.event.ctrlKey) { return; }
+ if (d3.event.shiftKey) {
+ this.mousedownNode = d;
+ this.currentSelectedNode = (this.mousedownNode === this.currentSelectedNode) ? null : this.mousedownNode;
+ this.dragLine.classed('hidden', false)
+ .attr('d', `M${this.mousedownNode.x},${this.mousedownNode.y}L${this.mousedownNode.x},${this.mousedownNode.y}`);
+ }
+ }
+ /** Event handles when mouseup event occures @private */
+ private mouseUp(d: VNFDNODE): void {
+ if (!this.mousedownNode) { return; }
+ this.dragLine.classed('hidden', true);
+ this.mouseupNode = d;
+ if (this.mousedownNode.nodeTypeRef === 'vdu' && this.mouseupNode.nodeTypeRef === 'intcp') {
+ this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKVDUANDINTCP'));
+ this.deselectPath();
+ }
+ else if (this.mousedownNode.nodeTypeRef === 'vdu' && this.mouseupNode.nodeTypeRef === 'vdu') {
+ this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKVDUANDVDU'));
+ this.deselectPath();
+ }
+ else if (this.mousedownNode.nodeTypeRef === 'intcp' && this.mouseupNode.nodeTypeRef === 'vdu') {
+ this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKINTCPANDVDU'));
+ this.deselectPath();
+ }
+ else if (this.mousedownNode.nodeTypeRef === 'cp' && this.mouseupNode.nodeTypeRef === 'intvl') {
+ this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKCPANDVNFVL'));
+ this.deselectPath();
+ }
+ else if (this.mousedownNode.nodeTypeRef === 'intvl' && this.mouseupNode.nodeTypeRef === 'cp') {
+ this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKVNFVLANDCP'));
+ this.deselectPath();
+ }
+ else if (this.mousedownNode.nodeTypeRef === 'intcp' && this.mouseupNode.nodeTypeRef === 'cp') {
+ this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKINTCPANDCP'));
+ this.deselectPath();
+ }
+ else if (this.mousedownNode.nodeTypeRef === 'cp' && this.mouseupNode.nodeTypeRef === 'intcp') {
+ this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.CANNOTLINKCPANDINTCP'));
+ this.deselectPath();
+ } else if (this.mousedownNode.nodeTypeRef === 'vdu' && this.mouseupNode.nodeTypeRef === 'cp') {
+ this.vnfdPackageDetails.vdu.forEach((vduDetails: VDU) => {
+ if (vduDetails.id === this.mousedownNode.id) {
+ if (vduDetails.interface === undefined) { vduDetails.interface = []; }
+ vduDetails.interface.push({
+ 'external-connection-point-ref': this.mouseupNode.id, 'mgmt-interface': true,
+ name: 'eth_' + this.sharedService.randomString(),
+ 'virtual-interface': { type: 'VIRTIO' },
+ type: 'EXTERNAL'
+ });
+ if (vduDetails['internal-connection-point'] === undefined) {
+ vduDetails['internal-connection-point'] = [];
+ }
+ if (vduDetails['monitoring-param'] === undefined) {
+ vduDetails['monitoring-param'] = [];
+ }
+ if (vduDetails['vm-flavor'] === undefined) {
+ vduDetails['vm-flavor'] = {};
+ }
+ }
+ });
+ this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
+ this.deselectPath();
+ } else if (this.mousedownNode.nodeTypeRef === 'vdu' && this.mouseupNode.nodeTypeRef === 'intvl') {
+ const setIntCP: string = 'intcp_' + this.sharedService.randomString();
+ this.vnfdPackageDetails['internal-vld'].forEach((vldInternal: InternalVLD) => {
+ if (vldInternal.id === this.mouseupNode.id) {
+ if (vldInternal['internal-connection-point'] === undefined) { vldInternal['internal-connection-point'] = []; }
+ vldInternal['internal-connection-point'].push({ 'id-ref': setIntCP });
+ }
+ });
+ this.vnfdPackageDetails.vdu.forEach((vduDetails: VDU) => {
+ if (vduDetails.id === this.mousedownNode.id) {
+ if (vduDetails.interface === undefined) {
+ vduDetails.interface = [];
+ }
+ vduDetails.interface.push({
+ 'internal-connection-point-ref': setIntCP, name: 'int_' + setIntCP, type: 'INTERNAL', 'virtual-interface': { type: 'VIRTIO' }
+ });
+ if (vduDetails['internal-connection-point'] === undefined) {
+ vduDetails['internal-connection-point'] = [];
+ }
+ vduDetails['internal-connection-point'].push({
+ id: setIntCP, name: setIntCP, 'short-name': setIntCP, type: 'VPORT'
+ });
+ }
+ });
+ this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
+ this.deselectPath();
+ }
+ else {
+ this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.INVALIDSELECTION'));
+ this.deselectPath();
+ }
+ this.resetMouseActions();
+ this.currentSelectedNode = null;
+ }
+ /** Events handles when mousemove it will capture the selected node data @private */
+ private mousemove(): void {
+ if (!this.mousedownNode) { return; }
+ this.dragLine.attr('d',
+ `M${this.mousedownNode.x},${this.mousedownNode.y}L${d3.mouse(d3.event.currentTarget)[0]},${d3.mouse(d3.event.currentTarget)[1]}`);
+ }
+ /** reset Mouse varaibles @private */
+ private resetMouseActions(): void {
+ this.mousedownNode = null;
+ this.mouseupNode = null;
+ }
+ /** Key press event @private */
+ private keyDown(): void {
+ const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
+ if (this.lastKeyDown !== -1) { return; }
+ this.lastKeyDown = d3.event.keyCode;
+ if (d3.event.keyCode === graphContainerAttr.shiftKeyCode) {
+ this.gNetwork.call(d3.drag().on('start', this.dragstarted).on('drag', this.dragged).on('end', this.dragended));
+ this.gVirutualDeploymentUnit.call(d3.drag().on('start', this.dragstarted).on('drag', this.dragged).on('end', this.dragended));
+ this.gConnectionPoint.call(d3.drag().on('start', this.dragstarted).on('drag', this.dragged).on('end', this.dragended));
+ this.gIntConnectionPoint.call(d3.drag().on('start', this.dragstarted).on('drag', this.dragged).on('end', this.dragended));
+ this.svg.classed('ctrl', true);
+ }
+ }
+ /** Key realse event @private */
+ private keyUp(): void {
+ const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
+ this.lastKeyDown = -1;
+ if (d3.event.keyCode === graphContainerAttr.shiftKeyCode) {
+ this.gNetwork.on('.drag', null);
+ this.gVirutualDeploymentUnit.on('.drag', null);
+ this.gConnectionPoint.on('.drag', null);
+ this.gIntConnectionPoint.on('.drag', null);
+ this.svg.classed('ctrl', false);
+ }
+ }
+ /** Mosue Drag Line false if it is not satisfied @private */
+ private deselectPath(): void {
+ this.dragLine.classed('hidden', true).attr('d', 'M0,0L0,0');
+ }
+ /** Events handles when Shift Click to perform create cp @private */
+ // tslint:disable-next-line: no-any
+ private singleClick(nodeSelected: any, d: VNFDNODE): void {
+ this.selectedNode(nodeSelected, d);
+ }
+ /** Get confirmation Before Deleting the Node in Topology @private */
+ private getDeleteNodeConfirmation(d: VNFDNODE): void {
+ const modalRef: NgbModalRef = this.modalService.open(ConfirmationTopologyComponent, { backdrop: 'static' });
+ modalRef.componentInstance.topologyType = 'Delete';
+ modalRef.componentInstance.topologyname = d.name;
+ if (d.nodeTypeRef === 'vdu') {
+ modalRef.componentInstance.topologytitle = 'PAGE.TOPOLOGY.VDU';
+ } else if (d.nodeTypeRef === 'intvl') {
+ modalRef.componentInstance.topologytitle = 'PAGE.TOPOLOGY.INTVL';
+ } else if (d.nodeTypeRef === 'cp') {
+ modalRef.componentInstance.topologytitle = 'PAGE.TOPOLOGY.CONNECTIONPOINT';
+ } else if (d.nodeTypeRef === 'intcp') {
+ modalRef.componentInstance.topologytitle = 'PAGE.TOPOLOGY.INTCP';
+ }
+ modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
+ if (result) {
+ this.deleteNode(d);
+ }
+ }).catch();
+ }
+ /** Delete nodes @private */
+ private deleteNode(d: VNFDNODE): void {
+ const deletedNode: VNFDNODE = d;
+ this.nodes.forEach((node: VNFDNODE) => {
+ if (node.id === d.id) {
+ if (deletedNode.nodeTypeRef === 'cp') {
+ if (this.vnfdPackageDetails.vdu !== undefined) {
+ this.vnfdPackageDetails.vdu.forEach((vduDetails: VDU) => {
+ if (vduDetails.interface !== undefined) {
+ const interfacePos: number = vduDetails.interface.map((e: VNFDInterface) => { return e['external-connection-point-ref']; })
+ .indexOf(d.id);
+ if (interfacePos >= 0) {
+ vduDetails.interface.splice(interfacePos, 1);
+ }
+ }
+ });
+ }
+ const cpPos: number = this.vnfdPackageDetails['connection-point'].map((e: CONNECTIONPOINT) => { return e.name; })
+ .indexOf(d.id);
+ if (cpPos >= 0) {
+ this.vnfdPackageDetails['connection-point'].splice(cpPos, 1);
+ }
+ } else if (deletedNode.nodeTypeRef === 'intcp') {
+ this.vnfdPackageDetails.vdu.forEach((vduDetails: VDU) => {
+ // Delete Interface
+ const interfacePos: number = vduDetails.interface.map((e: VNFDInterface) => { return e['internal-connection-point-ref']; })
+ .indexOf(d.id);
+ if (interfacePos >= 0) {
+ vduDetails.interface.splice(interfacePos, 1);
+ }
+ // Delete Internal CP
+ const interCPPos: number = vduDetails['internal-connection-point']
+ .map((e: VDUInternalConnectionPoint) => { return e.id; })
+ .indexOf(d.id);
+ if (interCPPos >= 0) {
+ vduDetails['internal-connection-point'].splice(interCPPos, 1);
+ }
+ });
+ if (this.vnfdPackageDetails['internal-vld'] !== undefined && this.vnfdPackageDetails['internal-vld'].length > 0) {
+ this.vnfdPackageDetails['internal-vld'].forEach((internalVLD: InternalVLD) => {
+ const interfacePos: number = internalVLD['internal-connection-point']
+ .map((e: VLDInternalConnectionPoint) => { return e['id-ref']; }).indexOf(d.id);
+ if (interfacePos >= 0) {
+ internalVLD['internal-connection-point'].splice(interfacePos, 1);
+ }
+ });
+ }
+ } else if (deletedNode.nodeTypeRef === 'intvl') {
+ const intvlPos: number = this.vnfdPackageDetails['internal-vld']
+ .map((e: InternalVLD) => { return e.name; }).indexOf(d.id);
+ if (intvlPos >= 0) {
+ this.vnfdPackageDetails['internal-vld'].splice(intvlPos, 1);
+ }
+ } else if (deletedNode.nodeTypeRef === 'vdu') {
+ const internalCPList: string[] = [];
+ if (deletedNode.interface !== undefined && deletedNode.interface.length > 0) {
+ deletedNode.interface.forEach((interfaceNode: InternalVLD) => {
+ if (interfaceNode['internal-connection-point-ref'] !== undefined) {
+ internalCPList.push(interfaceNode['internal-connection-point-ref']);
+ }
+ });
+ }
+ internalCPList.forEach((list: string) => {
+ if (this.vnfdPackageDetails['internal-vld'] !== undefined && this.vnfdPackageDetails['internal-vld'].length > 0) {
+ this.vnfdPackageDetails['internal-vld'].forEach((internalVLD: InternalVLD) => {
+ const interfacePos: number = internalVLD['internal-connection-point']
+ .map((e: VLDInternalConnectionPoint) => { return e['id-ref']; }).indexOf(list);
+ if (interfacePos >= 0) {
+ internalVLD['internal-connection-point'].splice(interfacePos, 1);
+ }
+ });
+ }
+ });
+ const vduPos: number = this.vnfdPackageDetails.vdu.map((e: VDU) => { return e.id; }).indexOf(d.id);
+ if (vduPos >= 0) {
+ this.vnfdPackageDetails.vdu.splice(vduPos, 1);
+ }
+ } else {
+ this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.INVALIDSELECTION'));
+ }
+ this.addNodes(environment.VNFPACKAGES_URL, this.identifier, this.vnfdPackageDetails);
+ }
+ });
+ }
+ /** Get confirmation before deleting the ink in Topology @private */
+ private getDeleteLinkConfirmation(d: Tick): void {
+ this.notifierService.notify('warning', this.translateService.instant('PAGE.VNFPACKAGE.VNFCOMPOSE.YOUCANNOTDELETELINK'));
+ }
+ /** Selected nodes @private */
+ // tslint:disable-next-line: no-any
+ private selectedNode(nodeSeleced: any, d: VNFDNODE): void {
+ const alreadyIsActive: boolean = nodeSeleced.select('#' + d.id).classed(this.activeNode);
+ this.deselectAllNodes();
+ nodeSeleced.select('#' + d.id).classed(this.activeNode, !alreadyIsActive);
+ if (d.nodeTypeRef === 'vdu' && !alreadyIsActive) {
+ this.vnfdPackageDetails.vdu.forEach((res: VDU) => {
+ if (res.name === d.id) {
+ this.showRightSideInfo = 'vduInfo';
+ this.vduInfo = res;
+ }
+ });
+ } else if (d.nodeTypeRef === 'intvl' && !alreadyIsActive) {
+ this.vnfdPackageDetails['internal-vld'].forEach((res: InternalVLD) => {
+ if (res.name === d.id) {
+ this.showRightSideInfo = 'intvlInfo';
+ this.intvlInfo = res;
+ this.intvlInfo.shortName = res['short-name'];
+ this.intvlInfo.ipProfileRef = res['ip-profile-ref'];
+ }
+ });
+ } else if (d.nodeTypeRef === 'cp' && !alreadyIsActive) {
+ this.vnfdPackageDetails['connection-point'].forEach((res: CONNECTIONPOINT) => {
+ if (res.name === d.id) {
+ this.showRightSideInfo = 'cpInfo';
+ this.cpInfo = res;
+ }
+ });
+ }
+ else if (d.nodeTypeRef === 'intcp' && !alreadyIsActive) {
+ this.intcpInfo = d;
+ this.showRightSideInfo = 'intcpInfo';
+ this.intcpInfo.shortName = d['short-name'];
+ } else {
+ this.showRightSideInfo = 'vnfdInfo';
+ }
+ }
+ /** De-select all the selected nodes @private */
+ private deselectAllNodes(): void {
+ this.network.select('image').classed(this.activeNode, false);
+ this.virutualDeploymentUnit.select('image').classed(this.activeNode, false);
+ this.connectionPoint.select('image').classed(this.activeNode, false);
+ this.intConnectionPoint.select('image').classed(this.activeNode, false);
+ }
+ /** Events handles when dragstarted @private */
+ private dragstarted(d: COMPOSERNODES): void {
+ d.fx = d.x;
+ d.fy = d.y;
+ }
+ /** Events handles when dragged @private */
+ private dragged(d: COMPOSERNODES): void {
+ d.fx = d.x = d3.event.x;
+ d.fy = d.y = d3.event.y;
+ }
+ /** Events handles when dragended @private */
+ private dragended(d: COMPOSERNODES): void {
+ if (this.forceSimulationActive) {
+ d.fx = null;
+ d.fy = null;
+ } else {
+ d.fx = d.x;
+ d.fy = d.y;
+ this.forceSimulationActive = false;
+ }
+ }
+ /** Events handles when node double click @private */
+ private onNodedblClickToggleSidebar(): void {
+ this.sideBarOpened = false;
+ }
+ /** Events handles when node single click @private */
+ private onNodeClickToggleSidebar(): void {
+ this.sideBarOpened = true;
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="modal-header">
+ <h4 class="modal-title" id="modal-basic-title">{{'FILES' | translate}} {{'IN' | translate}}
+ {{(params.id)?params.id:'-'}}</h4>
+ <button class="button-xs" type="button" class="close" aria-label="Close" (click)="activeModal.dismiss('Cross click')">
+ <i class="fas fa-times-circle text-danger"></i>
+ </button>
+</div>
+<div class="modal-body">
+ <table class="table table-bored show-content" *ngIf="contents else noData">
+ <tr>
+ <th># {{'FILES' | translate}} {{'NAME' | translate}}</th>
+ <th>{{'ACTIONS' | translate }}</th>
+ </tr>
+ <tr *ngFor="let data of contents">
+ <td>- {{(data)?data:'-'}}</td>
+ <td>
+ <button class="btn btn-xs">
+ <i class="far fa-folder-open icons"></i>
+ </button>
+ </td>
+ </tr>
+ </table>
+ <ng-template #noData>{{'NODATAERROR' | translate}}</ng-template>
+</div>
+<div class="modal-footer">
+ <button type="button" class="btn btn-danger" (click)="activeModal.close()">{{'CANCEL' | translate}}</button>
+</div>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file Show content modal
+ */
+import { Component, Injector, Input, OnInit } from '@angular/core';
+import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
+import { ERRORDATA, URLPARAMS } from 'CommonModel';
+import { environment } from 'environment';
+import { RestService } from 'RestService';
+
+/** Shows json data in the information modal */
+const defaults: {} = { 'text/json': '' };
+
+/**
+ * Creating component
+ * @Component takes ShowContentComponent.html as template url
+ */
+@Component({
+ selector: 'app-show-content',
+ templateUrl: './ShowContentComponent.html',
+ styleUrls: ['./ShowContentComponent.scss']
+})
+/** Exporting a class @exports ShowContentComponent */
+export class ShowContentComponent implements OnInit {
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** Instance for active modal service @public */
+ public activeModal: NgbActiveModal;
+
+ /** Contains files information @public */
+ public contents: {}[];
+
+ /** Input contains component objects @public */
+ @Input() public params: URLPARAMS;
+
+ /** Instance of the rest service @private */
+ private restService: RestService;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.restService = this.injector.get(RestService);
+ this.activeModal = this.injector.get(NgbActiveModal);
+ }
+
+ /**
+ * Lifecyle Hooks the trigger before component is instantiate @public
+ */
+ public ngOnInit(): void {
+ if (this.params.page === 'nsd') {
+ this.restService.getResource(environment.NSDESCRIPTORS_URL + '/' + this.params.id + '/artifacts/artifactPath')
+ .subscribe((nsd: {}[]) => {
+ this.contents = nsd;
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'get');
+ });
+ } else if (this.params.page === 'vnfd') {
+ this.restService.getResource(environment.VNFPACKAGES_URL + '/' + this.params.id + '/artifacts/artifactPath')
+ .subscribe((vnfd: {}[]) => {
+ this.contents = vnfd;
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'get');
+ });
+ }
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="row d-flex flex-row justify-content-between">
+ <div class="d-flex align-items-center header-style">VNF {{'PACKAGES' | translate}}</div>
+ <span class="button">
+ <button class="btn btn-primary" type="button" placement="top" container="body" ngbTooltip="{{'PAGE.VNFPACKAGE.ADDVNFPACKAGE' | translate}}"
+ (click)="composeVNFPackage()">
+ <i class="fas fa-plus-circle" aria-hidden="true"></i> {{'PAGE.VNFPACKAGE.ADDVNFPACKAGE' | translate}}
+ </button>
+ </span>
+</div>
+<div class="row">
+ <div class="dropzone mt-2" appDrag (click)="fileInput.click()" (files)="filesDropped($event)">
+ <input hidden type="file" #fileInput (change)="filesDropped($event.target.files)">
+ <div class="text-wrapper">
+ <div class="text-center file-drop-title">
+ <i class="fas fa-upload"></i> {{'DROPFILES' | translate}}</div>
+ </div>
+ </div>
+</div>
+<div class="row mt-2 mb-0 form-group justify-content-end list-utilites-actions">
+ <page-per-row class="mr-2" (pagePerRow)="onChange($event)"></page-per-row>
+ <page-reload></page-reload>
+</div>
+<div class="smarttable-style bg-white mt-1">
+ <ng2-smart-table [ngClass]="checkDataClass" [settings]="settings" [source]="dataSource" (userRowSelect)="onUserRowSelect($event)">
+ </ng2-smart-table>
+</div>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file VNF Package details Component.
+ */
+import { HttpHeaders } from '@angular/common/http';
+import { Component, ElementRef, Injector, OnInit, ViewChild } from '@angular/core';
+import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateService } from '@ngx-translate/core';
+import { NotifierService } from 'angular-notifier';
+import { APIURLHEADER, ERRORDATA } from 'CommonModel';
+import { ComposePackages } from 'ComposePackages';
+import { DataService } from 'DataService';
+import { environment } from 'environment';
+import { LocalDataSource } from 'ng2-smart-table';
+import { RestService } from 'RestService';
+import { Subscription } from 'rxjs';
+import { SharedService } from 'SharedService';
+import { VNFData, VNFDDetails } from 'VNFDModel';
+import { VNFPackagesActionComponent } from 'VNFPackagesAction';
+
+/**
+ * Creating component
+ * @Component takes VNFPackagesComponent.html as template url
+ */
+@Component({
+ selector: 'app-vnf-packages',
+ templateUrl: './VNFPackagesComponent.html',
+ styleUrls: ['./VNFPackagesComponent.scss']
+})
+/** Exporting a class @exports VNFPackagesComponent */
+export class VNFPackagesComponent implements OnInit {
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** Data of smarttable populate through LocalDataSource @public */
+ public dataSource: LocalDataSource = new LocalDataSource();
+
+ /** handle translate @public */
+ public translateService: TranslateService;
+
+ /** Columns list of the smart table @public */
+ public columnLists: object = {};
+
+ /** Settings for smarttable to populate the table with columns @public */
+ public settings: object = {};
+
+ /** Check the loading results @public */
+ public isLoadingResults: boolean = true;
+
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+
+ /** Class for empty and present data @public */
+ public checkDataClass: string;
+
+ /** Element ref for fileInput @public */
+ @ViewChild('fileInput', { static: true }) public fileInput: ElementRef;
+
+ /** Instance of the rest service @private */
+ private restService: RestService;
+
+ /** dataService to pass the data from one component to another @private */
+ private dataService: DataService;
+
+ /** Formation of appropriate Data for LocalDatasource @private */
+ private vnfData: VNFData[] = [];
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ /** variables contains file information */
+ private fileData: string | ArrayBuffer;
+
+ /** Controls the header form @private */
+ private headers: HttpHeaders;
+
+ /** Notifier service to popup notification @private */
+ private notifierService: NotifierService;
+
+ /** Instance of the modal service @private */
+ private modalService: NgbModal;
+
+ /** Instance of subscriptions @private */
+ private generateDataSub: Subscription;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.restService = this.injector.get(RestService);
+ this.dataService = this.injector.get(DataService);
+ this.sharedService = this.injector.get(SharedService);
+ this.translateService = this.injector.get(TranslateService);
+ this.notifierService = this.injector.get(NotifierService);
+ this.modalService = this.injector.get(NgbModal);
+ }
+
+ /**
+ * Lifecyle Hooks the trigger before component is instantiate
+ */
+ public ngOnInit(): void {
+ this.generateColumns();
+ this.generateSettings();
+ this.generateData();
+ this.headers = new HttpHeaders({
+ 'Content-Type': 'application/gzip',
+ Accept: 'application/json',
+ 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
+ });
+ this.generateDataSub = this.sharedService.dataEvent.subscribe(() => { this.generateData(); });
+ }
+
+ /** smart table Header Colums @public */
+ public generateColumns(): void {
+ this.columnLists = {
+ shortName: { title: this.translateService.instant('SHORTNAME'), width: '15%', sortDirection: 'asc' },
+ identifier: { title: this.translateService.instant('IDENTIFIER'), width: '20%' },
+ type: {
+ title: this.translateService.instant('TYPE'),
+ filter: {
+ type: 'list',
+ config: {
+ selectText: 'Select',
+ list: [
+ { value: 'vnfd', title: 'VNF' },
+ { value: 'pnfd', title: 'PNF' },
+ { value: 'hnfd', title: 'HNF' }
+ ]
+ }
+ },
+ width: '10%'
+ },
+ description: { title: this.translateService.instant('DESCRIPTION'), width: '20%' },
+ vendor: { title: this.translateService.instant('VENDOR'), width: '10%' },
+ version: { title: this.translateService.instant('VERSION'), width: '10%' },
+ Actions: {
+ name: 'Action', width: '15%', filter: false, sort: false, type: 'custom',
+ title: this.translateService.instant('ACTIONS'),
+ valuePrepareFunction: (cell: VNFData, row: VNFData): VNFData => row, renderComponent: VNFPackagesActionComponent
+ }
+ };
+ }
+
+ /** smart table Data Settings @public */
+ public generateSettings(): void {
+ this.settings = {
+ edit: {
+ editButtonContent: '<i class="fa fa-edit" title="Edit"></i>',
+ confirmSave: true
+ },
+ delete: {
+ deleteButtonContent: '<i class="far fa-trash-alt" title="delete"></i>',
+ confirmDelete: true
+ },
+ columns: this.columnLists,
+ actions: {
+ add: false,
+ edit: false,
+ delete: false,
+ position: 'right'
+ },
+ attr: this.sharedService.tableClassConfig(),
+ pager: this.sharedService.paginationPagerConfig(),
+ noDataMessage: this.translateService.instant('NODATAMSG')
+ };
+ }
+
+ /** smart table listing manipulation @public */
+ public onChange(perPageValue: number): void {
+ this.dataSource.setPaging(1, perPageValue, true);
+ }
+
+ /** OnUserRowSelect Function @public */
+ public onUserRowSelect(event: MessageEvent): void {
+ Object.assign(event.data, { page: 'vnf-package' });
+ this.dataService.changeMessage(event.data);
+ }
+
+ /** Drag and drop feature and fetchind the details of files @public */
+ public filesDropped(files: FileList): void {
+ if (files && files.length === 1) {
+ this.isLoadingResults = true;
+ this.sharedService.getFileString(files, 'gz').then((fileContent: ArrayBuffer): void => {
+ const apiURLHeader: APIURLHEADER = {
+ url: environment.VNFPACKAGESCONTENT_URL,
+ httpOptions: { headers: this.headers }
+ };
+ this.saveFileData(apiURLHeader, fileContent);
+ }).catch((err: string): void => {
+ this.isLoadingResults = false;
+ if (err === 'typeError') {
+ this.notifierService.notify('error', this.translateService.instant('GZFILETYPEERRROR'));
+ } else {
+ this.notifierService.notify('error', this.translateService.instant('ERROR'));
+ }
+ });
+ } else if (files && files.length > 1) {
+ this.notifierService.notify('error', this.translateService.instant('DROPFILESVALIDATION'));
+ }
+ }
+
+ /** Post the droped files and reload the page @public */
+ public saveFileData(urlHeader: APIURLHEADER, fileData: {}): void {
+ this.fileInput.nativeElement.value = null;
+ this.restService.postResource(urlHeader, fileData).subscribe((result: {}) => {
+ this.notifierService.notify('success', this.translateService.instant('PAGE.VNFPACKAGE.CREATEDSUCCESSFULLY'));
+ this.generateData();
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'post');
+ this.isLoadingResults = false;
+ });
+ }
+
+ /** Generate nsData object from loop and return for the datasource @public */
+ public generatevnfdData(vnfdpackagedata: VNFDDetails): VNFData {
+ return {
+ shortName: vnfdpackagedata['short-name'],
+ identifier: vnfdpackagedata._id,
+ type: vnfdpackagedata._admin.type,
+ description: vnfdpackagedata.description,
+ vendor: vnfdpackagedata.vendor,
+ version: vnfdpackagedata.version
+ };
+ }
+ /** Handle compose new ns package method @public */
+ public composeVNFPackage(): void {
+ this.modalService.open(ComposePackages, { backdrop: 'static' }).componentInstance.params = { page: 'vnf-package' };
+ }
+
+ /**
+ * Lifecyle hook which get trigger on component destruction
+ */
+ public ngOnDestroy(): void {
+ this.generateDataSub.unsubscribe();
+ }
+
+ /** Fetching the data from server to Load in the smarttable @protected */
+ protected generateData(): void {
+ this.isLoadingResults = true;
+ this.restService.getResource(environment.VNFPACKAGESCONTENT_URL).subscribe((vnfdPackageData: VNFDDetails[]) => {
+ this.vnfData = [];
+ vnfdPackageData.forEach((vnfdpackagedata: VNFDDetails) => {
+ const vnfDataObj: VNFData = this.generatevnfdData(vnfdpackagedata);
+ this.vnfData.push(vnfDataObj);
+ });
+ if (this.vnfData.length > 0) {
+ this.checkDataClass = 'dataTables_present';
+ } else {
+ this.checkDataClass = 'dataTables_empty';
+ }
+ this.dataSource.load(this.vnfData).then((data: boolean) => {
+ this.isLoadingResults = false;
+ }).catch(() => {
+ this.isLoadingResults = false;
+ });
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'get');
+ this.isLoadingResults = false;
+ });
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="d-flex flex-column align-items-center flex-grow-1 text-dark font-weight-bold page-not-found">
+ <img src="../../assets/images/page-not-found.jpg">
+ <h1>{{'PAGENOTFOUND.OOPS' | translate}}</h1>
+ <span>
+ {{'PAGENOTFOUND.CONTENT' | translate}}
+ </span>
+ <span>
+ {{'PAGENOTFOUND.MEAN' | translate}} <a routerLink="/">{{'PAGE.DASHBOARD.DASHBOARD' | translate}}</a>
+ </span>
+</div>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+@import "../../assets/scss/mixins/mixin";
+@import "../../assets/scss/variable";
+.page-not-found {
+ @include padding-percentage-value(10rem, 10rem, 10rem, 10rem);
+ .four-not-four {
+ @include font(null, 5rem, bold);
+ }
+ a:hover {
+ color: $primary;
+ text-decoration: underline;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file Page not found component
+ */
+import { Component, OnInit } from '@angular/core';
+
+/**
+ * Creating component
+ * @Component takes PageNotFoundComponent.html as template url
+ */
+@Component({
+ selector: 'app-page-not-found',
+ templateUrl: './PageNotFoundComponent.html',
+ styleUrls: ['./PageNotFoundComponent.scss']
+})
+/** Exporting a class @exports PageNotFoundComponent */
+export class PageNotFoundComponent implements OnInit {
+ constructor() {
+ //donothing
+ }
+
+ public ngOnInit(): void {
+ //donothing
+ }
+
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="row d-flex flex-row justify-content-between">
+ <div class="d-flex align-items-center header-style">{{'PAGE.DASHBOARD.PROJECTS' | translate}}</div>
+ <span class="button">
+ <button class="btn btn-primary" type="button" (click)="projectAdd()" placement="top" container="body" ngbTooltip="{{'PAGE.PROJECT.NEWPROJECT' | translate}}">
+ <i class="fas fa-plus-circle" aria-hidden="true"></i>
+ {{'PAGE.PROJECT.NEWPROJECT' | translate}}
+ </button>
+ </span>
+</div>
+<div class="row mt-2 mb-0 form-group justify-content-end list-utilites-actions">
+ <page-per-row class="mr-2" (pagePerRow)="onChange($event)"></page-per-row>
+ <page-reload></page-reload>
+</div>
+<div class="smarttable-style bg-white mt-1">
+ <ng2-smart-table [settings]="settings" [source]="dataSource" (userRowSelect)="onUserRowSelect($event)">
+ </ng2-smart-table>
+</div>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file Project details Component.
+ */
+import { Component, Injector, OnDestroy, OnInit } from '@angular/core';
+import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateService } from '@ngx-translate/core';
+import { ERRORDATA, MODALCLOSERESPONSEDATA } from 'CommonModel';
+import { DataService } from 'DataService';
+import { environment } from 'environment';
+import { LocalDataSource } from 'ng2-smart-table';
+import { ProjectCreateUpdateComponent } from 'ProjectCreateUpdate';
+import { ProjectLinkComponent } from 'ProjectLinkComponent';
+import { ProjectData, ProjectDetails } from 'ProjectModel';
+import { ProjectsActionComponent } from 'ProjectsAction';
+import { RestService } from 'RestService';
+import { Subscription } from 'rxjs';
+import { SharedService } from 'SharedService';
+
+/**
+ * Creating component
+ * @Component takes ProjectsComponent.html as template url
+ */
+@Component({
+ selector: 'app-projects',
+ templateUrl: './ProjectsComponent.html',
+ styleUrls: ['./ProjectsComponent.scss']
+})
+/** Exporting a class @exports ProjectsComponent */
+export class ProjectsComponent implements OnInit, OnDestroy {
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** handle translate @public */
+ public translateService: TranslateService;
+
+ /** Data of smarttable populate through LocalDataSource @public */
+ public dataSource: LocalDataSource = new LocalDataSource();
+
+ /** Columns list of the smart table @public */
+ public columnLists: object = {};
+
+ /** Settings for smarttable to populate the table with columns @public */
+ public settings: object = {};
+
+ /** Check the loading results @public */
+ public isLoadingResults: boolean = true;
+
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+
+ /** Instance of the rest service @private */
+ private restService: RestService;
+
+ /** dataService to pass the data from one component to another @private */
+ private dataService: DataService;
+
+ /** Instance of the modal service @private */
+ private modalService: NgbModal;
+
+ /** Formation of appropriate Data for LocalDatasource @private */
+ private projectData: ProjectData[] = [];
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ /** Instance of subscriptions @private */
+ private generateDataSub: Subscription;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.restService = this.injector.get(RestService);
+ this.dataService = this.injector.get(DataService);
+ this.sharedService = this.injector.get(SharedService);
+ this.modalService = this.injector.get(NgbModal);
+ this.translateService = this.injector.get(TranslateService);
+ }
+
+ /** Lifecyle Hooks the trigger before component is instantiate @public */
+ public ngOnInit(): void {
+ this.generateColumns();
+ this.generateSettings();
+ this.generateData();
+ this.generateDataSub = this.sharedService.dataEvent.subscribe(() => { this.generateData(); });
+ }
+
+ /** smart table Header Colums @public */
+ public generateColumns(): void {
+ this.columnLists = {
+ projectName: {
+ title: this.translateService.instant('NAME'), width: '55%', sortDirection: 'asc', type: 'custom',
+ valuePrepareFunction: (cell: ProjectData, row: ProjectData): ProjectData => row,
+ renderComponent: ProjectLinkComponent
+ },
+ modificationDate: { title: this.translateService.instant('MODIFIED'), width: '20%' },
+ creationDate: { title: this.translateService.instant('CREATED'), width: '20%' },
+ Actions: {
+ name: 'Action', width: '5%', filter: false, sort: false, type: 'custom',
+ title: this.translateService.instant('ACTIONS'),
+ valuePrepareFunction: (cell: ProjectData, row: ProjectData): ProjectData => row,
+ renderComponent: ProjectsActionComponent
+ }
+ };
+ }
+
+ /** smart table Data Settings @public */
+ public generateSettings(): void {
+ this.settings = {
+ edit: {
+ editButtonContent: '<i class="fa fa-edit" title="Edit"></i>',
+ confirmSave: true
+ },
+ delete: {
+ deleteButtonContent: '<i class="far fa-trash-alt" title="Delete"></i>',
+ confirmDelete: true
+ },
+ columns: this.columnLists,
+ actions: {
+ add: false,
+ edit: false,
+ delete: false,
+ position: 'right'
+ },
+ attr: this.sharedService.tableClassConfig(),
+ pager: this.sharedService.paginationPagerConfig(),
+ noDataMessage: this.translateService.instant('NODATAMSG')
+ };
+ }
+
+ /** Modal service to initiate the project add @private */
+ public projectAdd(): void {
+ const modalRef: NgbModalRef = this.modalService.open(ProjectCreateUpdateComponent, { backdrop: 'static' });
+ modalRef.componentInstance.projectType = 'Add';
+ modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
+ if (result) {
+ this.generateData();
+ }
+ }).catch();
+ }
+
+ /** smart table listing manipulation @private */
+ public onChange(perPageValue: number): void {
+ this.dataSource.setPaging(1, perPageValue, true);
+ }
+
+ /** convert UserRowSelect Function @private */
+ public onUserRowSelect(event: MessageEvent): void {
+ Object.assign(event.data, { page: 'projects' });
+ this.dataService.changeMessage(event.data);
+ }
+
+ /** Generate Projects object from loop and return for the datasource @public */
+ public generateProjectData(projectData: ProjectDetails): ProjectData {
+ return {
+ projectName: projectData.name,
+ modificationDate: this.sharedService.convertEpochTime(projectData._admin.modified),
+ creationDate: this.sharedService.convertEpochTime(projectData._admin.created),
+ id: projectData._id,
+ project: projectData._id
+ };
+ }
+
+ /**
+ * Lifecyle hook which get trigger on component destruction
+ */
+ public ngOnDestroy(): void {
+ this.generateDataSub.unsubscribe();
+ }
+
+ /** Fetching the data from server to Load in the smarttable @protected */
+ protected generateData(): void {
+ this.isLoadingResults = true;
+ this.restService.getResource(environment.PROJECTS_URL).subscribe((projectsData: ProjectDetails[]) => {
+ this.projectData = [];
+ projectsData.forEach((projectData: ProjectDetails) => {
+ const projectDataObj: ProjectData = this.generateProjectData(projectData);
+ this.projectData.push(projectDataObj);
+ });
+ this.dataSource.load(this.projectData).then((data: boolean) => {
+ this.isLoadingResults = false;
+ }).catch();
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'get');
+ this.isLoadingResults = false;
+ });
+ }
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file SDN Controller module.
+ */
+import { CommonModule } from '@angular/common';
+import { HttpClientModule } from '@angular/common/http';
+import { NgModule } from '@angular/core';
+import { FlexLayoutModule } from '@angular/flex-layout';
+import { FormsModule } from '@angular/forms';
+import { ReactiveFormsModule } from '@angular/forms';
+import { RouterModule, Routes } from '@angular/router';
+import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
+import { NgSelectModule } from '@ng-select/ng-select';
+import { TranslateModule } from '@ngx-translate/core';
+import { DataService } from 'DataService';
+import { LoaderModule } from 'LoaderModule';
+import { Ng2SmartTableModule } from 'ng2-smart-table';
+import { PagePerRowModule } from 'PagePerRowModule';
+import { PageReloadModule } from 'PageReloadModule';
+import { ProjectCreateUpdateComponent } from 'ProjectCreateUpdate';
+import { ProjectsComponent } from 'ProjectsComponent';
+
+/**
+ * configures routers
+ */
+const routes: Routes = [
+ {
+ path: '',
+ data: {
+ breadcrumb: [{ title: 'PAGE.DASHBOARD.DASHBOARD', url: '/' }, { title: 'PAGE.DASHBOARD.PROJECTS', url: null }]
+ },
+ component: ProjectsComponent
+ }
+];
+
+/**
+ * Creating @NgModule component for Modules
+ */
+// tslint:disable-next-line: no-stateless-class
+@NgModule({
+ imports: [
+ FormsModule,
+ CommonModule,
+ HttpClientModule,
+ Ng2SmartTableModule,
+ FlexLayoutModule,
+ TranslateModule,
+ RouterModule.forChild(routes),
+ NgbModule,
+ PagePerRowModule,
+ ReactiveFormsModule,
+ LoaderModule,
+ PageReloadModule,
+ NgSelectModule
+ ],
+ declarations: [
+ ProjectsComponent,
+ ProjectCreateUpdateComponent
+ ],
+ providers: [
+ DataService
+ ],
+ entryComponents: [
+ ProjectCreateUpdateComponent
+ ]
+})
+/** Exporting a class @exports ProjectsModule */
+export class ProjectsModule {
+ // empty module
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<form [formGroup]="projectForm" (ngSubmit)="projectAction(getProjectType)">
+ <div class="modal-header">
+ <h4 class="modal-title" id="modal-basic-title">{{ (getProjectType == 'Add' ? 'NEW' : 'EDIT') | translate}} {{'PROJECT' | translate}}</h4>
+ <button class="button-xs" type="button" class="close" aria-label="Close" (click)="activeModal.close()">
+ <i class="fas fa-times-circle text-danger"></i>
+ </button>
+ </div>
+ <div class="modal-body project-create-update">
+ <div class="form-group row">
+ <label class="col-sm-12 col-form-label mandatory-label" [ngClass]="{'text-danger': projectForm.invalid === true && submitted === true}">{{'MANDATORYCHECK' | translate}}</label>
+ <label class="col-sm-4 col-form-label">{{'PROJECT' | translate}} {{'NAME' | translate}}*</label>
+ <div class="col-sm-8">
+ <input placeholder="{{'PROJECT' | translate}} {{'NAME' | translate}}" type="text" class="form-control" formControlName="project_name" [(ngModel)]="projectName" [ngClass]="{ 'is-invalid': submitted && f.project_name.errors }" required>
+ </div>
+ </div>
+ <div class="form-group row" *ngIf="getProjectType === 'Add'">
+ <label class="col-sm-4 col-form-label">{{'DOMAIN' | translate}} {{'NAME' | translate}}</label>
+ <div class="col-sm-8">
+ <ng-select [clearable]="false" placeholder="{{'SELECT' | translate}}"
+ [items]="domains" bindLabel="text" bindValue="id" formControlName="domain_name" id="domain_name"
+ [ngClass]="{ 'is-invalid': submitted && f.domain_name.errors }"></ng-select> </div>
+ </div>
+ <div class="form-group row" *ngIf="getProjectType === 'Add'">
+ <label class="col-xs-10 col-sm-10 col-md-10 col-lg-10 col-xl-10">{{'RECENTLY' | translate}} {{'CREATED' | translate}} {{'PROJECT' | translate}}:
+ <b>{{(recentProject)?recentProject.name:''}}</b>
+ </label>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-danger" (click)="activeModal.close()">{{'CANCEL' | translate}}</button>
+ <button type="submit" class="btn btn-primary">{{(getProjectType == 'Add' ? 'CREATE' : 'APPLY') | translate}}</button>
+ </div>
+</form>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file Project Add Modal
+ */
+import { Component, Injector, Input, OnInit } from '@angular/core';
+import { FormBuilder, FormGroup, Validators } from '@angular/forms';
+import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateService } from '@ngx-translate/core';
+import { NotifierService } from 'angular-notifier';
+import { APIURLHEADER, ERRORDATA, MODALCLOSERESPONSEDATA } from 'CommonModel';
+import { DataService } from 'DataService';
+import { environment } from 'environment';
+import { ProjectData, ProjectDetails } from 'ProjectModel';
+import { ProjectService } from 'ProjectService';
+import { RestService } from 'RestService';
+import { SharedService } from 'SharedService';
+import { isNullOrUndefined } from 'util';
+
+/**
+ * Creating component
+ * @Component takes ProjectCreateUpdateComponent.html as template url
+ */
+@Component({
+ selector: 'app-project-create-update',
+ templateUrl: './ProjectCreateUpdateComponent.html',
+ styleUrls: ['./ProjectCreateUpdateComponent.scss']
+})
+/** Exporting a class @exports ProjectCreateUpdateComponent */
+export class ProjectCreateUpdateComponent implements OnInit {
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** Instance of the rest service @public */
+ public restService: RestService;
+
+ /** Instance for active modal service @public */
+ public activeModal: NgbActiveModal;
+
+ /** Contains the recently created project details @public */
+ public recentProject: ProjectDetails;
+
+ /** Contains project name @public */
+ public projectName: string;
+
+ /** Contains project create or edit @public */
+ public getProjectType: string;
+
+ /** To inject input type services @public */
+ @Input() public projectType: string;
+
+ /** FormGroup user Edit Account added to the form @ html @public */
+ public projectForm: FormGroup;
+
+ /** Form submission Add */
+ public submitted: boolean = false;
+
+ /** Check the loading results for loader status @public */
+ public isLoadingResults: boolean = false;
+
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+
+ /** Holds list of domains @public */
+ public domains: {}[] = [];
+
+ /** FormBuilder instance added to the formBuilder @private */
+ private formBuilder: FormBuilder;
+
+ /** DataService to pass the data from one component to another @private */
+ private dataService: DataService;
+
+ /** Contains project name ref @private */
+ private projectRef: string;
+
+ /** Notifier service to popup notification @private */
+ private notifierService: NotifierService;
+
+ /** Contains tranlsate instance @private */
+ private translateService: TranslateService;
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ /** ModalData instance of modal @private */
+ private modalData: MODALCLOSERESPONSEDATA;
+
+ /** Holds all project details @private */
+ private projectService: ProjectService;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.formBuilder = this.injector.get(FormBuilder);
+ this.restService = this.injector.get(RestService);
+ this.activeModal = this.injector.get(NgbActiveModal);
+ this.dataService = this.injector.get(DataService);
+ this.notifierService = this.injector.get(NotifierService);
+ this.translateService = this.injector.get(TranslateService);
+ this.sharedService = this.injector.get(SharedService);
+ this.projectService = this.injector.get(ProjectService);
+ /** Initializing Form Action */
+ this.projectForm = this.formBuilder.group({
+ project_name: ['', Validators.required],
+ domain_name: [null]
+ });
+ }
+
+ /** convenience getter for easy access to form fields */
+ get f(): FormGroup['controls'] { return this.projectForm.controls; }
+
+ /** Lifecyle Hooks the trigger before component is instantiate @public */
+ public ngOnInit(): void {
+ this.getProjectType = this.projectType;
+ if (this.getProjectType === 'Edit') {
+ this.dataService.currentMessage.subscribe((data: ProjectData) => {
+ if (data.projectName !== undefined || data.projectName !== '' || data.projectName !== null) {
+ this.projectName = data.projectName;
+ this.projectRef = data.id;
+ }
+ });
+ } else {
+ this.getProjects();
+ }
+ }
+
+ /** Get the last project name @public */
+ public getProjects(): void {
+ this.isLoadingResults = true;
+ this.restService.getResource(environment.PROJECTS_URL).subscribe((projects: ProjectDetails[]) => {
+ this.recentProject = projects.slice(-1).pop();
+ this.getDomainName();
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'get');
+ this.isLoadingResults = false;
+ });
+ }
+
+ /** On modal submit users acction will called @public */
+ public projectAction(userType: string): void {
+ this.submitted = true;
+ this.modalData = {
+ message: 'Done'
+ };
+ this.sharedService.cleanForm(this.projectForm);
+ if (!this.projectForm.invalid) {
+ if (userType === 'Add') {
+ this.createProject();
+ } else if (userType === 'Edit') {
+ this.editProject();
+ }
+ }
+ }
+
+ /** Create project @public */
+ public createProject(): void {
+ this.isLoadingResults = true;
+ const apiURLHeader: APIURLHEADER = {
+ url: environment.PROJECTS_URL
+ };
+ const projectPayload: {} = {
+ name: this.projectForm.value.project_name,
+ domain_name: !isNullOrUndefined(this.projectForm.value.domain_name) ? this.projectForm.value.domain_name : undefined
+ };
+ this.restService.postResource(apiURLHeader, projectPayload).subscribe(() => {
+ this.activeModal.close(this.modalData);
+ this.isLoadingResults = false;
+ this.notifierService.notify('success', this.translateService.instant('PAGE.PROJECT.CREATEDSUCCESSFULLY'));
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'post');
+ this.isLoadingResults = false;
+ });
+ }
+ /** Edit project @public */
+ public editProject(): void {
+ this.isLoadingResults = true;
+ const apiURLHeader: APIURLHEADER = {
+ url: environment.PROJECTS_URL + '/' + this.projectRef
+ };
+ this.restService.patchResource(apiURLHeader, { name: this.projectForm.value.project_name }).subscribe(() => {
+ this.activeModal.close(this.modalData);
+ this.isLoadingResults = false;
+ this.projectService.setHeaderProjects();
+ this.notifierService.notify('success', this.translateService.instant('PAGE.PROJECT.UPDATEDSUCCESSFULLY'));
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'patch');
+ this.isLoadingResults = false;
+ });
+ }
+ /** Get domain name @private */
+ private getDomainName(): void {
+ this.restService.getResource(environment.DOMAIN_URL).subscribe((domains: { project_domain_name: string, user_domain_name: string }) => {
+ let domainNames: string[] = [];
+ if (!isNullOrUndefined(domains.project_domain_name)) {
+ domainNames = domainNames.concat(domains.project_domain_name.split(','));
+ }
+ if (!isNullOrUndefined(domains.user_domain_name)) {
+ domainNames = domainNames.concat(domains.user_domain_name.split(','));
+ }
+ domainNames = Array.from(new Set(domainNames));
+ this.checkDomainNames(domainNames);
+ this.isLoadingResults = false;
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'get');
+ this.isLoadingResults = false;
+ });
+ }
+
+ /** Check the domain names and create modal for domain select @private */
+ private checkDomainNames(domainNames: string[]): void {
+ if (domainNames.length > 0) {
+ domainNames.forEach((domainName: string) => {
+ if (!domainName.endsWith(':ro')) {
+ this.domains.push({ id: domainName, text: domainName });
+ }
+ });
+ }
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<router-outlet></router-outlet>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file Roles component.
+ */
+import { Component, Injector } from '@angular/core';
+import { Router, RouterEvent } from '@angular/router';
+
+/**
+ * Creating component
+ * @Component takes RolesComponent.html as template url
+ */
+@Component({
+ selector: 'app-roles',
+ templateUrl: './RolesComponent.html',
+ styleUrls: ['./RolesComponent.scss']
+})
+
+/** Exporting a class @exports RolesComponent */
+export class RolesComponent {
+ /** Invoke service injectors @public */
+ public injector: Injector;
+
+ /** Holds teh instance of router service @private */
+ private router: Router;
+
+ // creates role datails component
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.router = this.injector.get(Router);
+ this.router.events.subscribe((event: RouterEvent) => {
+ this.redirectToList(event.url);
+ });
+ }
+
+ /** Return to role datails list */
+ public redirectToList(getURL: string): void {
+ if (getURL === '/roles') {
+ this.router.navigate(['/roles/details']).catch();
+ }
+ }
+
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+
+/**
+ * @file Roles Module
+ */
+import { CommonModule } from '@angular/common';
+import { HttpClientModule } from '@angular/common/http';
+import { NgModule } from '@angular/core';
+import { FormsModule } from '@angular/forms';
+import { ReactiveFormsModule } from '@angular/forms';
+import { RouterModule, Routes } from '@angular/router';
+import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateModule } from '@ngx-translate/core';
+import { LoaderModule } from 'LoaderModule';
+import { Ng2SmartTableModule } from 'ng2-smart-table';
+import { PagePerRowModule } from 'PagePerRowModule';
+import { PageReloadModule } from 'PageReloadModule';
+import { RolesComponent } from 'Roles';
+import { RolesActionComponent } from 'RolesAction';
+import { RolesCreateEditComponent } from 'RolesCreateEdit';
+import { RolesDetailsComponent } from 'RolesDetails';
+
+/** const values for Roles Routes */
+const routes: Routes = [
+ {
+ path: '',
+ component: RolesComponent,
+ children: [
+ {
+ path: 'details',
+ data: {
+ breadcrumb: [{ title: 'PAGE.DASHBOARD.DASHBOARD', url: '/' }, { title: 'ROLES', url: null }]
+ },
+ component: RolesDetailsComponent
+ },
+ {
+ path: 'create',
+ data: {
+ breadcrumb: [{ title: 'PAGE.DASHBOARD.DASHBOARD', url: '/' }, { title: 'ROLES', url: '/roles/details' },
+ { title: 'PAGE.ROLES.CREATEROLE', url: null }]
+ },
+ component: RolesCreateEditComponent
+ },
+ {
+ path: 'edit/:id',
+ data: {
+ breadcrumb: [{ title: 'PAGE.DASHBOARD.DASHBOARD', url: '/' }, { title: 'ROLES', url: '/roles/details' },
+ { title: '{id}', url: null }]
+ },
+ component: RolesCreateEditComponent
+ }
+ ]
+ }
+];
+/**
+ * An NgModule is a class adorned with the @NgModule decorator function.
+ * @NgModule takes a metadata object that tells Angular how to compile and run module code.
+ */
+@NgModule({
+ imports: [FormsModule, ReactiveFormsModule, CommonModule, HttpClientModule, TranslateModule,
+ RouterModule.forChild(routes), NgbModule, PagePerRowModule, Ng2SmartTableModule, LoaderModule, PageReloadModule],
+ declarations: [RolesComponent, RolesDetailsComponent, RolesActionComponent, RolesCreateEditComponent],
+ entryComponents: [RolesActionComponent]
+})
+/**
+ * AppModule is the Root module for application
+ */
+export class RolesModule {
+ /** Variables declared to avoid state-less class */
+ private rolesModule: string;
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="row d-flex flex-row justify-content-between">
+ <div class="d-flex align-items-center header-style">
+ {{ (getRoleType == 'Add' ? 'PAGE.ROLES.CREATEROLE' : 'PAGE.ROLES.EDITROLE') | translate}}</div>
+ <span class="button">
+ <button class="btn btn-primary" type="button" (click)="viewSelection()" placement="top" container="body"
+ ngbTooltip="{{ (viewMode == 'text' ? 'PAGE.ROLES.PREVIEW' : 'PAGE.ROLES.TEXTVIEW') | translate}}"> <i
+ [ngClass]="{ 'fa': 'true', 'fa-comment': viewMode == 'text', 'fa-edit': viewMode == 'preview' }"></i> {{ (viewMode == 'text' ? 'PAGE.ROLES.PREVIEW' : 'PAGE.ROLES.TEXTVIEW') | translate}}
+ </button>
+ </span>
+</div>
+<form [formGroup]="roleForm" (ngSubmit)="roleCheck()" autocomplete="off">
+ <div class="form-group row">
+ <label class="col-sm-12 col-form-label mandatory-label"
+ [ngClass]="{'text-danger': roleForm.invalid === true && submitted === true}">{{'MANDATORYCHECK' | translate}}</label>
+ <label class="col-sm-2 col-form-label">{{'NAME' | translate}}*</label>
+ <div class="col-sm-5">
+ <input placeholder="{{'NAME' | translate}}" type="text" class="form-control" maxlength="30"
+ formControlName="roleName" [ngClass]="{ 'is-invalid': submitted && f.roleName.errors }" required>
+ </div>
+ </div>
+ <div class="form-group row" *ngIf="viewMode == 'text'">
+ <label class="col-sm-2 col-form-label">{{'PAGE.ROLES.PERMISSIONS' | translate}}</label>
+ <div class="col-sm-5">
+ <textarea placeholder="{{'PAGE.ROLES.YAMLPERMISSIONS' | translate}}" rows="10" cols="50" type="text"
+ class="form-control" formControlName="permissions"></textarea>
+ </div>
+ </div>
+ <div class="form-group row" [ngClass]="{ 'justify-content-end': viewMode == 'text' }">
+ <div class="col-sm-6">
+ <button type="button" class="btn btn-danger" routerLink="/roles/details">{{'CANCEL' | translate}}</button>
+ <button class="btn btn-primary ml-3"
+ type="submit">{{ (getRoleType == 'Add' ? 'CREATE' : 'APPLY') | translate}}</button>
+ </div>
+ </div>
+</form>
+<ngb-accordion class="roles-section" [closeOthers]="true" type="secondary" *ngIf="rolePermissions && viewMode == 'preview'">
+ <ngb-panel *ngFor="let permissionGroup of rolePermissions; let i = index">
+ <ng-template ngbPanelHeader let-opened="opened">
+ <div class="d-flex align-items-center justify-content-between">
+ <button ngbPanelToggle class="btn text-dark container-fluid text-left pl-0"><i
+ [ngClass]="{ 'fas': true, 'fa-angle-down': opened, 'fa-angle-right': !opened }"></i> {{permissionGroup.title}}</button>
+ </div>
+ </ng-template>
+ <ng-template ngbPanelContent>
+ <div class="row">
+ <div class="col-lg-4 col-md-6 col-sm-12" *ngFor="let permission of permissionGroup.permissions">
+ <div class="row">
+ <div class="col-md-6 col-sm-6 p-2">{{permission.operation}}</div>
+ <div class="btn-group btn-group-toggle custom-button col-md-6 col-sm-6" ngbRadioGroup name="permission"
+ [(ngModel)]="permission.value">
+ <label ngbButtonLabel ngbTooltip="true">
+ <input ngbButton type="radio" [value]="true">
+ <span class="bg-success"><img src="assets/images/TICK.svg" alt="Checked Icon" /></span>
+ </label>
+ <label ngbButtonLabel ngbTooltip="NA">
+ <input ngbButton type="radio" value="NA">
+ <span class="bg-warning"><img src="assets/images/TICK.svg" alt="Checked Icon" /></span>
+ </label>
+ <label ngbButtonLabel ngbTooltip="false">
+ <input ngbButton type="radio" [value]="false">
+ <span class="bg-danger"><img src="assets/images/TICK.svg" alt="Checked Icon" /></span>
+ </label>
+ </div>
+ </div>
+ </div>
+ </div>
+ </ng-template>
+ </ngb-panel>
+</ngb-accordion>
+<div class="float-right" *ngIf="viewMode == 'preview'">
+ <button type="button" class="btn btn-danger" routerLink="/roles/details">{{'CANCEL' | translate}}</button>
+ <button class="btn btn-primary ml-3"
+ (click)="roleCheck()">{{ (getRoleType == 'Add' ? 'CREATE' : 'APPLY') | translate}}</button>
+</div>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+@import '../../../assets/scss/mixins/mixin';
+@import '../../../assets/scss/variable';
+ .custom-button{
+ label {
+ @include padding-value(2,2,2,2);
+ &.active {
+ @include background(null, $white, null, null, null);
+ span{
+ img {
+ opacity: 1;
+ }
+ }
+ }
+ input[type="radio"] {
+ display: none;
+ }
+ span {
+ display: inline-block;
+ @include wh-value(30px,30px);
+ cursor: pointer;
+ border-radius: 50%;
+ @include border(all,2,solid, $white);
+ @include box-shadow(0px, 1px, 3px, 0px, $dark);
+ @include background(null, null, null, no-repeat, center);
+ text-align: center;
+ @include line-height(25px);
+ img {
+ width:50%;
+ opacity: 0;
+ @include transition(all, 0.3, null, ease);
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file Roles Create and Edit Component
+ */
+import { HttpClient, HttpHeaders } from '@angular/common/http';
+import { Component, Injector, Input, OnInit } from '@angular/core';
+import { FormBuilder, FormGroup, Validators } from '@angular/forms';
+import { ActivatedRoute, Router } from '@angular/router';
+import { TranslateService } from '@ngx-translate/core';
+import { NotifierService } from 'angular-notifier';
+import { APIURLHEADER, ERRORDATA } from 'CommonModel';
+import { environment } from 'environment';
+import * as jsonpath from 'jsonpath';
+import { RestService } from 'RestService';
+import { Permission, PermissionGroup, RoleConfig, RoleData } from 'RolesModel';
+import { SharedService } from 'SharedService';
+import { isNullOrUndefined } from 'util';
+
+/**
+ * Creating component
+ * @Component takes RolesCreateEditComponent.html as template url
+ */
+@Component({
+ selector: 'app-roles-create-edit',
+ templateUrl: './RolesCreateEditComponent.html',
+ styleUrls: ['./RolesCreateEditComponent.scss']
+})
+/** Exporting a class @exports RolesCreateEditComponent */
+export class RolesCreateEditComponent implements OnInit {
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** contains role permissions from config file @public */
+ public rolePermissions: {}[];
+
+ /** contains role form group information @public */
+ public roleForm: FormGroup;
+
+ /** Instance of the rest service @public */
+ public restService: RestService;
+
+ /** Check the loading results for loader status @public */
+ public isLoadingResults: boolean = false;
+
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+
+ /** Instance to check role form submitted status @public */
+ public submitted: boolean = false;
+
+ /** Contains role create or edit value @public */
+ public getRoleType: string;
+
+ /** Contains view selection value either text or preview @public */
+ public viewMode: string = 'text';
+
+ /** Contains role id value @private */
+ private roleRef: string;
+
+ /** Notifier service to popup notification @private */
+ private notifierService: NotifierService;
+
+ /** Contains tranlsate instance @private */
+ private translateService: TranslateService;
+
+ /** contians form builder module @private */
+ private formBuilder: FormBuilder;
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ /** Controls the header form @private */
+ private headers: HttpHeaders;
+
+ /** Varaibles to hold http client @private */
+ private httpClient: HttpClient;
+
+ /** Holds the instance of activatedRoute of router service @private */
+ private activatedRoute: ActivatedRoute;
+
+ /** Holds the instance of roter service @private */
+ private router: Router;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.restService = this.injector.get(RestService);
+ this.notifierService = this.injector.get(NotifierService);
+ this.translateService = this.injector.get(TranslateService);
+ this.formBuilder = this.injector.get(FormBuilder);
+ this.sharedService = this.injector.get(SharedService);
+ this.httpClient = this.injector.get(HttpClient);
+ this.activatedRoute = this.injector.get(ActivatedRoute);
+ this.router = this.injector.get(Router);
+ }
+
+ /** Lifecyle Hooks the trigger before component is instantiate @public */
+ public ngOnInit(): void {
+ this.headers = new HttpHeaders({
+ 'Content-Type': 'application/json',
+ Accept: 'application/json',
+ 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
+ });
+ this.roleForm = this.formBuilder.group({
+ roleName: ['', [Validators.required]],
+ permissions: ['']
+ });
+ this.getRolePermissions();
+ }
+
+ /** Get role permission information based on action @public */
+ public getRolePermissions(): void {
+ this.isLoadingResults = true;
+ this.loadPermissions().then((response: RoleConfig) => {
+ this.rolePermissions = response.rolePermissions;
+ if (this.activatedRoute.snapshot.url[0].path === 'create') {
+ this.getRoleType = 'Add';
+ this.isLoadingResults = false;
+ } else {
+ this.getRoleType = 'Edit';
+ this.getRoleData();
+ }
+ }).catch(() => {
+ // Empty Block
+ });
+ }
+
+ /** Check Role Create or Edit and proceed action @public */
+ public roleCheck(): void {
+ this.submitted = true;
+ if (!this.roleForm.valid) {
+ const errorIp: Element = document.querySelector('.ng-invalid[formControlName]');
+ if (errorIp) {
+ errorIp.scrollIntoView({ behavior: 'smooth', block: 'center' });
+ }
+ } else {
+ if (this.getRoleType === 'Add') {
+ this.createRole();
+ } else {
+ this.editRole();
+ }
+ }
+ }
+
+ /** Convenience getter for easy access to form fields */
+ get f(): FormGroup['controls'] { return this.roleForm.controls; }
+
+ /** Create role @private */
+ public createRole(): void {
+ const apiURLHeader: APIURLHEADER = {
+ url: environment.ROLES_URL,
+ httpOptions: { headers: this.headers }
+ };
+ let permissionData: Object = {};
+ this.sharedService.cleanForm(this.roleForm);
+ if (!this.roleForm.invalid) {
+ if (this.viewMode === 'preview') {
+ this.isLoadingResults = true;
+ permissionData = this.generatePermissions();
+ this.roleCreateAPI(apiURLHeader, permissionData);
+ } else {
+ if (this.checkPermission()) {
+ this.isLoadingResults = true;
+ permissionData = this.roleForm.value.permissions !== '' ? JSON.parse(this.roleForm.value.permissions) : {};
+ this.roleCreateAPI(apiURLHeader, permissionData);
+ }
+ }
+ }
+ }
+
+ /** Method to handle role create API call @public */
+ public roleCreateAPI(apiURLHeader: APIURLHEADER, permissionData: {}): void {
+ const postData: {} = {
+ name: this.roleForm.value.roleName,
+ permissions: !isNullOrUndefined(permissionData) ? permissionData : {}
+ };
+ this.restService.postResource(apiURLHeader, postData).subscribe(() => {
+ this.notifierService.notify('success', this.translateService.instant('PAGE.ROLES.CREATEDSUCCESSFULLY'));
+ this.router.navigate(['/roles/details']).catch();
+ }, (error: ERRORDATA) => {
+ this.isLoadingResults = false;
+ this.restService.handleError(error, 'post');
+ });
+ }
+
+ /** Edit role @private */
+ public editRole(): void {
+ const apiURLHeader: APIURLHEADER = {
+ url: environment.ROLES_URL + '/' + this.roleRef,
+ httpOptions: { headers: this.headers }
+ };
+ let permissionData: Object = {};
+ this.sharedService.cleanForm(this.roleForm);
+ if (!this.roleForm.invalid) {
+ if (this.viewMode === 'preview') {
+ this.isLoadingResults = true;
+ permissionData = this.generatePermissions();
+ this.roleEditAPI(apiURLHeader, permissionData);
+ } else {
+ if (this.checkPermission()) {
+ this.isLoadingResults = true;
+ permissionData = this.roleForm.value.permissions !== '' ? JSON.parse(this.roleForm.value.permissions) : {};
+ this.roleEditAPI(apiURLHeader, permissionData);
+ }
+ }
+ }
+ }
+
+ /** Method to handle role edit API call */
+ public roleEditAPI(apiURLHeader: APIURLHEADER, permissionData: {}): void {
+ const postData: {} = {
+ name: this.roleForm.value.roleName,
+ permissions: !isNullOrUndefined(permissionData) ? permissionData : {}
+ };
+ this.restService.patchResource(apiURLHeader, postData).subscribe(() => {
+ this.notifierService.notify('success', this.translateService.instant('PAGE.ROLES.UPDATEDSUCCESSFULLY'));
+ this.router.navigate(['/roles/details']).catch();
+ }, (error: ERRORDATA) => {
+ this.isLoadingResults = false;
+ this.restService.handleError(error, 'patch');
+ });
+ }
+
+ /** Method to handle toggle role view selection @public */
+ public viewSelection(): void {
+ if (this.viewMode === 'text' && this.checkPermission()) {
+ this.loadPermissions().then((response: RoleConfig) => {
+ this.rolePermissions = response.rolePermissions;
+ const permissions: {} = this.roleForm.value.permissions !== '' ? JSON.parse(this.roleForm.value.permissions) : {};
+ this.filterRoleData(permissions);
+ this.viewMode = 'preview';
+ }).catch(() => {
+ // Empty Block
+ });
+ } else {
+ const rolePermission: {} = this.generatePermissions();
+ if (Object.keys(rolePermission).length !== 0) {
+ this.roleForm.patchValue({ permissions: JSON.stringify(rolePermission, null, '\t') });
+ }
+ this.viewMode = 'text';
+ }
+
+ }
+
+ /** Generate role permission post data @private */
+ private generatePermissions(): Object {
+ const permissions: Object = {};
+ this.rolePermissions.forEach((permissionGroup: PermissionGroup) => {
+ if (!isNullOrUndefined(permissionGroup)) {
+ permissionGroup.permissions.forEach((permission: Permission) => {
+ if (!isNullOrUndefined(permission.value) && permission.value !== 'NA') {
+ permissions[permission.operation] = permission.value;
+ }
+ });
+ }
+ });
+ return permissions;
+ }
+
+ /** Validation method for check permission json string @private */
+ private checkPermission(): boolean {
+ if (this.roleForm.value.permissions) {
+ if (!this.sharedService.checkJson(this.roleForm.value.permissions)) {
+ this.notifierService.notify('error', this.translateService.instant('PAGE.ROLES.ROLEJSONERROR'));
+ return false;
+ } else {
+ this.roleForm.value.permissions = this.roleForm.value.permissions.replace(/'/g, '"');
+ const rolePermission: {} = JSON.parse(this.roleForm.value.permissions);
+ for (const key of Object.keys(rolePermission)) {
+ if (typeof rolePermission[key] !== 'boolean') {
+ this.notifierService.notify('error', this.translateService.instant('PAGE.ROLES.ROLEKEYERROR', { roleKey: key }));
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ /** Get role data from NBI based on ID and apply filter @private */
+ private getRoleData(): void {
+ // tslint:disable-next-line: no-backbone-get-set-outside-model
+ this.roleRef = this.activatedRoute.snapshot.paramMap.get('id');
+ if (!isNullOrUndefined(this.roleRef)) {
+ this.restService.getResource(environment.ROLES_URL + '/' + this.roleRef).subscribe((data: RoleData) => {
+ this.roleForm.setValue({ roleName: data.name, permissions: JSON.stringify(data.permissions, null, '\t') });
+ this.filterRoleData(data.permissions);
+ this.isLoadingResults = false;
+ }, (error: ERRORDATA) => {
+ this.router.navigate(['/roles/details']).catch();
+ this.restService.handleError(error, 'get');
+ });
+ }
+ }
+
+ /** Method to filter role data @private */
+ private filterRoleData(permissions: {}): void {
+ Object.keys(permissions).forEach((permission: string) => {
+ jsonpath.apply(this.rolePermissions, '$..permissions[?(@.operation == "' + permission + '")]', (response: Permission) => {
+ if (response.operation === permission) {
+ response.value = permissions[permission];
+ }
+ return response;
+ });
+ });
+ }
+
+ /** Method to load the role permission Json file @private */
+ private async loadPermissions(): Promise<Object> {
+ const jsonFile: string = environment.PERMISSIONS_CONFIG_FILE + '?cb=' + new Date().getTime();
+ return new Promise<Object>((resolve: Function, reject: Function): void => {
+ this.httpClient.get(jsonFile).subscribe((response: Response) => {
+ resolve(response);
+ }, (error: {}) => {
+ reject();
+ });
+ });
+ }
+
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="row d-flex flex-row justify-content-between">
+ <div class="d-flex align-items-center header-style">{{'ROLES' | translate}}</div>
+ <span class="button">
+ <button class="btn btn-primary" type="button" (click)="createRole()" placement="top"
+ container="body" ngbTooltip="{{'PAGE.ROLES.CREATEROLE' | translate}}">
+ <i class="fas fa-plus-circle" aria-hidden="true"></i>
+ {{'PAGE.ROLES.CREATEROLE' | translate}}
+ </button>
+ </span>
+</div>
+<div class="row mt-2 mb-0 form-group justify-content-end list-utilites-actions">
+ <page-per-row class="mr-2" (pagePerRow)="onChange($event)"></page-per-row>
+ <page-reload></page-reload>
+</div>
+<div class="smarttable-style bg-white mt-1">
+ <ng2-smart-table [settings]="settings" [source]="dataSource" (userRowSelect)="onUserRowSelect($event)">
+ </ng2-smart-table>
+</div>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file Roles Deatils component.
+ */
+import { Component, Injector, OnInit } from '@angular/core';
+import { Router } from '@angular/router';
+import { TranslateService } from '@ngx-translate/core';
+import { ERRORDATA } from 'CommonModel';
+import { DataService } from 'DataService';
+import { environment } from 'environment';
+import { LocalDataSource } from 'ng2-smart-table';
+import { RestService } from 'RestService';
+import { RolesActionComponent } from 'RolesAction';
+import { RoleData, RoleDetails } from 'RolesModel';
+import { Subscription } from 'rxjs';
+import { SharedService } from 'SharedService';
+
+/**
+ * Creating component
+ * @Component takes RolesComponent.html as template url
+ */
+@Component({
+ selector: 'app-roles-details',
+ templateUrl: './RolesDetailsComponent.html',
+ styleUrls: ['./RolesDetailsComponent.scss']
+})
+export class RolesDetailsComponent implements OnInit {
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** Formation of appropriate Data for LocalDatasource @public */
+ public dataSource: LocalDataSource = new LocalDataSource();
+
+ /** handle translate @public */
+ public translateService: TranslateService;
+
+ /** Columns list of the smart table @public */
+ public columnLists: object = {};
+
+ /** Settings for smarttable to populate the table with columns @public */
+ public settings: object = {};
+
+ /** Check the loading results @public */
+ public isLoadingResults: boolean = true;
+
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+
+ /** Instance of the rest service @private */
+ private restService: RestService;
+
+ /** dataService to pass the data from one component to another @private */
+ private dataService: DataService;
+
+ /** Contains role details data @private */
+ private roleData: RoleData[] = [];
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ /** Instance of subscriptions @private */
+ private generateDataSub: Subscription;
+
+ /** Holds the instance of roter service @private */
+ private router: Router;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.restService = this.injector.get(RestService);
+ this.dataService = this.injector.get(DataService);
+ this.sharedService = this.injector.get(SharedService);
+ this.translateService = this.injector.get(TranslateService);
+ this.router = this.injector.get(Router);
+ }
+ /** Lifecyle Hooks the trigger before component is instantiate @public */
+ public ngOnInit(): void {
+ this.generateColumns();
+ this.generateSettings();
+ this.generateData();
+ this.generateDataSub = this.sharedService.dataEvent.subscribe(() => { this.generateData(); });
+ }
+ /** smart table Header Colums @public */
+ public generateColumns(): void {
+ this.columnLists = {
+ name: { title: this.translateService.instant('NAME'), width: '30%', sortDirection: 'asc' },
+ identifier: { title: this.translateService.instant('IDENTIFIER'), width: '35%' },
+ modified: { title: this.translateService.instant('MODIFIED'), width: '15%' },
+ created: { title: this.translateService.instant('CREATED'), width: '15%' },
+ Actions: {
+ name: 'Actions', width: '5%', filter: false, sort: false, type: 'custom',
+ title: this.translateService.instant('ACTIONS'),
+ valuePrepareFunction: (cell: RoleData, row: RoleData): RoleData => row,
+ renderComponent: RolesActionComponent
+ }
+ };
+ }
+
+ /** smart table Data Settings @public */
+ public generateSettings(): void {
+ this.settings = {
+ edit: {
+ editButtonContent: '<i class="fa fa-edit" title="Edit"></i>',
+ confirmSave: true
+ },
+ delete: {
+ deleteButtonContent: '<i class="far fa-trash-alt" title="delete"></i>',
+ confirmDelete: true
+ },
+ columns: this.columnLists,
+ actions: {
+ add: false,
+ edit: false,
+ delete: false,
+ topology: false,
+ position: 'right'
+ },
+ attr: this.sharedService.tableClassConfig(),
+ pager: this.sharedService.paginationPagerConfig(),
+ noDataMessage: this.translateService.instant('NODATAMSG')
+ };
+ }
+
+ /** smart table listing manipulation @public */
+ public onChange(perPageValue: number): void {
+ this.dataSource.setPaging(1, perPageValue, true);
+ }
+
+ /** convert UserRowSelect Function @private */
+ public onUserRowSelect(event: MessageEvent): void {
+ Object.assign(event.data, { page: 'roles' });
+ this.dataService.changeMessage(event.data);
+ }
+
+ /** Fetching the role data from API and Load it in the smarttable @public */
+ public generateData(): void {
+ this.isLoadingResults = true;
+ this.roleData = [];
+ this.restService.getResource(environment.ROLES_URL).subscribe((roleList: RoleDetails[]) => {
+ roleList.forEach((role: RoleDetails) => {
+ const roleDataObj: RoleData = this.generateRoleData(role);
+ this.roleData.push(roleDataObj);
+ });
+ this.dataSource.load(this.roleData).then((data: boolean) => {
+ this.isLoadingResults = false;
+ }).catch();
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'get');
+ this.isLoadingResults = false;
+ });
+ }
+
+ /** Generate role data object and return for the datasource @public */
+ public generateRoleData(roleData: RoleDetails): RoleData {
+ return {
+ name: roleData.name,
+ identifier: roleData._id,
+ modified: this.sharedService.convertEpochTime(Number(roleData._admin.modified)),
+ created: this.sharedService.convertEpochTime(Number(roleData._admin.created)),
+ permissions: roleData.permissions
+ };
+ }
+
+ /** Create role click handler @public */
+ public createRole(): void {
+ this.router.navigate(['/roles/create']).catch(() => {
+ // Catch Navigation Error
+ });
+ }
+
+ /** Lifecyle hook which get trigger on component destruction @private */
+ public ngOnDestroy(): void {
+ this.generateDataSub.unsubscribe();
+ }
+
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<router-outlet></router-outlet>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file SDN Controller Component.
+ */
+import { Component, Injector } from '@angular/core';
+import { Router, RouterEvent } from '@angular/router';
+
+/**
+ * Creating component
+ * @Component takes SDNControllerComponent.html as template url
+ */
+@Component({
+ templateUrl: './SDNControllerComponent.html',
+ styleUrls: ['./SDNControllerComponent.scss']
+})
+/** Exporting a class @exports SDNControllerComponent */
+export class SDNControllerComponent {
+ /** Invoke service injectors @public */
+ public injector: Injector;
+
+ /** Holds teh instance of AuthService class of type AuthService @private */
+ private router: Router;
+
+ // creates packages component
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.router = this.injector.get(Router);
+ this.router.events.subscribe((event: RouterEvent) => {
+ this.redirectToList(event.url);
+ });
+ }
+
+ /** Return to list NS Package List */
+ public redirectToList(getURL: string): void {
+ if (getURL === '/sdn') {
+ this.router.navigate(['/sdn/details']).catch();
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file SDN Controller module.
+ */
+import { CommonModule } from '@angular/common';
+import { HttpClientModule } from '@angular/common/http';
+import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { RouterModule, Routes } from '@angular/router';
+import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
+import { NgSelectModule } from '@ng-select/ng-select';
+import { TranslateModule } from '@ngx-translate/core';
+import { DataService } from 'DataService';
+import { LoaderModule } from 'LoaderModule';
+import { NewSDNControllerComponent } from 'NewSDNControllerComponent';
+import { Ng2SmartTableModule } from 'ng2-smart-table';
+import { PagePerRowModule } from 'PagePerRowModule';
+import { PageReloadModule } from 'PageReloadModule';
+import { SDNControllerComponent } from 'SDNControllerComponent';
+import { SDNControllerDetailsComponent } from 'SDNControllerDetailsComponent';
+import { SDNControllerInfoComponent } from 'SDNControllerInfoComponent';
+
+/** To halndle project information */
+const projectInfo: {} = localStorage.getItem('project') !== null ? { title: localStorage.getItem('project'), url: '/' } : {};
+
+/**
+ * configures routers
+ */
+const routes: Routes = [
+ {
+ path: '',
+ component: SDNControllerComponent,
+ children: [
+ {
+ path: 'details',
+ data: {
+ breadcrumb: [{ title: 'PAGE.DASHBOARD.DASHBOARD', url: '/' }, { title: 'PAGE.DASHBOARD.PROJECTS', url: '/projects' },
+ projectInfo, { title: 'SDNCONTROLLER', url: null }]
+ },
+ component: SDNControllerDetailsComponent
+ }
+ ]
+ }
+];
+
+/**
+ * Creating @NgModule component for Modules
+ */
+@NgModule({
+ imports: [ReactiveFormsModule.withConfig({ warnOnNgModelWithFormControl: 'never' }), FormsModule, CommonModule,
+ HttpClientModule, NgSelectModule, Ng2SmartTableModule, TranslateModule, RouterModule.forChild(routes), NgbModule,
+ PagePerRowModule, LoaderModule, PageReloadModule],
+ declarations: [SDNControllerComponent, SDNControllerDetailsComponent, SDNControllerInfoComponent, NewSDNControllerComponent],
+ providers: [DataService],
+ entryComponents: [SDNControllerInfoComponent, NewSDNControllerComponent],
+ schemas: [CUSTOM_ELEMENTS_SCHEMA]
+})
+/** Exporting a class @exports SDNControllerModule */
+export class SDNControllerModule {
+ /**
+ * Lifecyle Hooks the trigger before component is instantiate
+ */
+ public ngOnInit(): void {
+ //Empty Class
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<form [formGroup]="sdnControllerForm" (ngSubmit)="sdnControllerFormSubmit()" autocomplete="off">
+ <div class="modal-header">
+ <h4 class="modal-title" id="modal-basic-title">{{'PAGE.SDNCONTROLLER.NEWSDNCONTROLLER' | translate}}</h4>
+ <button class="button-xs" type="button" class="close" aria-label="Close" (click)="activeModal.close()">
+ <i class="fas fa-times-circle text-danger"></i>
+ </button>
+ </div>
+ <div class="modal-body modal-body-custom-height">
+ <div class="form-group row">
+ <label class="col-sm-12 col-form-label mandatory-label"
+ [ngClass]="{'text-danger': sdnControllerForm.invalid === true && submitted === true}">{{'MANDATORYCHECK' | translate}}</label>
+ <label class="col-sm-4 col-form-label" for="name">{{'NAME' | translate}}*</label>
+ <div class="col-sm-8">
+ <input autocomplete="off" class="form-control" placeholder="{{'NAME' | translate}}" type="text"
+ formControlName="name" id="name" [ngClass]="{ 'is-invalid': submitted && f.name.errors }" required>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label" for="sdn_type">{{'TYPE' | translate}}*</label>
+ <div class="col-sm-8">
+ <ng-select [items]="sdnType" placeholder="{{'SELECT' | translate}}" bindLabel="title" bindValue="value"
+ formControlName="type" id="sdn_type" [(ngModel)]="sdnTypeMod"
+ [ngClass]="{ 'is-invalid': submitted && f.type.errors }" required>
+ </ng-select>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label" for="username">{{'USERNAME' | translate}}*</label>
+ <div class="col-sm-8">
+ <input autocomplete="off" class="form-control" placeholder="{{'USERNAME' | translate}}" type="text"
+ formControlName="user" id="username" [ngClass]="{ 'is-invalid': submitted && f.user.errors }"
+ required>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label" for="password">{{'PASSWORD' | translate}}*</label>
+ <div class="col-sm-8">
+ <input autocomplete="off" class="form-control" placeholder="{{'PASSWORD' | translate}}" type="password"
+ formControlName="password" id="password"
+ [ngClass]="{ 'is-invalid': submitted && f.password.errors }" required>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label" for="ip">{{'IP' | translate}}*</label>
+ <div class="col-sm-8">
+ <input autocomplete="off" class="form-control" placeholder="{{'IP' | translate}}" type="text"
+ formControlName="ip" id="ip" [ngClass]="{ 'is-invalid': submitted && f.ip.errors }" required>
+ <div *ngIf="sdnControllerForm.invalid" class="invalid-feedback">
+ <div *ngIf="f.ip.errors && f.ip.value">{{'DOMVALIDATIONS.INVALIDIPADDRESS' | translate}}</div>
+ </div>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label" for="port">{{'PORT' | translate}}*</label>
+ <div class="col-sm-8">
+ <input autocomplete="off" class="form-control" placeholder="{{'PORT' | translate}}" type="text"
+ formControlName="port" id="port" [ngClass]="{ 'is-invalid': submitted && f.port.errors }" required>
+ <div *ngIf="sdnControllerForm.invalid" class="invalid-feedback">
+ <div *ngIf="f.port.errors && f.port.value">{{'DOMVALIDATIONS.INVALIDPORTADDRESS' | translate}}</div>
+ </div>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label" for="dpid">{{'PAGE.SDNCONTROLLER.DPID' | translate}}*</label>
+ <div class="col-sm-8">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.SDNCONTROLLER.DPIDPLACEHOLDER' | translate}}" type="text"
+ formControlName="dpid" id="dpid" [ngClass]="{ 'is-invalid': submitted && f.dpid.errors }" required>
+ <div *ngIf="sdnControllerForm.invalid" class="invalid-feedback">
+ <div *ngIf="f.dpid.errors && f.dpid.value">{{'DOMVALIDATIONS.INVALIDDPID' | translate}}</div>
+ </div>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label" for="version">{{'VERSION' | translate}}</label>
+ <div class="col-sm-8">
+ <input autocomplete="off" class="form-control" placeholder="{{'VERSION' | translate}}" type="text"
+ formControlName="version" id="version">
+ </div>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-danger" (click)="activeModal.close()">{{'CANCEL' | translate}}</button>
+ <button type="submit" class="btn btn-primary">{{'CREATE' | translate}}</button>
+ </div>
+</form>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @file SDN Controller Component.
+ */
+import { HttpHeaders } from '@angular/common/http';
+import { Component, Injector, OnInit } from '@angular/core';
+import { FormBuilder, FormGroup, Validators } from '@angular/forms';
+import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateService } from '@ngx-translate/core';
+import { NotifierService } from 'angular-notifier';
+import { APIURLHEADER, ERRORDATA, MODALCLOSERESPONSEDATA, SDN_TYPES, TYPESECTION } from 'CommonModel';
+import { environment } from 'environment';
+import { RestService } from 'RestService';
+import { SharedService } from 'SharedService';
+
+/**
+ * Creating component
+ * @Component takes NewSDNControllerComponent.html as template url
+ */
+@Component({
+ templateUrl: './NewSDNControllerComponent.html',
+ styleUrls: ['./NewSDNControllerComponent.scss']
+})
+/** Exporting a class @exports NewSDNControllerComponent */
+export class NewSDNControllerComponent implements OnInit {
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** Set SDN Type select to empty @public */
+ public sdnTypeMod: string = null;
+
+ /** Setting SDN types in array @public */
+ public sdnType: TYPESECTION[];
+
+ /** New SDN controller form controls using formgroup @public */
+ public sdnControllerForm: FormGroup;
+
+ /** Form submission Add */
+ public submitted: boolean = false;
+
+ /** Instance for active modal service @public */
+ public activeModal: NgbActiveModal;
+
+ /** Check the loading results for loader status @public */
+ public isLoadingResults: boolean = false;
+
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+
+ /** Instance of the rest service @private */
+ private restService: RestService;
+
+ /** Controls the header form @private */
+ private headers: HttpHeaders;
+
+ /** FormBuilder instance added to the formBuilder @private */
+ private formBuilder: FormBuilder;
+
+ /** Notifier service to popup notification @private */
+ private notifierService: NotifierService;
+
+ /** Contains tranlsate instance @private */
+ private translateService: TranslateService;
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.restService = this.injector.get(RestService);
+ this.formBuilder = this.injector.get(FormBuilder);
+ this.notifierService = this.injector.get(NotifierService);
+ this.translateService = this.injector.get(TranslateService);
+ this.activeModal = this.injector.get(NgbActiveModal);
+ this.sharedService = this.injector.get(SharedService);
+
+ /** Initializing Form Action */
+ this.sdnControllerForm = this.formBuilder.group({
+ name: ['', Validators.required],
+ type: ['', Validators.required],
+ user: ['', Validators.required],
+ password: ['', Validators.required],
+ ip: ['', Validators.pattern(this.sharedService.REGX_IP_PATTERN)],
+ port: ['', Validators.pattern(this.sharedService.REGX_PORT_PATTERN)],
+ dpid: ['', Validators.pattern(this.sharedService.REGX_DPID_PATTERN)],
+ version: ['']
+ });
+ }
+
+ /** convenience getter for easy access to form fields */
+ get f(): FormGroup['controls'] { return this.sdnControllerForm.controls; }
+
+ /**
+ * Lifecyle Hooks the trigger before component is instantiate
+ */
+ public ngOnInit(): void {
+ this.sdnType = SDN_TYPES;
+ this.headers = new HttpHeaders({
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
+ });
+ }
+
+ /** On modal submit sdnControllerFormSubmit will called @public */
+ public sdnControllerFormSubmit(): void {
+ this.submitted = true;
+ const modalData: MODALCLOSERESPONSEDATA = {
+ message: 'Done'
+ };
+ this.sharedService.cleanForm(this.sdnControllerForm);
+ if (!this.sdnControllerForm.invalid) {
+ this.isLoadingResults = true;
+ const apiURLHeader: APIURLHEADER = {
+ url: environment.SDNCONTROLLER_URL,
+ httpOptions: { headers: this.headers }
+ };
+ if (this.sdnControllerForm.value.port) {
+ this.sdnControllerForm.value.port = +this.sdnControllerForm.value.port;
+ }
+ if (this.sdnControllerForm.value.version === '') {
+ this.sdnControllerForm.value.version = undefined;
+ }
+ this.restService.postResource(apiURLHeader, this.sdnControllerForm.value)
+ .subscribe((result: {}) => {
+ this.activeModal.close(modalData);
+ this.isLoadingResults = false;
+ this.notifierService.notify('success', this.translateService.instant('PAGE.SDNCONTROLLER.CREATEDSUCCESSFULLY'));
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'post');
+ this.isLoadingResults = false;
+ });
+ }
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="row d-flex flex-row justify-content-between">
+ <div class="d-flex align-items-center header-style">{{'PAGE.SDNCONTROLLER.REGISTEREDSDNCONTROLLER' | translate}}</div>
+ <span class="button">
+ <button class="btn btn-primary" type="button" placement="top" container="body" ngbTooltip="{{'PAGE.SDNCONTROLLER.NEWSDNCONTROLLER' | translate}}"
+ (click)="composeSDN()">
+ <i class="fas fa-plus-circle" aria-hidden="true"></i>
+ {{'PAGE.SDNCONTROLLER.NEWSDNCONTROLLER' | translate}}
+ </button>
+ </span>
+</div>
+<div class="row mt-2 mb-0 list-utilites-actions">
+ <div class="col-auto mr-auto">
+ <nav class="custom-items-config">
+ <span><i class="fas fa-clock text-warning"></i>{{operationalStateFirstStep}}</span>
+ <span><i class="fas fa-check-circle text-success"></i>{{operationalStateSecondStep}}</span>
+ <span><i class="fas fa-times-circle text-danger"></i>{{operationalStateThirdStep}}</span>
+ </nav>
+ </div>
+ <page-per-row class="mr-2" (pagePerRow)="onChange($event)"></page-per-row>
+ <page-reload></page-reload>
+</div>
+<div class="smarttable-style bg-white mt-1">
+ <ng2-smart-table [ngClass]="checkDataClass" [settings]="settings" [source]="dataSource" (userRowSelect)="onUserRowSelect($event)">
+ </ng2-smart-table>
+</div>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file SDN Controller details Component.
+ */
+import { Component, Injector, OnDestroy, OnInit } from '@angular/core';
+import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateService } from '@ngx-translate/core';
+import { CONFIGCONSTANT, ERRORDATA, MODALCLOSERESPONSEDATA, SDN_TYPES } from 'CommonModel';
+import { DataService } from 'DataService';
+import { environment } from 'environment';
+import { NewSDNControllerComponent } from 'NewSDNControllerComponent';
+import { LocalDataSource } from 'ng2-smart-table';
+import { RestService } from 'RestService';
+import { Subscription } from 'rxjs';
+import { SDNControllerActionComponent } from 'SDNControllerActionComponent';
+import { SDNControllerList, SDNControllerModel } from 'SDNControllerModel';
+import { SharedService } from 'SharedService';
+
+/**
+ * Creating component
+ * @Component takes SDNControllerDetailsComponent.html as template url
+ */
+@Component({
+ templateUrl: './SDNControllerDetailsComponent.html',
+ styleUrls: ['./SDNControllerDetailsComponent.scss']
+})
+/** Exporting a class @exports SDNControllerDetailsComponent */
+export class SDNControllerDetailsComponent implements OnInit, OnDestroy {
+ /** Injector to invoke other services @public */
+ public injector: Injector;
+
+ /** Selected list array @public */
+ public selectList: object[] = [];
+
+ /** Instance component are stored in settings @public */
+ public settings: {} = {};
+
+ /** Contains objects for menu settings @public */
+ public columnList: {} = {};
+
+ /** Data of smarttable populate through LocalDataSource @public */
+ public dataSource: LocalDataSource = new LocalDataSource();
+
+ /** Check the loading results @public */
+ public isLoadingResults: boolean = true;
+
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+
+ /** Class for empty and present data @public */
+ public checkDataClass: string;
+
+ /** operational State init data @public */
+ public operationalStateFirstStep: string = CONFIGCONSTANT.sdnOperationalStateFirstStep;
+
+ /** operational State running data @public */
+ public operationalStateSecondStep: string = CONFIGCONSTANT.sdnOperationalStateStateSecondStep;
+
+ /** operational State failed data @public */
+ public operationalStateThirdStep: string = CONFIGCONSTANT.sdnOperationalStateThirdStep;
+
+ /** Instance of the rest service @private */
+ private restService: RestService;
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ /** dataService to pass the data from one component to another @private */
+ private dataService: DataService;
+
+ /** Contains tranlsate instance @private */
+ private translateService: TranslateService;
+
+ /** Formation of appropriate Data for LocalDatasource @private */
+ private sdnData: {}[] = [];
+
+ /** Instance of the modal service @private */
+ private modalService: NgbModal;
+
+ /** Instance of subscriptions @private */
+ private generateDataSub: Subscription;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.restService = this.injector.get(RestService);
+ this.translateService = this.injector.get(TranslateService);
+ this.sharedService = this.injector.get(SharedService);
+ this.dataService = this.injector.get(DataService);
+ this.modalService = this.injector.get(NgbModal);
+ }
+
+ /**
+ * Lifecyle Hooks the trigger before component is instantiate
+ */
+ public ngOnInit(): void {
+ this.generateTableColumn();
+ this.generateTableSettings();
+ this.generateData();
+ this.generateDataSub = this.sharedService.dataEvent.subscribe(() => { this.generateData(); });
+ }
+
+ /** Generate smart table row title and filters @public */
+ public generateTableSettings(): void {
+ this.settings = {
+ columns: this.columnList,
+ actions: { add: false, edit: false, delete: false, position: 'right' },
+ attr: this.sharedService.tableClassConfig(),
+ pager: this.sharedService.paginationPagerConfig(),
+ noDataMessage: this.translateService.instant('NODATAMSG')
+ };
+ }
+
+ /** Generate smart table row title and filters @public */
+ public generateTableColumn(): void {
+ this.columnList = {
+ name: { title: this.translateService.instant('NAME'), width: '15%', sortDirection: 'asc' },
+ identifier: { title: this.translateService.instant('IDENTIFIER'), width: '20%' },
+ type: {
+ title: this.translateService.instant('TYPE'), width: '15%',
+ filter: {
+ type: 'list',
+ config: {
+ selectText: 'Select',
+ list: SDN_TYPES
+ }
+ }
+ },
+ operationalState: {
+ title: this.translateService.instant('OPERATIONALSTATUS'), width: '15%', type: 'html',
+ filter: {
+ type: 'list',
+ config: {
+ selectText: 'Select',
+ list: [
+ { value: this.operationalStateFirstStep, title: this.operationalStateFirstStep },
+ { value: this.operationalStateSecondStep, title: this.operationalStateSecondStep },
+ { value: this.operationalStateThirdStep, title: this.operationalStateThirdStep }
+ ]
+ }
+ },
+ valuePrepareFunction: (cell: SDNControllerList, row: SDNControllerList): string => {
+ if (row.operationalState === this.operationalStateFirstStep) {
+ return `<span class="icon-label" title="${row.operationalState}">
+ <i class="fas fa-clock text-warning"></i>
+ </span>`;
+ } else if (row.operationalState === this.operationalStateSecondStep) {
+ return `<span class="icon-label" title="${row.operationalState}">
+ <i class="fas fa-check-circle text-success"></i>
+ </span>`;
+ } else if (row.operationalState === this.operationalStateThirdStep) {
+ return `<span class="icon-label" title="${row.operationalState}">
+ <i class="fas fa-times-circle text-danger"></i>
+ </span>`;
+ } else {
+ return `<span>${row.operationalState}</span>`;
+ }
+ }
+ },
+ ip: { title: this.translateService.instant('IP'), width: '15%' },
+ port: { title: this.translateService.instant('PORT'), width: '15%' },
+ Actions: {
+ name: 'Action', width: '5%', filter: false, sort: false, type: 'custom',
+ title: this.translateService.instant('ACTIONS'),
+ valuePrepareFunction: (cell: SDNControllerList, row: SDNControllerList): SDNControllerList => row,
+ renderComponent: SDNControllerActionComponent
+ }
+ };
+ }
+
+ /** smart table listing manipulation @public */
+ public onChange(perPageValue: number): void {
+ this.dataSource.setPaging(1, perPageValue, true);
+ }
+
+ /** smart table listing manipulation @public */
+ public onUserRowSelect(event: MessageEvent): void {
+ Object.assign(event.data, { page: 'sdn-controller' });
+ this.dataService.changeMessage(event.data);
+ }
+
+ /** Generate generateSDNData object from loop and return for the datasource @public */
+ public generateSDNList(sdn: SDNControllerModel): SDNControllerList {
+ return {
+ name: sdn.name,
+ identifier: sdn._id,
+ type: sdn.type,
+ operationalState: sdn._admin.operationalState,
+ ip: sdn.ip,
+ port: sdn.port
+ };
+ }
+
+ /** Compose new SDN Controller @public */
+ public composeSDN(): void {
+ const modalRef: NgbModalRef = this.modalService.open(NewSDNControllerComponent, { backdrop: 'static' });
+ modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
+ if (result) {
+ this.sharedService.callData();
+ }
+ }).catch();
+ }
+
+ /**
+ * Lifecyle hook which get trigger on component destruction
+ */
+ public ngOnDestroy(): void {
+ this.generateDataSub.unsubscribe();
+ }
+
+ /** Fetching the data from server to Load in the smarttable @protected */
+ protected generateData(): void {
+ this.isLoadingResults = true;
+ this.sdnData = [];
+ this.restService.getResource(environment.SDNCONTROLLER_URL).subscribe((sdnDetails: {}[]) => {
+ sdnDetails.forEach((res: SDNControllerModel) => {
+ const sdnDataObj: SDNControllerList = this.generateSDNList(res);
+ this.sdnData.push(sdnDataObj);
+ });
+ if (this.sdnData.length > 0) {
+ this.checkDataClass = 'dataTables_present';
+ } else {
+ this.checkDataClass = 'dataTables_empty';
+ }
+ this.dataSource.load(this.sdnData).then((data: {}) => {
+ this.isLoadingResults = false;
+ }).catch();
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'get');
+ this.isLoadingResults = false;
+ });
+ }
+
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="modal-header">
+ <h4 class="modal-title" id="modal-basic-title">{{'PAGE.SDNCONTROLLER.DETAILS' | translate}}</h4>
+ <button class="button-xs" type="button" class="close" aria-label="Close" (click)="activeModal.close()">
+ <i class="fas fa-times-circle text-danger"></i>
+ </button>
+</div>
+<div class="modal-body modal-body-custom-height p-0">
+ <table class="table table-striped table-layout-fixed mb-0" *ngIf="sdnDetails else noData">
+ <tr>
+ <td colspan="2">
+ <b>{{'ID' | translate}}:</b> {{(sdnDetails._id)?sdnDetails._id:''}}
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <b>{{'OPERATIONALSTATE' | translate}}:</b>
+ <span class="badge ml-1" [ngClass]="{'badge-info':sdnDetails._admin.operationalState === operationalStateFirstStep,
+ 'badge-success':sdnDetails._admin.operationalState === operationalStateSecondStep,
+ 'badge-danger':sdnDetails._admin.operationalState === operationalStateThirdStep}">
+ {{(sdnDetails._admin.operationalState)?sdnDetails._admin.operationalState:''}}</span>
+ </td>
+ <td>
+ <b>{{'IP' | translate}}:</b> {{(sdnDetails.ip)?sdnDetails.ip:''}}
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <b>{{'NAME' | translate}}:</b> {{(sdnDetails.name)?sdnDetails.name:''}}
+ </td>
+ <td>
+ <b>{{'PORT' | translate}}:</b> {{(sdnDetails.port)?sdnDetails.port:''}}
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <b>{{'TYPE' | translate}}:</b> {{(sdnDetails.type)?sdnDetails.type:''}}
+ </td>
+ <td>
+ <b>{{'VERSION' | translate}}:</b> {{(sdnDetails.version)?sdnDetails.version:''}}
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <b>{{'USER' | translate}}:</b> {{(sdnDetails.user)?sdnDetails.user:''}}
+ </td>
+ <td>
+ <b>{{'CREATED' | translate}}:</b>
+ {{(sdnDetails._admin.created)?this.sharedService.convertEpochTime(sdnDetails._admin.created):''}}
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <b>{{'PAGE.SDNCONTROLLER.DPID' | translate}}:</b> {{(sdnDetails.dpid)?sdnDetails.dpid:''}}
+ </td>
+ <td>
+ <b>{{'MODIFIED' | translate}}:</b>
+ {{(sdnDetails._admin.modified)?this.sharedService.convertEpochTime(sdnDetails._admin.modified):''}}
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2">
+ <b>{{'DEPLOYED' | translate}}</b> <br>
+ <b>{{'PAGE.SDNCONTROLLER.RO' | translate}}:</b> {{(sdnDetails._admin.deployed.RO)?sdnDetails._admin.deployed.RO:''}}
+ <br>
+ </td>
+ </tr>
+ </table>
+ <ng-template #noData>{{'NODATAERROR' | translate}}</ng-template>
+</div>
+<div class="modal-footer">
+ <button (click)="activeModal.close()" class="btn btn-danger">{{'CANCEL' | translate}}</button>
+</div>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file Info SDN Controller Info Component
+ */
+import { Component, Injector, Input, OnInit } from '@angular/core';
+import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
+import { CONFIGCONSTANT, ERRORDATA, URLPARAMS } from 'CommonModel';
+import { environment } from 'environment';
+import { RestService } from 'RestService';
+import { SDNControllerModel } from 'SDNControllerModel';
+import { SharedService } from 'SharedService';
+
+/**
+ * Creating component
+ * @Component takes SDNControllerInfoComponent.html as template url
+ */
+@Component({
+ templateUrl: './SDNControllerInfoComponent.html',
+ styleUrls: ['./SDNControllerInfoComponent.scss']
+})
+/** Exporting a class @exports SDNControllerInfoComponent */
+export class SDNControllerInfoComponent implements OnInit {
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** Input contains component objects @public */
+ @Input() public params: URLPARAMS;
+
+ /** Contains sdn details @public */
+ public sdnDetails: SDNControllerModel;
+
+ /** Instance for active modal service @public */
+ public activeModal: NgbActiveModal;
+
+ /** Check the loading results for loader status @public */
+ public isLoadingResults: boolean = true;
+
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+
+ /** operational State init data @public */
+ public operationalStateFirstStep: string = CONFIGCONSTANT.sdnOperationalStateFirstStep;
+
+ /** operational State running data @public */
+ public operationalStateSecondStep: string = CONFIGCONSTANT.sdnOperationalStateStateSecondStep;
+
+ /** operational State failed data @public */
+ public operationalStateThirdStep: string = CONFIGCONSTANT.sdnOperationalStateThirdStep;
+
+ /** Instance of the rest service @private */
+ private restService: RestService;
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.restService = this.injector.get(RestService);
+ this.activeModal = this.injector.get(NgbActiveModal);
+ this.sharedService = this.injector.get(SharedService);
+ }
+
+ /**
+ * Lifecyle Hooks the trigger before component is instantiate
+ */
+ public ngOnInit(): void {
+ this.generateData();
+ }
+
+ /** Generate Data function @public */
+ public generateData(): void {
+ this.restService.getResource(environment.SDNCONTROLLER_URL + '/' + this.params.id).subscribe((sdnDetails: SDNControllerModel) => {
+ this.sdnDetails = sdnDetails;
+ this.isLoadingResults = false;
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'get');
+ this.isLoadingResults = false;
+ });
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<form [formGroup]="usersettingsForm" (ngSubmit)="usersettingsSubmit();">
+ <div class="modal-header">
+ <h4 class="modal-title" id="modal-basic-title">{{'PAGE.DASHBOARD.USERSETTINGS' | translate}}</h4>
+ <button class="button-xs" type="button" class="close" aria-label="Close" (click)="activeModal.close()">
+ <i class="fas fa-times-circle text-danger"></i>
+ </button>
+ </div>
+ <div class="modal-body user-settings">
+ <label class="col-sm-12 col-form-label mandatory-label" [ngClass]="{'text-danger': usersettingsForm.invalid === true && submitted === true}">{{'MANDATORYCHECK' | translate}}</label>
+ <div class="row form-group">
+ <div class="col-sm-3">
+ <label for="selectedLanguage">{{'PAGE.USERSETTINGS.LANGUAGE' | translate}}* </label>
+ </div>
+ <div class="col-sm-9">
+ <ng-select [items]="languageList" bindLabel="language" bindValue="code"
+ placeholder="{{'SELECT' | translate}} {{'PAGE.USERSETTINGS.LANGUAGE' | translate}}"
+ formControlName="selectedLanguage" id="selectedLanguage"
+ [ngClass]="{ 'is-invalid': submitted && f.selectedLanguage.errors }" required>
+ </ng-select>
+ </div>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-danger" (click)="activeModal.close()">{{'CANCEL' | translate}}</button>
+ <button type="submit" class="btn btn-primary">{{'SAVE' | translate}}</button>
+ </div>
+</form>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+@import '../../assets/scss/mixins/mixin';
+.user-settings{
+ form label{
+ @include margin-value-percentage(0.5rem, auto, auto, auto);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file User Settings Modal Component.
+ */
+
+import { Component, Injector, OnInit } from '@angular/core';
+import { FormBuilder, FormGroup, Validators } from '@angular/forms';
+import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateService } from '@ngx-translate/core';
+import { SharedService } from 'SharedService';
+
+/**
+ * Creating component
+ * @Component takes UserSettingsComponent.html as template url
+ */
+@Component({
+ templateUrl: './UserSettingsComponent.html',
+ styleUrls: ['./UserSettingsComponent.scss']
+})
+/** Exporting a class @exports UserSettingsComponent */
+export class UserSettingsComponent implements OnInit {
+ /** Invoke service injectors @public */
+ public injector: Injector;
+
+ /** Supported language list for the dropdown */
+ public languageList: {}[];
+
+ /** FormGroup instance added to the form @ html @public */
+ public usersettingsForm: FormGroup;
+
+ /** Instance for active modal service @public */
+ public activeModal: NgbActiveModal;
+
+ /** Form submission Add */
+ public submitted: boolean = false;
+
+ /** FormBuilder instance added to the formBuilder @private */
+ private formBuilder: FormBuilder;
+
+ /** Instance for translate service @private */
+ private translateService: TranslateService;
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.formBuilder = this.injector.get(FormBuilder);
+ this.activeModal = this.injector.get(NgbActiveModal);
+ this.translateService = this.injector.get(TranslateService);
+ this.sharedService = this.injector.get(SharedService);
+ }
+
+ /**
+ * Lifecyle Hooks the trigger before component is instantiate
+ */
+ public ngOnInit(): void {
+ this.initializeSettings();
+ }
+
+ /** Initialize user's settings */
+ public initializeSettings(): void {
+ this.languageList = this.sharedService.languageCodeList();
+ /** Initializing Form Action */
+ this.usersettingsForm = this.formBuilder.group({
+ selectedLanguage: [null, [Validators.required]]
+ });
+ const setLanguage: string = localStorage.getItem('languageCode');
+ if (setLanguage !== null && this.validateLanguageList(setLanguage)) {
+ // tslint:disable-next-line:no-backbone-get-set-outside-model
+ this.usersettingsForm.get('selectedLanguage').setValue(setLanguage);
+ } else {
+ // tslint:disable-next-line:no-backbone-get-set-outside-model
+ this.usersettingsForm.get('selectedLanguage').setValue('en');
+ }
+ }
+
+ /** convenience getter for easy access to form fields */
+ get f(): FormGroup['controls'] { return this.usersettingsForm.controls; }
+
+ /** On modal submit UserSettingsSubmit will called @public */
+ public usersettingsSubmit(): void {
+ this.submitted = true;
+ if (!this.usersettingsForm.invalid) {
+ const selectedLanguage: string = this.usersettingsForm.value.selectedLanguage;
+ localStorage.setItem('languageCode', this.usersettingsForm.value.selectedLanguage);
+ this.translateService.use(selectedLanguage);
+ location.reload();
+ }
+ }
+ /** Validate language code in the language list @private */
+ private validateLanguageList(setLanguage: string): boolean {
+ return this.languageList.some((item: { code: string }) => item.code === setLanguage);
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<router-outlet></router-outlet>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file users details Component.
+ */
+import { Component, Injector } from '@angular/core';
+import { Router, RouterEvent } from '@angular/router';
+
+/**
+ * Creating component
+ * @Component takes UsersComponent.html as template url
+ */
+@Component({
+ templateUrl: './UsersComponent.html',
+ styleUrls: ['./UsersComponent.scss']
+})
+/** Exporting a class @exports UsersComponent */
+export class UsersComponent {
+ /** Invoke service injectors @public */
+ public injector: Injector;
+
+ /** Holds teh instance of AuthService class of type AuthService @private */
+ private router: Router;
+
+ // creates packages component
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.router = this.injector.get(Router);
+ this.router.events.subscribe((event: RouterEvent) => {
+ this.redirectToList(event.url);
+ });
+ }
+
+ /** Return to list NS Package List */
+ public redirectToList(getURL: string): void {
+ if (getURL === '/users') {
+ this.router.navigate(['/users/details']).catch();
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file Users module.
+ */
+import { CommonModule } from '@angular/common';
+import { HttpClientModule } from '@angular/common/http';
+import { NgModule } from '@angular/core';
+import { FlexLayoutModule } from '@angular/flex-layout';
+import { FormsModule } from '@angular/forms';
+import { ReactiveFormsModule } from '@angular/forms';
+import { RouterModule, Routes } from '@angular/router';
+import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
+import { NgSelectModule } from '@ng-select/ng-select';
+import { TranslateModule } from '@ngx-translate/core';
+import { AddEditUserComponent } from 'AddEditUserComponent';
+import { DataService } from 'DataService';
+import { LoaderModule } from 'LoaderModule';
+import { Ng2SmartTableModule } from 'ng2-smart-table';
+import { PagePerRowModule } from 'PagePerRowModule';
+import { PageReloadModule } from 'PageReloadModule';
+import { ProjectRoleComponent } from 'ProjectRoleComponent';
+import { UserDetailsComponent } from 'UserDetailsComponent';
+import { UsersComponent } from 'UsersComponent';
+
+/** const values for dashboard Routes */
+const routes: Routes = [
+ {
+ path: '',
+ component: UsersComponent,
+ children: [
+ {
+ path: 'details',
+ data: {
+ breadcrumb: [{ title: 'PAGE.DASHBOARD.DASHBOARD', url: '/' }, { title: 'PAGE.DASHBOARD.USERS', url: null }]
+ },
+ component: UserDetailsComponent
+ }
+ ]
+ }
+];
+
+/**
+ * Creating @NgModule component for Modules
+ */
+@NgModule({
+ imports: [ReactiveFormsModule, FormsModule, CommonModule, HttpClientModule, Ng2SmartTableModule, TranslateModule,
+ FlexLayoutModule, NgSelectModule, NgbModule, RouterModule.forChild(routes), PagePerRowModule, LoaderModule, PageReloadModule],
+ declarations: [UsersComponent, UserDetailsComponent, AddEditUserComponent, ProjectRoleComponent],
+ providers: [DataService],
+ entryComponents: [AddEditUserComponent, ProjectRoleComponent]
+})
+/** Exporting a class @exports UsersModule */
+export class UsersModule {
+ /**
+ * Lifecyle Hooks the trigger before component is instantiate
+ */
+ public ngOnInit(): void {
+ // Empty Block
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<form [formGroup]="userForm" (ngSubmit)="userAction(userType)" autocomplete="off">
+ <div class="modal-header">
+ <h4 class="modal-title" id="modal-basic-title">{{userTitle}}</h4>
+ <button class="button-xs" type="button" class="close" aria-label="Close" (click)="activeModal.close()">
+ <i class="fas fa-times-circle text-danger"></i>
+ </button>
+ </div>
+ <div class="modal-body">
+ <label class="col-sm-12 col-form-label mandatory-label"
+ [ngClass]="{'text-danger': userForm.invalid === true && submitted === true}">{{'MANDATORYCHECK' | translate}}</label>
+ <div class="row form-group" *ngIf="userType === 'add' || userType === 'editUserName'">
+ <div class="col-sm-4">
+ <label for="userName">{{'PAGE.USERS.USERNAME' | translate}} *</label>
+ </div>
+ <div class="col-sm-8">
+ <input class="form-control" placeholder="{{'PAGE.USERS.USERNAME' | translate}}" type="text"
+ formControlName="userName" id="userName" [ngClass]="{ 'is-invalid': submitted && f.userName.errors }"
+ required>
+ </div>
+ <div *ngIf="submitted && f.userName.errors" class="input-validation-msg">
+ <div *ngIf="f.userName.errors.minlength">
+ {{'PAGE.LOGIN.USERNAMEMINLENGTHVALIDMESSAGE' | translate}} </div>
+ </div>
+ </div>
+ <ng-container *ngIf="userType === 'add' || userType === 'editPassword'">
+ <div class="row form-group">
+ <div class="col-sm-4">
+ <label for="password">{{'PAGE.USERS.PASSWORD' | translate}} *</label>
+ </div>
+ <div class="col-sm-8">
+ <input class="form-control" placeholder="{{'PAGE.USERS.PASSWORD' | translate}}" minlength="8" maxlength="50"
+ type="password" formControlName="password" id="password" autocomplete="new-password"
+ [ngClass]="{ 'is-invalid': submitted && f.password.errors }" required>
+ </div>
+ <div class="input-validation-msg">
+ <div *ngIf="userForm?.controls.password.hasError('minlength') || userForm?.controls.password.errors?.pattern">
+ {{'PAGE.LOGIN.PASSWORDMINLENGTHVALIDMESSAGE' | translate}} </div>
+ </div>
+ </div>
+ <div class="row form-group">
+ <div class="col-sm-4">
+ <label for="password2">{{'PAGE.USERS.CONFPASSWORD' | translate}} *</label>
+ </div>
+ <div class="col-sm-8">
+ <input class="form-control" placeholder="{{'PAGE.USERS.CONFPASSWORD' | translate}}" type="password"
+ formControlName="password2" id="password2" autocomplete="new-password"
+ [ngClass]="{ 'is-invalid': submitted && f.password2.errors }" required>
+ <div class="mr-top-5" *ngIf="userForm?.controls.password.value && userForm?.controls.password2.value">
+ <i class="far"
+ [ngClass]="{'fa-times-circle text-danger':userForm?.controls.password.value !== userForm?.controls.password2.value,
+ 'fa-check-circle text-success':userForm?.controls.password.value === userForm?.controls.password2.value}"></i>
+ {{'PAGE.USERS.PASSWORDMATCH' | translate}}
+ </div>
+ </div>
+ </div>
+ </ng-container>
+ <div class="form-group row" *ngIf="userType === 'add'">
+ <label class="col-sm-4 col-form-label">{{'DOMAIN' | translate}} {{'NAME' | translate}}</label>
+ <div class="col-sm-8">
+ <ng-select [clearable]="false" placeholder="{{'SELECT' | translate}}" [items]="domains" bindLabel="text"
+ bindValue="id" formControlName="domain_name" id="domain_name"
+ [ngClass]="{ 'is-invalid': submitted && f.domain_name.errors }"></ng-select>
+ </div>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-danger" (click)="activeModal.close()">{{'CANCEL' | translate}}</button>
+ <button *ngIf="userType==='add'" type="submit" class="btn btn-primary">{{'CREATE' | translate}}</button>
+ <button *ngIf="userType!=='add'" type="submit" class="btn btn-primary">{{'APPLY' | translate}}</button>
+ </div>
+</form>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+@import '../../../assets/scss/mixins/mixin';
+@import '../../../assets/scss/variable';
+.input-validation-msg{
+ color:$red;
+ text-align:left;
+ @include padding-value(0, 0, 0, 10);
+ @include font(null, 11px, null);
+}
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file Add Edit Component.
+ */
+import { HttpHeaders } from '@angular/common/http';
+import { Component, Injector, Input, OnInit } from '@angular/core';
+import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms';
+import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateService } from '@ngx-translate/core';
+import { NotifierService } from 'angular-notifier';
+import { AuthenticationService } from 'AuthenticationService';
+import { APIURLHEADER, ERRORDATA, MODALCLOSERESPONSEDATA } from 'CommonModel';
+import { environment } from 'environment';
+import { RestService } from 'RestService';
+import { SharedService } from 'SharedService';
+import { isNullOrUndefined } from 'util';
+
+/**
+ * Creating component
+ * @Component takes AddEditUserComponent.html as template url
+ */
+@Component({
+ templateUrl: './AddEditUserComponent.html',
+ styleUrls: ['./AddEditUserComponent.scss']
+})
+/** Exporting a class @exports AddEditUserComponent */
+export class AddEditUserComponent implements OnInit {
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** Instance for active modal service @public */
+ public activeModal: NgbActiveModal;
+
+ /** FormGroup user Edit Account added to the form @ html @public */
+ public userForm: FormGroup;
+
+ /** Form submission Add */
+ public submitted: boolean = false;
+
+ /** Input contains Modal dialog component Instance @public */
+ @Input() public userTitle: string;
+
+ /** Input contains Modal dialog component Instance @public */
+ @Input() public userType: string;
+
+ /** Input contains Modal dialog component Instance @public */
+ @Input() public userID: string;
+
+ /** Input contains Modal dialog component Instance @public */
+ @Input() public userName: string;
+
+ /** Check the loading results for loader status @public */
+ public isLoadingResults: boolean = false;
+
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+
+ /** Holds list of domains @public */
+ public domains: {}[] = [];
+
+ /** Instance of the rest service @private */
+ private restService: RestService;
+
+ /** FormBuilder instance added to the formBuilder @private */
+ private formBuilder: FormBuilder;
+
+ /** Controls the header form @private */
+ private headers: HttpHeaders;
+
+ /** Notifier service to popup notification @private */
+ private notifierService: NotifierService;
+
+ /** Contains tranlsate instance @private */
+ private translateService: TranslateService;
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ /** ModalData instance of modal @private */
+ private modalData: MODALCLOSERESPONSEDATA;
+
+ /** Utilizes auth service for any auth operations @private */
+ private authService: AuthenticationService;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.formBuilder = this.injector.get(FormBuilder);
+ this.restService = this.injector.get(RestService);
+ this.activeModal = this.injector.get(NgbActiveModal);
+ this.notifierService = this.injector.get(NotifierService);
+ this.translateService = this.injector.get(TranslateService);
+ this.sharedService = this.injector.get(SharedService);
+ this.authService = this.injector.get(AuthenticationService);
+
+ /** Initializing Form Action */
+ this.userForm = this.formBuilder.group({
+ userName: ['', Validators.required],
+ password: [null, [Validators.required, Validators.pattern(this.sharedService.REGX_PASSWORD_PATTERN)]],
+ password2: [null, Validators.required],
+ domain_name: [null]
+ });
+ }
+
+ /** convenience getter for easy access to form fields */
+ get f(): FormGroup['controls'] { return this.userForm.controls; }
+
+ /** Lifecyle Hooks the trigger before component is instantiate @public */
+ public ngOnInit(): void {
+ this.headers = new HttpHeaders({
+ 'Content-Type': 'application/json',
+ Accept: 'application/json',
+ 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
+ });
+ if (this.userType === 'add') {
+ this.getDomainName();
+ } else if (this.userType === 'editUserName') {
+ this.userForm.patchValue({ userName: this.userName });
+ }
+ }
+
+ /** On modal submit users acction will called @public */
+ public userAction(userType: string): void {
+ if (userType === 'editPassword') {
+ this.getFormControl('userName').setValidators([]);
+ this.getFormControl('userName').updateValueAndValidity();
+ } else if (userType === 'editUserName') {
+ this.getFormControl('password').setValidators([]);
+ this.getFormControl('password').updateValueAndValidity();
+ this.getFormControl('password2').setValidators([]);
+ this.getFormControl('password2').updateValueAndValidity();
+ }
+ this.submitted = true;
+ this.modalData = {
+ message: 'Done'
+ };
+ this.sharedService.cleanForm(this.userForm);
+ if (!this.userForm.invalid) {
+ if (this.userForm.value.password !== this.userForm.value.password2) {
+ this.notifierService.notify('error', this.translateService.instant('PAGE.USERS.PASSWORDCONFLICT'));
+ return;
+ }
+ if (userType === 'add') {
+ this.addUser();
+ } else if (userType === 'editUserName' || userType === 'editPassword') {
+ this.editUser();
+ }
+ }
+ }
+
+ /** Add user @public */
+ public addUser(): void {
+ this.isLoadingResults = true;
+ const payLoad: {} = JSON.stringify({
+ username: (this.userForm.value.userName).toLowerCase(),
+ password: (this.userForm.value.password),
+ domain_name: !isNullOrUndefined(this.userForm.value.domain_name) ? this.userForm.value.domain_name : undefined
+ });
+ const apiURLHeader: APIURLHEADER = {
+ url: environment.USERS_URL,
+ httpOptions: { headers: this.headers }
+ };
+ this.restService.postResource(apiURLHeader, payLoad).subscribe((result: {}) => {
+ this.activeModal.close(this.modalData);
+ this.isLoadingResults = false;
+ this.notifierService.notify('success', this.translateService.instant('PAGE.USERS.CREATEDSUCCESSFULLY'));
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'post');
+ this.isLoadingResults = false;
+ });
+ }
+
+ /** Edit user @public */
+ public editUser(): void {
+ this.isLoadingResults = true;
+ const payLoad: { username?: string, password?: string } = {};
+ if (this.userType === 'editPassword') {
+ payLoad.password = (this.userForm.value.password);
+ } else {
+ payLoad.username = this.userForm.value.userName.toLowerCase();
+ }
+ const apiURLHeader: APIURLHEADER = {
+ url: environment.USERS_URL + '/' + this.userID,
+ httpOptions: { headers: this.headers }
+ };
+ this.restService.patchResource(apiURLHeader, payLoad).subscribe((result: {}) => {
+ this.checkUsername(payLoad);
+ this.activeModal.close(this.modalData);
+ this.isLoadingResults = false;
+ this.notifierService.notify('success', this.translateService.instant('PAGE.USERS.EDITEDSUCCESSFULLY'));
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'put');
+ this.isLoadingResults = false;
+ });
+ }
+ /** Get domain name @private */
+ private getDomainName(): void {
+ this.isLoadingResults = true;
+ this.restService.getResource(environment.DOMAIN_URL).subscribe((domains: { project_domain_name: string, user_domain_name: string }) => {
+ let domainNames: string[] = [];
+ if (!isNullOrUndefined(domains.project_domain_name)) {
+ domainNames = domainNames.concat(domains.project_domain_name.split(','));
+ }
+ if (!isNullOrUndefined(domains.user_domain_name)) {
+ domainNames = domainNames.concat(domains.user_domain_name.split(','));
+ }
+ domainNames = Array.from(new Set(domainNames));
+ this.checkDomainNames(domainNames);
+ this.isLoadingResults = false;
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'get');
+ this.isLoadingResults = false;
+ });
+ }
+
+ /** Check the domain names and create modal for domain select @private */
+ private checkDomainNames(domainNames: string[]): void {
+ if (domainNames.length > 0) {
+ domainNames.forEach((domainName: string) => {
+ if (!domainName.endsWith(':ro')) {
+ this.domains.push({ id: domainName, text: domainName });
+ }
+ });
+ }
+ }
+
+ /** Used to get the AbstractControl of controlName passed @private */
+ private getFormControl(controlName: string): AbstractControl {
+ return this.userForm.controls[controlName];
+ }
+
+ /** Method to check loggedin username and update @private */
+ private checkUsername(payLoad: { username?: string }): void {
+ const logUsername: string = localStorage.getItem('username');
+ if (this.userType === 'editUserName' && logUsername === this.userName) {
+ this.authService.userName.next(payLoad.username);
+ localStorage.setItem('username', payLoad.username);
+ }
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="modal-header">
+ <h4 class="modal-title" id="modal-basic-title">{{userTitle}}</h4>
+ <button class="button-xs" type="button" class="close" aria-label="Close" (click)="activeModal.close()">
+ <i class="fas fa-times-circle text-danger"></i>
+ </button>
+</div>
+<form [formGroup]="projectRoleForm" (ngSubmit)="addProjectRole()">
+ <div class="modal-body" *ngIf="userDetails" formArrayName="project_role_mappings">
+ <div class="form-group row p-2 bg-light text-white projects-roles-head text-white justify-content-end">
+ <div class="col-4">
+ <button type="button" class="btn btn-primary" (click)="addMapping()">
+ <i class="fas fa-plus-circle"></i> {{'PAGE.USERS.ADDMAPPINGS' | translate}}</button>
+ </div>
+ </div>
+ <label class="col-sm-12 col-form-label mandatory-label" [ngClass]="{'text-danger': projectRoleForm.invalid === true && submitted === true}">{{'MANDATORYCHECK' | translate}}</label>
+ <div *ngFor="let params of getControls(); let i = index;" [formGroupName]="i">
+ <div class="form-group row">
+ <label class="col-sm-2 col-form-label" for="project_{{i}}">{{'PROJECT' | translate}}*</label>
+ <div class="col-sm-3">
+ <ng-select placeholder="{{'SELECT' | translate}}" [items]="projects" bindLabel="name"
+ bindValue="name" formControlName="project_name" id="project_{{i}}"
+ [ngClass]="{ 'is-invalid': submitted && params.controls.project_name.errors }"></ng-select>
+ </div>
+ <label class="col-sm-2 col-form-label" for="roles_{{i}}">{{'ROLES' | translate}}*</label>
+ <div class="col-sm-4">
+ <ng-select placeholder="{{'SELECT' | translate}}" [items]="roles" bindLabel="name" bindValue="name"
+ formControlName="role_name" id="roles_{{i}}"
+ [ngClass]="{ 'is-invalid': submitted && params.controls.role_name.errors }"></ng-select>
+ </div>
+ <div class="col-sm-1">
+ <button type="button" class="btn btn-sm btn-danger remove-mapping" (click)="removeMapping(i)">
+ <i class="fas fa-times-circle"></i>
+ </button>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-danger" (click)="activeModal.close()">{{'CANCEL' | translate}}</button>
+ <button type="submit" class="btn btn-primary">{{'APPLY' | translate}}</button>
+ </div>
+</form>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file Project Role Component.
+ */
+import { HttpHeaders } from '@angular/common/http';
+import { Component, Injector, Input, OnInit } from '@angular/core';
+import { AbstractControl, FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms';
+import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateService } from '@ngx-translate/core';
+import { NotifierService } from 'angular-notifier';
+import { APIURLHEADER, ERRORDATA, MODALCLOSERESPONSEDATA } from 'CommonModel';
+import { environment } from 'environment';
+import { ProjectData } from 'ProjectModel';
+import { ProjectService } from 'ProjectService';
+import { RestService } from 'RestService';
+import { RoleData } from 'RolesModel';
+import { ProjectRoleMappings, UserDetail, UserRoleMap } from 'UserModel';
+
+/**
+ * Creating component
+ * @Component takes ProjectRole.html as template url
+ */
+@Component({
+ templateUrl: './ProjectRoleComponent.html',
+ styleUrls: ['./ProjectRoleComponent.scss']
+})
+/** Exporting a class @exports ProjectRoleComponent */
+export class ProjectRoleComponent implements OnInit {
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** Instance for active modal service @public */
+ public activeModal: NgbActiveModal;
+
+ /** FormGroup user Edit Account added to the form @ html @public */
+ public projectRoleForm: FormGroup;
+
+ /** Form submission Add */
+ public submitted: boolean = false;
+
+ /** Input contains Modal dialog component Instance @private */
+ @Input() public userTitle: string;
+
+ /** Input contains Modal dialog component Instance @private */
+ @Input() public userID: string;
+
+ /** Contains user details information @public */
+ public userDetails: UserDetail;
+
+ /** Project Role Mapping @public */
+ public projectRoleMap: UserRoleMap = {};
+
+ /** Check the loading results @public */
+ public isLoadingResults: boolean = false;
+
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+
+ /** Contains project information @public */
+ public projects: ProjectData[] = [];
+
+ /** Contains roles information @public */
+ public roles: RoleData[] = [];
+
+ /** Instance of the rest service @private */
+ private restService: RestService;
+
+ /** FormBuilder instance added to the formBuilder @private */
+ private formBuilder: FormBuilder;
+
+ /** Controls the header form @private */
+ private headers: HttpHeaders;
+
+ /** Notifier service to popup notification @private */
+ private notifierService: NotifierService;
+
+ /** Contains tranlsate instance @private */
+ private translateService: TranslateService;
+
+ /** Project Role Form array @private */
+ private projectRoleFormArray: FormArray;
+
+ /** Holds all project details @private */
+ private projectService: ProjectService;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.formBuilder = this.injector.get(FormBuilder);
+ this.restService = this.injector.get(RestService);
+ this.activeModal = this.injector.get(NgbActiveModal);
+ this.notifierService = this.injector.get(NotifierService);
+ this.translateService = this.injector.get(TranslateService);
+ this.projectService = this.injector.get(ProjectService);
+ this.initializeForm();
+ }
+
+ /** Generate primitive params @public */
+ get projectRoleParamsBuilder(): FormGroup {
+ return this.formBuilder.group({
+ project_name: [null, [Validators.required]],
+ role_name: [null, [Validators.required]]
+ });
+ }
+
+ /** Lifecyle Hooks the trigger before component is instantiate @public */
+ public ngOnInit(): void {
+ this.headers = new HttpHeaders({
+ 'Content-Type': 'application/json',
+ Accept: 'application/json',
+ 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
+ });
+ this.getProjects();
+ this.generateData();
+ }
+
+ /** convenience getter for easy access to form fields */
+ get f(): FormGroup['controls'] { return this.projectRoleForm.controls; }
+
+ /** Initializing Form Action @public */
+ public initializeForm(): void {
+ this.projectRoleForm = this.formBuilder.group({
+ project_role_mappings: this.formBuilder.array([])
+ });
+ }
+
+ /** Handle FormArray Controls @public */
+ public getControls(): AbstractControl[] {
+ // tslint:disable-next-line:no-backbone-get-set-outside-model
+ return (this.projectRoleForm.get('project_role_mappings') as FormArray).controls;
+ }
+
+ /** Fetching the data from server to Load in the smarttable @public */
+ public generateData(): void {
+ if (this.userID !== '') {
+ this.isLoadingResults = true;
+ this.restService.getResource(environment.USERS_URL + '/' + this.userID).subscribe((userDetails: UserDetail) => {
+ this.userDetails = userDetails;
+ this.loadMapping();
+ this.isLoadingResults = false;
+ }, (error: ERRORDATA) => {
+ this.isLoadingResults = false;
+ this.restService.handleError(error, 'get');
+ });
+ }
+ }
+ /** Fetching the projects information @public */
+ public getProjects(): void {
+ this.isLoadingResults = true;
+ this.restService.getResource(environment.PROJECTS_URL).subscribe((projectsData: ProjectData[]) => {
+ this.projects = projectsData;
+ this.getRoles();
+ }, (error: ERRORDATA) => {
+ this.isLoadingResults = false;
+ this.restService.handleError(error, 'get');
+ });
+ }
+
+ /** Fetching the Roles information @public */
+ public getRoles(): void {
+ this.restService.getResource(environment.ROLES_URL).subscribe((rolesData: RoleData[]) => {
+ this.roles = rolesData;
+ this.isLoadingResults = false;
+ }, (error: ERRORDATA) => {
+ this.isLoadingResults = false;
+ this.restService.handleError(error, 'get');
+ });
+ }
+
+ /** Set all roles and project values to the form @public */
+ public loadMapping(): void {
+ this.userDetails.project_role_mappings.forEach((data: ProjectRoleMappings) => {
+ // tslint:disable-next-line:no-backbone-get-set-outside-model
+ this.projectRoleFormArray = this.projectRoleForm.get('project_role_mappings') as FormArray;
+ this.projectRoleFormArray.push(this.projectRoleParamsBuilder);
+ });
+ this.projectRoleForm.patchValue(this.userDetails);
+ }
+
+ /** Remove project and roles from the list @public */
+ public removeMapping(index: number): void {
+ this.projectRoleFormArray.removeAt(index);
+ }
+
+ /** Submit project and roles @public */
+ public addProjectRole(): void {
+ this.submitted = true;
+ const modalData: MODALCLOSERESPONSEDATA = {
+ message: 'Done'
+ };
+ if (this.projectRoleForm.invalid) { return; }
+ const apiURLHeader: APIURLHEADER = {
+ url: environment.USERS_URL + '/' + this.userID
+ };
+ this.projectRoleMap.project_role_mappings = [];
+ this.projectRoleForm.value.project_role_mappings.forEach((res: ProjectRoleMappings) => {
+ this.projectRoleMap.project_role_mappings.push({ project: res.project_name, role: res.role_name });
+ });
+ if (this.projectRoleMap.project_role_mappings.length !== 0) {
+ this.isLoadingResults = true;
+ this.restService.patchResource(apiURLHeader, this.projectRoleMap).subscribe((result: {}) => {
+ this.isLoadingResults = false;
+ this.activeModal.close(modalData);
+ this.projectService.setHeaderProjects();
+ this.notifierService.notify('success', this.translateService.instant('PAGE.USERS.EDITEDSUCCESSFULLY'));
+ }, (error: ERRORDATA) => {
+ this.isLoadingResults = false;
+ this.restService.handleError(error, 'patch');
+ });
+ } else {
+ this.notifierService.notify('error', this.translateService.instant('PAGE.USERS.EDITPROJECTROLEERROR'));
+ }
+ }
+
+ /** Add extra mapping and set empty project and roles @public */
+ public addMapping(): void {
+ // tslint:disable-next-line:no-backbone-get-set-outside-model
+ this.projectRoleFormArray = this.projectRoleForm.get('project_role_mappings') as FormArray;
+ this.projectRoleFormArray.push(this.projectRoleParamsBuilder);
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="row d-flex flex-row justify-content-between">
+ <div class="d-flex align-items-center header-style">{{'PAGE.DASHBOARD.USERS' | translate}}</div>
+ <span class="button">
+ <button class="btn btn-primary" type="button" (click)="composeUser()" placement="top" container="body"
+ ngbTooltip="{{'PAGE.USERS.CREATEUSER' | translate}}">
+ <i class="fas fa-plus-circle" aria-hidden="true"></i>
+ {{'PAGE.USERS.CREATEUSER' | translate}}
+ </button>
+ </span>
+</div>
+<div class="row mt-2 mb-0 form-group justify-content-end list-utilites-actions">
+ <page-per-row class="mr-2" (pagePerRow)="onChange($event)"></page-per-row>
+ <page-reload></page-reload>
+</div>
+<div class="smarttable-style bg-white mt-1">
+ <ng2-smart-table [ngClass]="checkDataClass" [settings]="settings" [source]="dataSource" (userRowSelect)="onUserRowSelect($event)">
+ </ng2-smart-table>
+</div>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file users details Component.
+ */
+import { Component, Injector, OnDestroy, OnInit } from '@angular/core';
+import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateService } from '@ngx-translate/core';
+import { AddEditUserComponent } from 'AddEditUserComponent';
+import { ERRORDATA, MODALCLOSERESPONSEDATA } from 'CommonModel';
+import { DataService } from 'DataService';
+import { environment } from 'environment';
+import { LocalDataSource } from 'ng2-smart-table';
+import { ProjectService } from 'ProjectService';
+import { RestService } from 'RestService';
+import { Subscription } from 'rxjs';
+import { SharedService } from 'SharedService';
+import { UserData, UserDetail } from 'UserModel';
+import { UsersActionComponent } from 'UsersActionComponent';
+
+/**
+ * Creating component
+ * @Component takes UserDetailsComponent.html as template url
+ */
+@Component({
+ templateUrl: './UserDetailsComponent.html',
+ styleUrls: ['./UserDetailsComponent.scss']
+})
+/** Exporting a class @exports UserDetailsComponent */
+export class UserDetailsComponent implements OnInit, OnDestroy {
+ /** Data of smarttable populate through LocalDataSource @public */
+ public dataSource: LocalDataSource = new LocalDataSource();
+
+ /** handle translate @public */
+ public translateService: TranslateService;
+
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** Settings for smarttable to populate the table with columns @public */
+ public settings: object = {};
+
+ /** Check the loading results @public */
+ public isLoadingResults: boolean = true;
+
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+
+ /** Class for empty and present data @public */
+ public checkDataClass: string;
+
+ /** Instance of the rest service @private */
+ private restService: RestService;
+
+ /** dataService to pass the data from one component to another @private */
+ private dataService: DataService;
+
+ /** Instance of the modal service @private */
+ private modalService: NgbModal;
+
+ /** Formation of appropriate Data for LocalDatasource @private */
+ private userData: {}[] = [];
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ /** Holds all project details */
+ private projectService: ProjectService;
+
+ /** holds the project information @private */
+ private projectList: {}[] = [];
+
+ /** Columns list of the smart table @public */
+ private columnLists: object = {};
+
+ /** Instance of subscriptions @private */
+ private generateDataSub: Subscription;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.restService = this.injector.get(RestService);
+ this.dataService = this.injector.get(DataService);
+ this.sharedService = this.injector.get(SharedService);
+ this.modalService = this.injector.get(NgbModal);
+ this.projectService = this.injector.get(ProjectService);
+ this.translateService = this.injector.get(TranslateService);
+ }
+
+ /**
+ * Lifecyle Hooks the trigger before component is instantiate
+ */
+ public ngOnInit(): void {
+ this.projectService.getAllProjects().subscribe((projects: {}[]) => {
+ this.projectList = projects;
+ });
+ this.generateColumns();
+ this.generateSettings();
+ this.generateData();
+ this.generateDataSub = this.sharedService.dataEvent.subscribe(() => { this.generateData(); });
+ }
+
+ /** smart table Header Colums @public */
+ public generateColumns(): void {
+ this.columnLists = {
+ username: { title: this.translateService.instant('NAME'), width: '20%', sortDirection: 'asc' },
+ projects: { title: this.translateService.instant('PAGE.DASHBOARD.PROJECTS'), width: '25%' },
+ identifier: { title: this.translateService.instant('IDENTIFIER'), width: '20%' },
+ modified: { title: this.translateService.instant('MODIFIED'), width: '15%' },
+ created: { title: this.translateService.instant('CREATED'), width: '15%' },
+ Actions: {
+ name: 'Action', width: '5%', filter: false, sort: false, title: this.translateService.instant('ACTIONS'), type: 'custom',
+ valuePrepareFunction: (cell: UserData, row: UserData): UserData => row,
+ renderComponent: UsersActionComponent
+ }
+ };
+ }
+
+ /** smart table Data Settings @public */
+ public generateSettings(): void {
+ this.settings = {
+ edit: { editButtonContent: '<i class="fa fa-edit" title="Edit"></i>', confirmSave: true },
+ delete: { deleteButtonContent: '<i class="far fa-trash-alt" title="delete"></i>', confirmDelete: true },
+ columns: this.columnLists,
+ actions: { add: false, edit: false, delete: false, position: 'right' },
+ attr: this.sharedService.tableClassConfig(),
+ pager: this.sharedService.paginationPagerConfig(),
+ noDataMessage: this.translateService.instant('NODATAMSG')
+ };
+ }
+
+ /** on Navigate to Composer Page @public */
+ public composeUser(): void {
+ const modalRef: NgbModalRef = this.modalService.open(AddEditUserComponent, { backdrop: 'static' });
+ modalRef.componentInstance.userTitle = this.translateService.instant('PAGE.USERS.NEWUSER');
+ modalRef.componentInstance.userType = 'add';
+ modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
+ if (result) {
+ this.sharedService.callData();
+ }
+ }).catch();
+ }
+
+ /** smart table listing manipulation @private */
+ public onChange(perPageValue: number): void {
+ this.dataSource.setPaging(1, perPageValue, true);
+ }
+
+ /** OnUserRowSelect function @private */
+ public onUserRowSelect(event: MessageEvent): void {
+ Object.assign(event.data, { page: 'users' });
+ this.dataService.changeMessage(event.data);
+ }
+
+ /** Set up user details @public */
+ public setUserDetails(userData: UserDetail): void {
+ const userDataObj: UserData = {
+ username: userData.username,
+ modified: this.sharedService.convertEpochTime(userData._admin.modified),
+ created: this.sharedService.convertEpochTime(userData._admin.created),
+ projects: userData.projectListName,
+ identifier: userData._id
+ };
+ this.userData.push(userDataObj);
+ }
+
+ /**
+ * Lifecyle hook which get trigger on component destruction
+ */
+ public ngOnDestroy(): void {
+ this.generateDataSub.unsubscribe();
+ }
+
+ /** Fetching the data from server to Load in the smarttable @protected */
+ protected generateData(): void {
+ this.isLoadingResults = true;
+ this.restService.getResource(environment.USERS_URL).subscribe((usersData: UserDetail[]) => {
+ this.userData = [];
+ usersData.forEach((userData: UserDetail) => {
+ if (userData.projects.length > 0) {
+ userData.projectListName = userData.projects.join(', ');
+ } else {
+ userData.projectListName = '';
+ }
+ this.setUserDetails(userData);
+ });
+ if (this.userData.length > 0) {
+ this.checkDataClass = 'dataTables_present';
+ } else {
+ this.checkDataClass = 'dataTables_empty';
+ }
+ this.dataSource.load(this.userData).then((data: {}) => {
+ this.isLoadingResults = false;
+ }).catch();
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'get');
+ this.isLoadingResults = false;
+ });
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="modal-header">
+ <h4 class="modal-title" id="modal-clone-title">
+ {{'CLONE' | translate}}
+ </h4>
+ <button class="button-xs" type="button" class="close" aria-label="Close" (click)="activeModal.close()">
+ <i class="fas fa-times-circle text-danger"></i>
+ </button>
+</div>
+<div class="modal-body">
+ <span>{{'CLONECONFIRMPOPUPMESSAGE' | translate}} <b>{{ params.name }}</b> ?</span>
+</div>
+<div class="modal-footer">
+ <button (click)="activeModal.close()" class="btn btn-danger">{{'CANCEL' | translate}}</button>
+ <button (click)="clonePackageInfo();" class="btn btn-primary">{{'OK' | translate }}</button>
+</div>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @file Clone Package Model
+ */
+import { HttpHeaders } from '@angular/common/http';
+import { Component, Injector, Input, OnInit } from '@angular/core';
+import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateService } from '@ngx-translate/core';
+import { NotifierService } from 'angular-notifier';
+import { APIURLHEADER, ERRORDATA, GETAPIURLHEADER, MODALCLOSERESPONSEDATA, URLPARAMS } from 'CommonModel';
+import { environment } from 'environment';
+import * as jsyaml from 'js-yaml';
+import { NSDDetails } from 'NSDModel';
+import { RestService } from 'RestService';
+import { SharedService } from 'SharedService';
+
+/**
+ * Creating component
+ * @Component takes ClonePackageComponent.html as template url
+ */
+
+@Component({
+ selector: 'app-clone-package',
+ templateUrl: './ClonePackageComponent.html',
+ styleUrls: ['./ClonePackageComponent.scss']
+})
+/** Exporting a class @exports ClonePackageComponent */
+export class ClonePackageComponent implements OnInit {
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** Instance for active modal service @public */
+ public activeModal: NgbActiveModal;
+
+ /** Input contains component objects @public */
+ @Input() public params: URLPARAMS;
+
+ /** To handle loader status for API call @public */
+ public isLoadingResults: boolean = false;
+
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ /** Instance of the rest service @private */
+ private restService: RestService;
+
+ /** Notifier service to popup notification @private */
+ private notifierService: NotifierService;
+
+ /** Contains tranlsate instance @private */
+ private translateService: TranslateService;
+
+ /** Contains cloned package name instance @private */
+ private packageName: string = '';
+
+ /** Contains API end point for package creation @private */
+ private endPoint: string;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.restService = this.injector.get(RestService);
+ this.sharedService = this.injector.get(SharedService);
+ this.activeModal = this.injector.get(NgbActiveModal);
+ this.notifierService = this.injector.get(NotifierService);
+ this.translateService = this.injector.get(TranslateService);
+ }
+ /**
+ * Lifecyle Hooks the trigger before component is instantiate
+ */
+ public ngOnInit(): void {
+ // Empty Block
+ }
+ /**
+ * Get package information based on type
+ */
+ public clonePackageInfo(): void {
+ let apiUrl: string = '';
+ const httpOptions: GETAPIURLHEADER = this.getHttpoptions();
+ apiUrl = this.params.page === 'nsd' ? apiUrl = environment.NSDESCRIPTORS_URL + '/' + this.params.id + '/nsd' :
+ apiUrl = environment.VNFPACKAGES_URL + '/' + this.params.id + '/vnfd';
+ this.isLoadingResults = true;
+ this.restService.getResource(apiUrl, httpOptions)
+ .subscribe((nsData: NSDDetails[]) => {
+ this.modifyContent(nsData);
+ }, (error: ERRORDATA) => {
+ this.isLoadingResults = false;
+ error.error = typeof error.error === 'string' ? jsyaml.load(error.error) : error.error;
+ this.restService.handleError(error, 'get');
+ });
+ }
+ /**
+ * Get HTTP header options
+ */
+ private getHttpoptions(): GETAPIURLHEADER {
+ const apiHeaders: HttpHeaders = new HttpHeaders({
+ 'Content-Type': 'application/json',
+ Accept: 'text/plain',
+ 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
+ });
+ return {
+ headers: apiHeaders,
+ responseType: 'text'
+ };
+ }
+ /**
+ * Get and modify package information based on type
+ */
+ private modifyContent(packageInfo: NSDDetails[]): void {
+ const packageContent: string = jsyaml.load(packageInfo.toString());
+ if (this.params.page === 'nsd') {
+ this.packageName = 'clone_' + packageContent['nsd:nsd-catalog'].nsd[0].name;
+ this.endPoint = environment.NSDESCRIPTORSCONTENT_URL;
+ packageContent['nsd:nsd-catalog'].nsd.forEach((nsd: NSDDetails) => {
+ nsd.id = 'clone_' + nsd.id;
+ nsd.name = 'clone_' + nsd.name;
+ nsd['short-name'] = 'clone_' + nsd['short-name'];
+ });
+ } else {
+ this.packageName = 'clone_' + packageContent['vnfd:vnfd-catalog'].vnfd[0].name;
+ this.endPoint = environment.VNFPACKAGESCONTENT_URL;
+ packageContent['vnfd:vnfd-catalog'].vnfd.forEach((vnfd: NSDDetails) => {
+ vnfd.id = 'clone_' + vnfd.id;
+ vnfd.name = 'clone_' + vnfd.name;
+ vnfd['short-name'] = 'clone_' + vnfd['short-name'];
+ });
+ }
+ this.clonePackage(packageContent);
+ }
+ /**
+ * Create clone package and upload as TAR.GZ file
+ */
+ private clonePackage(packageContent: string): void {
+ const descriptorInfo: string = jsyaml.dump(packageContent);
+ const apiHeader: HttpHeaders = new HttpHeaders({
+ 'Content-Type': 'application/gzip',
+ Accept: 'application/json',
+ 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
+ });
+ const modalData: MODALCLOSERESPONSEDATA = {
+ message: 'Done'
+ };
+ this.sharedService.targzFile({ packageType: this.params.page, id: this.params.id, descriptor: descriptorInfo })
+ .then((content: ArrayBuffer): void => {
+ const apiURLHeader: APIURLHEADER = {
+ url: this.endPoint,
+ httpOptions: { headers: apiHeader }
+ };
+ this.restService.postResource(apiURLHeader, content).subscribe((result: { id: string }) => {
+ this.activeModal.close(modalData);
+ this.isLoadingResults = false;
+ this.notifierService.notify('success', this.translateService.instant('CLONESUCCESSFULLY'));
+ }, (error: ERRORDATA) => {
+ this.isLoadingResults = false;
+ this.restService.handleError(error, 'post');
+ });
+ }).catch((): void => {
+ this.isLoadingResults = false;
+ this.notifierService.notify('error', this.translateService.instant('ERROR'));
+ });
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<form [formGroup]="packagesForm" (ngSubmit)="createPackages()" autocomplete="off">
+ <div class="modal-header">
+ <h4 class="modal-title" id="modal-basic-title">{{'CREATEPACKAGE' | translate}}</h4>
+ <button class="button-xs" type="button" class="close" (click)="activeModal.close()">
+ <i class="fas fa-times-circle text-danger"></i>
+ </button>
+ </div>
+ <div class="modal-body">
+ <div class="form-group row">
+ <label class="col-sm-12 col-form-label mandatory-label" [ngClass]="{'text-danger': packagesForm.invalid === true && submitted === true}">{{'MANDATORYCHECK' | translate}}</label>
+ <label class="col-sm-6 col-form-label">{{'PACKAGE' | translate}} {{'NAME' | translate}}*</label>
+ <div class="col-sm-6">
+ <input type="text" class="form-control" placeholder="{{'PACKAGE' | translate}} {{'NAME' | translate}}"
+ formControlName="name" id="name" [ngClass]="{ 'is-invalid': submitted && f.name.errors }" required>
+ </div>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-danger" (click)="activeModal.close()">{{'CANCEL' | translate}}</button>
+ <button type="submit" class="btn btn-primary">{{'CREATE' | translate}}</button>
+ </div>
+</form>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @file Info Compose Package Model
+ */
+import { HttpClient, HttpHeaders } from '@angular/common/http';
+import { Component, Injector, Input, OnInit } from '@angular/core';
+import { FormBuilder, FormGroup, Validators } from '@angular/forms';
+import { Router } from '@angular/router';
+import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateService } from '@ngx-translate/core';
+import { NotifierService } from 'angular-notifier';
+import { APIURLHEADER, ERRORDATA, URLPARAMS } from 'CommonModel';
+import { DataService } from 'DataService';
+import { environment } from 'environment';
+import * as jsyaml from 'js-yaml';
+import * as pako from 'pako';
+import { RestService } from 'RestService';
+import { SharedService } from 'SharedService';
+
+/** This is added globally by the tar.js library */
+// tslint:disable-next-line: no-any
+declare const Tar: any;
+
+/**
+ * Creating component
+ * @Component takes ComposePackages.html as template url
+ */
+@Component({
+ templateUrl: './ComposePackages.html',
+ styleUrls: ['./ComposePackages.scss']
+})
+/** Exporting a class @exports ComposePackages */
+export class ComposePackages implements OnInit {
+ /** Invoke service injectors @public */
+ public injector: Injector;
+
+ /** dataService to pass the data from one component to another @public */
+ public dataService: DataService;
+
+ /** Varaibles to hold http client @public */
+ public httpClient: HttpClient;
+
+ /** Instance for active modal service @public */
+ public activeModal: NgbActiveModal;
+
+ /** FormGroup instance added to the form @ html @public */
+ public packagesForm: FormGroup;
+
+ /** Form submission Add */
+ public submitted: boolean = false;
+
+ /** To handle loader status for API call @public */
+ public isLoadingResults: boolean = false;
+
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+
+ /** FormBuilder instance added to the formBuilder @private */
+ private formBuilder: FormBuilder;
+
+ /** Instance of the rest service @private */
+ private restService: RestService;
+
+ /** Notifier service to popup notification @private */
+ private notifierService: NotifierService;
+
+ /** Controls the header form @private */
+ private headers: HttpHeaders;
+
+ /** Create URL holds the end point of any packages @private */
+ private createURL: string;
+
+ /** Input contains component objects @private */
+ @Input() private params: URLPARAMS;
+
+ /** Holds the end point @private */
+ private endPoint: string;
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ /** Holds teh instance of AuthService class of type AuthService @private */
+ private router: Router;
+
+ /** Contains tranlsate instance @private */
+ private translateService: TranslateService;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.dataService = this.injector.get(DataService);
+ this.restService = this.injector.get(RestService);
+ this.activeModal = this.injector.get(NgbActiveModal);
+ this.notifierService = this.injector.get(NotifierService);
+ this.formBuilder = this.injector.get(FormBuilder);
+ this.router = this.injector.get(Router);
+ this.translateService = this.injector.get(TranslateService);
+ this.sharedService = this.injector.get(SharedService);
+ }
+
+ /**
+ * Lifecyle Hooks the trigger before component is instantiate
+ */
+ public ngOnInit(): void {
+ this.headers = new HttpHeaders({
+ 'Content-Type': 'application/gzip',
+ Accept: 'application/json',
+ 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
+ });
+ this.initializeForm();
+ }
+
+ /** initialize Forms @public */
+ public initializeForm(): void {
+ this.packagesForm = this.formBuilder.group({
+ name: ['', [Validators.required]]
+ });
+ }
+
+ /** convenience getter for easy access to form fields */
+ get f(): FormGroup['controls'] { return this.packagesForm.controls; }
+
+ /** Create packages @public */
+ public createPackages(): void {
+ this.submitted = true;
+ this.sharedService.cleanForm(this.packagesForm);
+ if (!this.packagesForm.invalid) {
+ this.isLoadingResults = true;
+ if (this.params.page === 'ns-package') {
+ this.endPoint = environment.NSDESCRIPTORSCONTENT_URL;
+ } else if (this.params.page === 'vnf-package') {
+ this.endPoint = environment.VNFPACKAGESCONTENT_URL;
+ }
+ const descriptor: string = this.packageYaml(this.params.page);
+ try {
+ // tslint:disable-next-line: no-any
+ const tar: any = new Tar();
+ const out: Uint8Array = tar.append(this.packagesForm.value.name + '/' + this.packagesForm.value.name + '.yaml',
+ descriptor, { type: '0' });
+ const gzipContent: Uint8Array = pako.gzip(out);
+ this.createPackageApi(gzipContent.buffer);
+ } catch (e) {
+ this.isLoadingResults = false;
+ this.notifierService.notify('error', this.translateService.instant('ERROR'));
+ }
+ }
+ }
+ /** Create packages @public */
+ private createPackageApi(packageContent: ArrayBuffer | SharedArrayBuffer): void {
+ const apiURLHeader: APIURLHEADER = {
+ url: this.endPoint,
+ httpOptions: { headers: this.headers }
+ };
+ this.restService.postResource(apiURLHeader, packageContent).subscribe((result: { id: string }) => {
+ this.isLoadingResults = false;
+ this.activeModal.close();
+ this.composeNSPackages(result.id);
+ }, (error: ERRORDATA) => {
+ this.isLoadingResults = false;
+ this.restService.handleError(error, 'post');
+ });
+ }
+ /** Compose NS Packages @private */
+ private composeNSPackages(id: string): void {
+ let packageUrl: string;
+ if (this.params.page === 'ns-package') {
+ packageUrl = '/packages/ns/compose/';
+ this.notifierService.notify('success', this.packagesForm.value.name + ' ' +
+ this.translateService.instant('PAGE.NSPACKAGE.CREATEDSUCCESSFULLY'));
+ } else if (this.params.page === 'vnf-package') {
+ packageUrl = '/packages/vnf/compose/';
+ this.notifierService.notify('success', this.packagesForm.value.name + ' ' +
+ this.translateService.instant('PAGE.VNFPACKAGE.CREATEDSUCCESSFULLY'));
+ }
+ this.router.navigate([packageUrl, id]).catch(() => {
+ // Catch Navigation Error
+ });
+ }
+ /** Deafult template for NS and VNF Packages @private */
+ private packageYaml(descriptorType: string): string {
+ let packageYaml: {} = {};
+ if (descriptorType === 'ns-package') {
+ packageYaml = {
+ 'nsd:nsd-catalog': {
+ nsd: [
+ {
+ 'short-name': this.packagesForm.value.name,
+ vendor: 'OSM Composer',
+ description: this.packagesForm.value.name + ' descriptor',
+ vld: [],
+ 'constituent-vnfd': [],
+ version: '1.0',
+ id: this.packagesForm.value.name,
+ name: this.packagesForm.value.name
+ }
+ ]
+ }
+ };
+ } else {
+ packageYaml = {
+ 'vnfd:vnfd-catalog': {
+ vnfd: [
+ {
+ 'short-name': this.packagesForm.value.name,
+ vdu: [],
+ description: '',
+ 'mgmt-interface': {
+ cp: ''
+ },
+ id: this.packagesForm.value.name,
+ version: '1.0',
+ 'internal-vld': [],
+ 'connection-point': [],
+ name: this.packagesForm.value.name
+ }
+ ]
+ }
+ };
+ }
+ return jsyaml.dump(packageYaml);
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div *ngIf="topologyType === 'Add'">
+ <form [formGroup]="addConfirmationForm" (ngSubmit)="addConfirmation()" autocomplete="off">
+ <div class="modal-header">
+ <h4 class="modal-title" id="modal-basic-title">
+ {{'CREATE' | translate}}
+ {{ topologytitle | translate}}
+ </h4>
+ <button class="button-xs" type="button" class="close" aria-label="Close" (click)="activeModal.close()">
+ <i class="fas fa-times-circle text-danger"></i>
+ </button>
+ </div>
+ <div class="modal-body">
+ <div *ngIf="topologyType === 'Add'">
+ <p [innerHTML]="topologyname"></p>
+ <ng-select placeholder="{{'SELECT' | translate}}" formControlName="cpName" [items]="cpDetails" bindLabel="name"
+ bindValue="name" [(ngModel)]="connectionPointInput"
+ [ngClass]="{ 'is-invalid': submitted && f.cpName.errors }"></ng-select>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-danger" (click)="activeModal.close()">{{'CANCEL' | translate}}</button>
+ <button type="submit" class="btn btn-primary">{{'OK' | translate }}</button>
+ </div>
+ </form>
+</div>
+<div *ngIf="topologyType !== 'Add'">
+ <div class="modal-header">
+ <h4 class="modal-title" id="modal-basic-title">
+ {{(topologyType === 'Delete' ? 'DELETE' : (topologyType === 'Add' ? 'CREATE' : '')) | translate}}
+ {{ topologytitle | translate}}
+ </h4>
+ <button class="button-xs" type="button" class="close" aria-label="Close" (click)="activeModal.close()">
+ <i class="fas fa-times-circle text-danger"></i>
+ </button>
+ </div>
+ <div class="modal-body">
+ <span *ngIf="topologyType === 'Delete'">{{'DELETECONFIRMPOPUPMESSAGE' | translate}} {{ topologyname }} ?</span>
+ <ul *ngIf="topologyType === 'Info'">
+ <li>
+ <p><b>{{'PAGE.TOPOLOGY.HELPINFO.CREATEEDGE' | translate}}</b>:
+ {{'PAGE.TOPOLOGY.HELPINFO.CREATEEDGEFIRSTSETENCE' | translate}} <span class="help-key">Shift</span> + <span
+ class="help-key">Drag</span> {{'PAGE.TOPOLOGY.HELPINFO.CREATEEDGESECONDSETENCE' | translate}}</p>
+ </li>
+ <li>
+ <p><b>{{'PAGE.TOPOLOGY.HELPINFO.DELETEEDGEVERTEX' | translate}}</b>:
+ {{'PAGE.TOPOLOGY.HELPINFO.DELETEEDGEVERTEXSENTENCE' | translate}}</p>
+ </li>
+ <li>
+ <p><b>{{'PAGE.TOPOLOGY.HELPINFO.SPREADEDGE' | translate}}</b>:
+ {{'PAGE.TOPOLOGY.HELPINFO.SPREADEDGESENTENCE' | translate}} <span class="help-key">ctrl</span> + <span
+ class="help-key">Drag</span></p>
+ </li>
+ <li>
+ <p><b>{{'PAGE.TOPOLOGY.HELPINFO.EDGEINFO' | translate}}</b>:
+ {{'PAGE.TOPOLOGY.HELPINFO.EDGEINFOSENTENCE' | translate}}</p>
+ </li>
+ </ul>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-danger" (click)="activeModal.close()">{{'CANCEL' | translate}}</button>
+ <button type="button" *ngIf="topologyType !== 'Info'" (click)="confirmation();"
+ class="btn btn-primary">{{'OK' | translate }}</button>
+ </div>
+</div>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+.help-key {
+ border: 1px solid #ddd;
+ padding: 4px;
+ border-radius: 3px;
+ background: #f6f6f6;
+ box-shadow: #999 1px 1px 1px;
+}
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file Delete Topology Model
+ */
+import { Component, Injector, Input, OnInit } from '@angular/core';
+import { FormBuilder, FormGroup, Validators } from '@angular/forms';
+import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateService } from '@ngx-translate/core';
+import { MODALCLOSERESPONSEWITHCP } from 'CommonModel';
+/**
+ * Creating component
+ * @Component takes ConfirmationTopologyComponent.html as template url
+ */
+@Component({
+ selector: 'app-confirmation-topology',
+ templateUrl: './ConfirmationTopologyComponent.html',
+ styleUrls: ['./ConfirmationTopologyComponent.scss']
+})
+/** Exporting a class @exports ConfirmationTopologyComponent */
+export class ConfirmationTopologyComponent implements OnInit {
+ /** Form valid on submit trigger @public */
+ public submitted: boolean = false;
+ /** To inject services @public */
+ public injector: Injector;
+ /** Instance for active modal service @public */
+ public activeModal: NgbActiveModal;
+ /** FormGroup instance added to the form @ html @public */
+ public addConfirmationForm: FormGroup;
+ /** Input contains Modal dialog componentInstance @private */
+ @Input() public topologytitle: string;
+ /** Input contains Modal dialog componentInstance @private */
+ @Input() public topologyname: string;
+ /** Input contains Modal dialog componentInstance @private */
+ @Input() public topologyType: string;
+ /** Input contains Modal dialog componentInstance @private */
+ @Input() public cpDetails: {}[];
+
+ /** Contains connectionpoint @public */
+ public connectionPointInput: string;
+
+ /** Contains tranlsate instance @private */
+ private translateService: TranslateService;
+ /** FormBuilder instance added to the formBuilder @private */
+ private formBuilder: FormBuilder;
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.activeModal = this.injector.get(NgbActiveModal);
+ this.translateService = this.injector.get(TranslateService);
+ this.formBuilder = this.injector.get(FormBuilder);
+ }
+
+ /**
+ * Lifecyle Hooks the trigger before component is instantiate
+ */
+ public ngOnInit(): void {
+ this.initializeForm();
+ }
+ /** convenience getter for easy access to form fields */
+ get f(): FormGroup['controls'] { return this.addConfirmationForm.controls; }
+
+ /** initialize Forms @public */
+ public initializeForm(): void {
+ this.addConfirmationForm = this.formBuilder.group({
+ cpName: [null, [Validators.required]]
+ });
+ }
+
+ /** add confirmation to be handled in this function @public */
+ public addConfirmation(): void {
+ this.submitted = true;
+ if (this.addConfirmationForm.invalid) { return; } // Proceed, onces form is valid
+ const modalData: MODALCLOSERESPONSEWITHCP = {
+ message: 'Done',
+ connection_point: this.connectionPointInput
+ };
+ this.activeModal.close(modalData);
+ }
+ /** confirmation to be handled in this function @public */
+ public confirmation(): void {
+ const modalData: MODALCLOSERESPONSEWITHCP = {
+ message: 'Done'
+ };
+ this.activeModal.close(modalData);
+ }
+
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="modal-header">
+ <h4 class="modal-title" id="modal-basic-title">
+ {{'DELETE' | translate}}
+ </h4>
+ <button class="button-xs" type="button" class="close" aria-label="Close" (click)="activeModal.close()">
+ <i class="fas fa-times-circle text-danger"></i>
+ </button>
+</div>
+<div class="modal-body">
+ <span>{{'DELETECONFIRMPOPUPMESSAGE' | translate}} <b>{{ this.title }}</b> ?</span>
+</div>
+<div class="modal-footer">
+ <button (click)="activeModal.close()" class="btn btn-danger">{{'CANCEL' | translate}}</button>
+ <button (click)="deleteData();" class="btn btn-primary">{{'OK' | translate }}</button>
+</div>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+.loadermessage-column {
+ min-height: 150px;
+}
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file Delete Model
+ */
+import { HttpHeaders } from '@angular/common/http';
+import { Component, Injector, Input } from '@angular/core';
+import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateService } from '@ngx-translate/core';
+import { NotifierService } from 'angular-notifier';
+import { DELETEPARAMS, ERRORDATA, MODALCLOSERESPONSEDATA, URLPARAMS } from 'CommonModel';
+import { DataService } from 'DataService';
+import { environment } from 'environment';
+import { RestService } from 'RestService';
+
+/**
+ * Creating component
+ * @Component takes DeleteComponent.html as template url
+ */
+@Component({
+ selector: 'app-delete',
+ templateUrl: './DeleteComponent.html',
+ styleUrls: ['./DeleteComponent.scss']
+})
+/** Exporting a class @exports DeleteComponent */
+export class DeleteComponent {
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** Instance for active modal service @public */
+ public activeModal: NgbActiveModal;
+
+ /** Instance of the modal service @public */
+ public title: string;
+
+ /** Show the Delete Ok button to trigger the terminate and delete */
+ public forceDelete: boolean = false;
+
+ /** Check the loading results @public */
+ public isLoadingResults: Boolean = false;
+
+ /** Give the message for the loading @public */
+ public notifyMessage: string = 'DELETELOADERMESSAGE';
+
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+
+ /** DataService to pass the data from one component to another @private */
+ private dataService: DataService;
+
+ /** Instance of the rest service @private */
+ private restService: RestService;
+
+ /** Instance of the modal service @private */
+ private id: string;
+
+ /** Variables holds url to be delete @private */
+ private deleteURL: string;
+
+ /** Controls the header form @private */
+ private headers: HttpHeaders;
+
+ /** Input contains component objects @private */
+ @Input() private params: URLPARAMS;
+
+ /** Notifier service to popup notification @private */
+ private notifierService: NotifierService;
+
+ /** Contains tranlsate instance @private */
+ private translateService: TranslateService;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.restService = this.injector.get(RestService);
+ this.dataService = this.injector.get(DataService);
+ this.activeModal = this.injector.get(NgbActiveModal);
+ this.notifierService = this.injector.get(NotifierService);
+ this.translateService = this.injector.get(TranslateService);
+ }
+
+ /**
+ * Lifecyle Hooks the trigger before component is instantiate
+ */
+ public ngOnInit(): void {
+ this.headers = new HttpHeaders({
+ 'Content-Type': 'application/json',
+ Accept: 'application/json',
+ 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
+ });
+ this.dataService.currentMessage.subscribe((data: DELETEPARAMS) => {
+ if (data.identifier !== undefined || data.identifier !== '' || data.identifier !== null) {
+ this.id = data.identifier;
+ }
+ this.createTitleandID(data);
+ this.createDeleteUrl(data);
+ });
+ }
+ /** Generate Title and Id from data @public */
+ public createTitleandID(data: DELETEPARAMS): void {
+ this.title = '';
+ if (data.name !== undefined) {
+ this.title = data.name;
+ } else if (data.shortName !== undefined) {
+ this.title = data.shortName;
+ } else if (data.projectName !== undefined) {
+ this.title = data.projectName;
+ this.id = this.title;
+ } else if (data.userName !== undefined) {
+ this.title = data.userName;
+ } else if (data.username !== undefined) {
+ this.title = data.username;
+ }
+ }
+ /** Generate Delete url from data @public */
+ public createDeleteUrl(data: DELETEPARAMS): void {
+ this.deleteURL = '';
+ if (data.page === 'ns-instance') {
+ this.deleteURL = environment.NSINSTANCESCONTENT_URL;
+ this.forceDelete = this.params.forceDeleteType;
+ } else if (data.page === 'ns-package') {
+ this.deleteURL = environment.NSDESCRIPTORSCONTENT_URL;
+ this.notifyMessage = 'DELETEDSUCCESSFULLY';
+ } else if (data.page === 'vnf-package') {
+ this.deleteURL = environment.VNFPACKAGESCONTENT_URL;
+ this.notifyMessage = 'DELETEDSUCCESSFULLY';
+ } else if (data.page === 'vim-account') {
+ this.deleteURL = environment.VIMACCOUNTS_URL;
+ this.notifyMessage = 'DELETEDSUCCESSFULLY';
+ } else if (data.page === 'wim-account') {
+ this.deleteURL = environment.WIMACCOUNTS_URL;
+ this.notifyMessage = 'DELETEDSUCCESSFULLY';
+ } else if (data.page === 'projects') {
+ this.deleteURL = environment.PROJECTS_URL;
+ this.notifyMessage = 'DELETEDSUCCESSFULLY';
+ this.id = data.id;
+ } else if (data.page === 'users') {
+ this.deleteURL = environment.USERS_URL;
+ this.notifyMessage = 'DELETEDSUCCESSFULLY';
+ } else if (data.page === 'network-slice') {
+ this.deleteURL = environment.NETWORKSLICETEMPLATECONTENT_URL;
+ this.notifyMessage = 'DELETEDSUCCESSFULLY';
+ } else if (data.page === 'net-slice-instance') {
+ this.deleteURL = environment.NETWORKSLICEINSTANCESCONTENT_URL;
+ this.forceDelete = this.params.forceDeleteType;
+ } else if (data.page === 'roles') {
+ this.deleteURL = environment.ROLES_URL;
+ this.notifyMessage = 'DELETEDSUCCESSFULLY';
+ } else if (data.page === 'pdu-instances') {
+ this.deleteURL = environment.PDUINSTANCE_URL;
+ } else if (data.page === 'sdn-controller') {
+ this.deleteURL = environment.SDNCONTROLLER_URL;
+ this.notifyMessage = 'DELETEDSUCCESSFULLY';
+ } else if (data.page === 'k8-cluster') {
+ this.deleteURL = environment.K8SCLUSTER_URL;
+ this.notifyMessage = 'DELETEDSUCCESSFULLY';
+ } else if (data.page === 'k8-repo') {
+ this.deleteURL = environment.K8REPOS_URL;
+ this.notifyMessage = 'DELETEDSUCCESSFULLY';
+ }
+ }
+ /** Generate Data function @public */
+ public deleteData(): void {
+ this.isLoadingResults = true;
+ const modalData: MODALCLOSERESPONSEDATA = {
+ message: 'Done'
+ };
+ let deletingURl: string = '';
+ if (this.forceDelete) {
+ deletingURl = this.deleteURL + '/' + this.id + '?FORCE=true';
+ this.notifyMessage = 'DELETEDSUCCESSFULLY';
+ } else {
+ deletingURl = this.deleteURL + '/' + this.id;
+ }
+ this.restService.deleteResource(deletingURl).subscribe((res: {}) => {
+ this.activeModal.close(modalData);
+ this.notifierService.notify('success', this.translateService.instant(this.notifyMessage, { title: this.title}));
+ }, (error: ERRORDATA) => {
+ this.isLoadingResults = false;
+ this.restService.handleError(error, 'delete');
+ }, () => {
+ this.isLoadingResults = false;
+ });
+ }
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file Drag and Drop feature.
+ */
+import { Directive, EventEmitter, HostBinding, HostListener, Output } from '@angular/core';
+import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
+
+/** Interface for FileHandle */
+export interface FileHandle {
+ file: File;
+ url: SafeUrl;
+}
+
+/**
+ * Creating Directive
+ * @Directive for handling the files.
+ */
+// tslint:disable-next-line:export-name
+@Directive({
+ selector: '[appDrag]'
+})
+/** Exporting a class @exports DragDirective */
+export class DragDirective {
+ /** To publish the details of files @public */
+ @Output() public files: EventEmitter<FileList> = new EventEmitter();
+
+ /** To set the background of drag and drop region @public */
+ @HostBinding('style.background') private background: string = '#e6f3fe';
+
+ /** To set the background of drag and drop region @public */
+ @HostBinding('style.color') private color: string = '#6a7a8c';
+
+ /** To trust the SecurityURL @public */
+ private sanitizer: DomSanitizer;
+
+ constructor(sanitizer: DomSanitizer) {
+ this.sanitizer = sanitizer;
+ }
+
+ /** To handle the Drag over Event @public */
+ @HostListener('dragover', ['$event']) public onDragOver(evt: DragEvent): void {
+ evt.preventDefault();
+ evt.stopPropagation();
+ this.background = '#087add';
+ this.color = '#fff';
+ }
+ /** To handle Drag leave Event @public */
+ @HostListener('dragleave', ['$event']) public onDragLeave(evt: DragEvent): void {
+ evt.preventDefault();
+ evt.stopPropagation();
+ this.background = '#e6f3fe';
+ this.color = '#6a7a8c';
+ }
+ /** To handle Drop Event @public */
+ @HostListener('drop', ['$event']) public onDrop(evt: DragEvent): void {
+ evt.preventDefault();
+ evt.stopPropagation();
+ this.background = '#e6f3fe';
+ this.color = '#6a7a8c';
+
+ const files: FileHandle[] = [];
+ Array.from(evt.dataTransfer.files).forEach((listFiles: File, index: number) => {
+ const file: File = listFiles;
+ const url: SafeUrl = this.sanitizer.bypassSecurityTrustUrl(window.URL.createObjectURL(file));
+ files.push({ file, url });
+ });
+ if (files.length > 0) {
+ this.files.emit(evt.dataTransfer.files);
+ }
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="form-group row">
+ <div class="d-flex align-items-center header-style">{{'EDIT' | translate}} <span
+ class="text-uppercase">{{pacakgeType}} </span>{{'DESCRIPTOR' | translate}}</div>
+</div>
+<form *ngIf="defaults[mode]">
+ <div class="row">
+ <div class="col-2">
+ <div class="form-group">
+ <select class="form-control custom-select" name="state" [(ngModel)]="mode" (ngModelChange)="changeMode()">
+ <option *ngFor="let types of fileTypes;" [value]="types.value">
+ {{types.viewValue}}</option>
+ </select>
+ </div>
+ </div>
+ <div class="col-4">
+ <div class="btn-group-toggle mb-1 mr-1 float-left">
+ <label class="btn btn-light" [class.active]="readOnly">
+ <input type="checkbox" [(ngModel)]="readOnly" name="readOnly" autocomplete="off">
+ {{'READONLYMODE' | translate}} ({{'CURRENTLY' | translate}} {{ (readOnly ? 'ON' : 'OFF') | translate }})
+ </label>
+ </div>
+ </div>
+ <div class="col-6 text-right">
+ <button type="button" class="btn btn-primary mr-2" routerLink="/packages/{{navigatePath}}/compose/{{paramsID}}"
+ [hidden]="navigatePath==='netslice'">
+ <i class="fa fa-sitemap" aria-hidden="true"></i> {{'SHOWGRAPH' | translate}}
+ </button>
+ <button type="button" class="btn btn-primary mr-2" (click)="update(true)" [hidden]="navigatePath==='netslice'">
+ <i class="fa fa-save" aria-hidden="true"></i> {{'UPDATESHOWGRAPH' | translate}}
+ </button>
+ <button type="button" class="btn btn-primary" (click)="update(false)">
+ <i class="fa fa-save" aria-hidden="true"></i> {{'UPDATE' | translate}}
+ </button>
+ </div>
+ </div>
+</form>
+<div class="ngx-codemirror" *ngIf="defaults[mode] else noData">
+ <ngx-codemirror [options]="options" [ngModel]="defaults[mode]" [disabled]="readOnly" [autoFocus]="true"
+ (ngModelChange)="handleChange($event)"></ngx-codemirror>
+</div>
+<ng-template #noData>
+ {{'NODATAERROR' | translate}}
+</ng-template>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+.ngx-codemirror {
+ font-size: 14px;
+}
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file Edit Actions Component
+ */
+import { HttpHeaders } from '@angular/common/http';
+import { Component, Injector, OnInit } from '@angular/core';
+import { ActivatedRoute, Router } from '@angular/router';
+import { TranslateService } from '@ngx-translate/core';
+import { NotifierService } from 'angular-notifier';
+import 'codemirror/addon/dialog/dialog';
+import 'codemirror/addon/display/autorefresh';
+import 'codemirror/addon/display/fullscreen';
+import 'codemirror/addon/edit/closebrackets';
+import 'codemirror/addon/edit/matchbrackets';
+import 'codemirror/addon/fold/brace-fold';
+import 'codemirror/addon/fold/foldcode';
+import 'codemirror/addon/fold/foldgutter';
+import 'codemirror/addon/search/search';
+import 'codemirror/addon/search/searchcursor';
+import 'codemirror/keymap/sublime';
+import 'codemirror/lib/codemirror';
+import 'codemirror/mode/javascript/javascript';
+import 'codemirror/mode/markdown/markdown';
+import 'codemirror/mode/yaml/yaml';
+import { APIURLHEADER, ERRORDATA, GETAPIURLHEADER } from 'CommonModel';
+import { environment } from 'environment';
+import * as HttpStatus from 'http-status-codes';
+import * as jsyaml from 'js-yaml';
+import { NSDDetails } from 'NSDModel';
+import { RestService } from 'RestService';
+import { SharedService } from 'SharedService';
+
+/**
+ * Creating component
+ * @Component takes EditPackagesComponent.html as template url
+ */
+@Component({
+ selector: 'app-edit-packages',
+ templateUrl: './EditPackagesComponent.html',
+ styleUrls: ['./EditPackagesComponent.scss']
+})
+
+/** Exporting a class @exports EditPackagesComponent */
+export class EditPackagesComponent implements OnInit {
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** dataService to pass the data from one component to another @public */
+ public identifier: {} = {};
+
+ /** readOnly @public */
+ public readOnly: boolean = false;
+
+ /** Handle the formate Change @public */
+ public defaults: {} = {
+ 'text/x-yaml': '',
+ 'text/json': ''
+ };
+
+ /** Get & Update URL VNFD & NSD */
+ public getUpdateURL: string;
+
+ /** Pass the type of VNFD & NSD for fetching text */
+ public getFileContentType: string;
+
+ /** Pass the type of VNFD & NSD for fileUpdate */
+ public updateFileContentType: string;
+
+ /** To Set Mode @public */
+ public mode: string = 'text/x-yaml';
+
+ /** To Set Mode @public */
+ public modeDefault: string = 'yaml';
+
+ /** options @public */
+ public options: {} = {
+ mode: this.modeDefault,
+ showCursorWhenSelecting: true,
+ autofocus: true,
+ autoRefresh: true,
+ lineNumbers: true,
+ lineWrapping: true,
+ foldGutter: true,
+ gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
+ autoCloseBrackets: true,
+ matchBrackets: true,
+ theme: 'neat',
+ keyMap: 'sublime'
+ };
+
+ /** Ymal Url for the VNFD & NSD */
+ public ymalUrl: string;
+
+ /** json Url for the VNFD & NSD */
+ public jsonUrl: string;
+
+ /** Navigation Path for the VNFD & NSD */
+ public navigatePath: string;
+
+ /** Package type */
+ public pacakgeType: string;
+
+ /** variables contains paramsID @public */
+ public paramsID: string;
+
+ /** Controls the File Type List form @public */
+ public fileTypes: { value: string; viewValue: string; }[] = [];
+
+ /** Check the loading results @public */
+ public isLoadingResults: boolean = true;
+
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+
+ /** Instance of the rest service @private */
+ private restService: RestService;
+
+ /** Holds teh instance of AuthService class of type AuthService @private */
+ private router: Router;
+
+ /** Holds teh instance of AuthService class of type AuthService @private */
+ private activatedRoute: ActivatedRoute;
+
+ /** Data @private */
+ private data: string = '';
+
+ /** contains http options @private */
+ private httpOptions: HttpHeaders;
+
+ /** Controls the header form @private */
+ private headers: HttpHeaders;
+
+ /** Notifier service to popup notification @private */
+ private notifierService: NotifierService;
+
+ /** Contains tranlsate instance @private */
+ private translateService: TranslateService;
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.restService = this.injector.get(RestService);
+ this.activatedRoute = this.injector.get(ActivatedRoute);
+ this.router = this.injector.get(Router);
+ this.notifierService = this.injector.get(NotifierService);
+ this.translateService = this.injector.get(TranslateService);
+ this.sharedService = this.injector.get(SharedService);
+ }
+
+ /** Lifecyle Hooks the trigger before component is instantiate @public */
+ public ngOnInit(): void {
+ this.headers = new HttpHeaders({
+ 'Content-Type': 'application/json',
+ Accept: 'text/plain',
+ 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
+ });
+ // tslint:disable-next-line: no-backbone-get-set-outside-model
+ this.paramsID = this.activatedRoute.snapshot.paramMap.get('id');
+ // tslint:disable-next-line: no-backbone-get-set-outside-model
+ this.pacakgeType = this.activatedRoute.snapshot.paramMap.get('type');
+ this.generateURLPath();
+ }
+
+ /** generate ymalURL, JSONURL, navigation Path */
+ public generateURLPath(): void {
+ if (this.pacakgeType === 'vnf') {
+ this.getUpdateURL = environment.VNFPACKAGES_URL;
+ this.getFileContentType = 'vnfd';
+ this.updateFileContentType = 'package_content';
+ this.navigatePath = 'vnf';
+ this.fileTypes = [{ value: 'text/x-yaml', viewValue: 'yaml' }, { value: 'text/json', viewValue: 'json' }];
+ this.httpOptions = this.getHeadersWithContentAccept('application/zip', 'application/json');
+ this.getEditFileData();
+ } else if (this.pacakgeType === 'netslice') {
+ this.getUpdateURL = environment.NETWORKSLICETEMPLATE_URL;
+ this.getFileContentType = 'nst';
+ this.updateFileContentType = 'nst_content';
+ this.navigatePath = 'netslice';
+ this.fileTypes = [{ value: 'text/x-yaml', viewValue: 'yaml' }];
+ this.httpOptions = this.getHeadersWithContentAccept('application/yaml', 'application/json');
+ this.getEditFileData();
+ } else {
+ this.getUpdateURL = environment.NSDESCRIPTORS_URL;
+ this.getFileContentType = 'nsd';
+ this.updateFileContentType = 'nsd_content';
+ this.pacakgeType = 'nsd';
+ this.navigatePath = 'ns';
+ this.fileTypes = [{ value: 'text/x-yaml', viewValue: 'yaml' }, { value: 'text/json', viewValue: 'json' }];
+ this.httpOptions = this.getHeadersWithContentAccept('application/zip', 'application/json');
+ this.getEditFileData();
+ }
+ }
+
+ /** Get the headers based on the type @public */
+ public getHeadersWithContentAccept(contentType: string, acceptType: string): HttpHeaders {
+ this.headers = new HttpHeaders({
+ 'Content-Type': contentType,
+ Accept: acceptType,
+ 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
+ });
+ return this.headers;
+ }
+
+ /** ChangeMode function @public */
+ public changeMode(): void {
+ if (this.mode === 'text/x-yaml') {
+ this.modeDefault = 'yaml';
+ } else {
+ this.modeDefault = 'javascript';
+ }
+ this.options = {
+ ...this.options,
+ mode: this.modeDefault
+ };
+ this.data = '';
+ }
+
+ /** HandleChange function @public */
+ public handleChange($event: string): void {
+ this.data = $event;
+ }
+
+ /** Update function @public */
+ public update(showgraph: boolean): void {
+ if (this.data === '') {
+ this.notifierService.notify('warning', this.translateService.instant('PAGE.TOPOLOGY.DATAEMPTY'));
+ } else {
+ this.updateCheck(showgraph);
+ }
+ }
+ /** Update the file Data @public */
+ public updateFileData(urlHeader: APIURLHEADER, fileData: string | ArrayBuffer, showgraph: boolean, packageType: string): void {
+ this.restService.putResource(urlHeader, fileData).subscribe(() => {
+ this.isLoadingResults = false;
+ this.notifierService.notify('success', this.translateService.instant(
+ (packageType !== 'netslice') ? 'PAGE.NSPACKAGE.EDITPACKAGES.UPDATEDSUCCESSFULLY' : 'PAGE.NETSLICE.UPDATEDSUCCESSFULLY'));
+ if (showgraph) {
+ if (packageType === 'nsd') {
+ this.router.navigate(['/packages/ns/compose/' + this.paramsID]).catch();
+ } else if (packageType === 'vnf') {
+ this.router.navigate(['/packages/vnf/compose/' + this.paramsID]).catch();
+ }
+ }
+ this.getEditFileData();
+ }, (error: ERRORDATA) => {
+ this.isLoadingResults = false;
+ this.restService.handleError(error, 'put');
+ });
+ }
+ /** Update method for NS, VNF and net-slice template */
+ private updateCheck(showgraph: boolean): void {
+ this.isLoadingResults = true;
+ const apiURLHeader: APIURLHEADER = {
+ url: this.getUpdateURL + '/' + this.paramsID + '/' + this.updateFileContentType,
+ httpOptions: { headers: this.httpOptions }
+ };
+ let descriptorInfo: string = '';
+ if (this.mode === 'text/json') {
+ descriptorInfo = jsyaml.dump(JSON.parse(this.data), {sortKeys: true});
+ } else {
+ descriptorInfo = this.data;
+ }
+ if (this.getFileContentType !== 'nst') {
+ this.sharedService.targzFile({ packageType: this.pacakgeType, id: this.paramsID, descriptor: descriptorInfo })
+ .then((content: ArrayBuffer): void => {
+ this.updateFileData(apiURLHeader, content, showgraph, this.pacakgeType);
+ }).catch((): void => {
+ this.isLoadingResults = false;
+ this.notifierService.notify('error', this.translateService.instant('ERROR'));
+ });
+ } else {
+ this.updateFileData(apiURLHeader, descriptorInfo, showgraph, this.pacakgeType);
+ }
+ }
+ /** Get the YAML content response as a plain/text and convert to JSON Format @private */
+ private getEditFileData(): void {
+ this.isLoadingResults = true;
+ const gethttpOptions: HttpHeaders = this.getHeadersWithContentAccept('application/json', 'text/plain');
+ const httpOptions: GETAPIURLHEADER = {
+ headers: gethttpOptions,
+ responseType: 'text'
+ };
+ this.restService.getResource(this.getUpdateURL + '/' + this.paramsID + '/' + this.getFileContentType, httpOptions)
+ .subscribe((nsData: NSDDetails[]) => {
+ const getJson: string = jsyaml.load(nsData.toString(), { json: true });
+ //tslint:disable-next-line:no-string-literal
+ this.defaults['text/x-yaml'] = nsData.toString();
+ this.defaults['text/json'] = JSON.stringify(getJson, null, '\t');
+ this.isLoadingResults = false;
+ }, (error: ERRORDATA) => {
+ error.error = typeof error.error === 'string' ? jsyaml.load(error.error) : error.error;
+ if (error.error.status === HttpStatus.NOT_FOUND || error.error.status === HttpStatus.UNAUTHORIZED ) {
+ this.router.navigateByUrl('404', { skipLocationChange: true }).catch();
+ } else {
+ this.restService.handleError(error, 'get');
+ }
+ this.isLoadingResults = false;
+ });
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="loader-overlay">
+ <div class="loader-content loader-center text-center">
+ <div class="loader">{{'LOADING' | translate}}...</div>
+ <p class="loader-text">
+ <strong>{{getMessage | translate}}
+ <span class="loader__dot" *ngFor="let index of [0,1,2]">.</span>
+ </strong>
+ </p>
+ </div>
+</div>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+@import '../../../assets/scss/mixins/mixin';
+@import '../../../assets/scss/variable';
+.loader-overlay {
+ -ms-opacity: 0.9;
+ @include background(null, $white, null, null, null);
+ @include position_value(absolute, 0, null, null, 0);
+ @include wh-value(100%, 100%);
+ opacity: 0.9;
+ vertical-align: middle;
+ z-index: 100000;
+ .loader-content {
+ @include wh-value(50%, null);
+ margin-left: auto;
+ margin-top: auto;
+ .loader-text {
+ color: $body-color;
+ }
+ }
+ .loader-center {
+ @include position_value(absolute, 50%, null, null, 50%);
+ @include flexbox(block, null, null, null, null, null);
+ -moz-transform: translate(-50%, -50%);
+ -ms-transform: translate(-50%, -50%);
+ -o-transform: translate(-50%, -50%);
+ -webkit-transform: translate(-50%, -50%);
+ transform: translate(-50%, -55%);
+ }
+}
+.loader,
+.loader:after {
+ @include roundedCornersPercentage(50%);
+ @include wh-value(10em, 10em);
+}
+.loader {
+ @include font(null, 3px, null);
+ @include position_value(relative, null, null, null, null);
+ @include border(top, 2, solid, rgba(5, 76, 140, 0.28));
+ @include border(right, 2, solid, rgba(5, 76, 140, 0.28));
+ @include border(bottom, 2, solid, rgba(5, 76, 140, 0.28));
+ @include border(left, 2, solid, $primary);
+ margin: 0 auto;
+ text-indent: -9999em;
+ -webkit-transform: translateZ(0);
+ -ms-transform: translateZ(0);
+ transform: translateZ(0);
+ -webkit-animation: load8 1.1s infinite linear;
+ animation: load8 1.1s infinite linear;
+}
+@-webkit-keyframes load8 {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+@keyframes load8 {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+@keyframes blink {50% { color: transparent }}
+.loader__dot { animation: 1s blink infinite }
+.loader__dot:nth-child(2) { animation-delay: 250ms }
+.loader__dot:nth-child(3) { animation-delay: 500ms }
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file Delete Model
+ */
+import { Component, Input, OnInit } from '@angular/core';
+/**
+ * Creating component
+ * @Component takes LoaderComponent.html as template url
+ */
+@Component({
+ selector: 'app-loader',
+ templateUrl: './LoaderComponent.html',
+ styleUrls: ['./LoaderComponent.scss']
+})
+/** Exporting a class @exports LoaderComponent */
+export class LoaderComponent implements OnInit {
+ /** Variables declared to get the message from parents @public */
+ @Input() public waitingMessage: string;
+ /** Variables declared to get the message of loader @public */
+ public getMessage: string;
+
+ constructor() {
+ // Empty block
+ }
+
+ public ngOnInit(): void {
+ if (this.waitingMessage !== '') {
+ this.getMessage = this.waitingMessage;
+ } else {
+ this.getMessage = '';
+ }
+ }
+
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file Loader Module.
+ */
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { TranslateModule } from '@ngx-translate/core';
+import { LoaderComponent } from 'LoaderComponent';
+/**
+ * Creating @NgModule component for Modules
+ */
+@NgModule({
+ imports: [CommonModule, TranslateModule],
+ declarations: [LoaderComponent],
+ exports: [LoaderComponent]
+})
+/** Exporting a class @exports LoaderModule */
+export class LoaderModule {
+ /**
+ * Lifecyle Hooks the trigger before component is instantiate
+ */
+ public ngOnInit(): void {
+ // Empty Block
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="btn-group list action" role="group">
+ <button type="button" class="btn btn-primary" (click)="infoNetSliceInstance()" placement="top" container="body"
+ ngbTooltip="{{'INFO' | translate}}">
+ <i class="fas fa-info icons"></i>
+ </button>
+ <button type="button" class="btn btn-primary" (click)="deleteNetSliceInstance(false)" placement="top"
+ container="body" ngbTooltip="{{'DELETE' | translate}}">
+ <i class="far fa-trash-alt icons"></i>
+ </button>
+ <div ngbDropdown class="btn-group">
+ <button type="button" class="btn btn-primary dropdown-toggle action-button" ngbDropdownToggle>
+ {{'ACTION' | translate}}
+ </button>
+ <div class="dropdown-menu" ngbDropdownMenu>
+ <button type="button" class="btn btn-primary dropdown-item" (click)="historyOfOperations()" placement="left"
+ container="body" ngbTooltip="{{'HISTORYOFOPERATIONS' | translate}}">
+ <i class="fas fa-history"></i> {{'HISTORYOFOPERATIONS' | translate}}
+ </button>
+ <button type="button" class="btn btn-primary dropdown-item text-danger" (click)="deleteNetSliceInstance(true)" placement="left"
+ container="body" ngbTooltip="{{'FORCEDELETE' | translate}}">
+ <i class="fas fa-trash-alt icons text-danger"></i> {{'FORCEDELETE' | translate}}
+ </button>
+ </div>
+ </div>
+</div>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file Netslice InstancesAction Component
+ */
+import { Component, Injector } from '@angular/core';
+import { Router } from '@angular/router';
+import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
+import { MODALCLOSERESPONSEDATA } from 'CommonModel';
+import { DeleteComponent } from 'DeleteComponent';
+import { NSTInstanceData } from 'NetworkSliceModel';
+import { SharedService } from 'SharedService';
+import { ShowInfoComponent } from 'ShowInfoComponent';
+/**
+ * Creating component
+ * @Component takes NetsliceInstancesActionComponent.html as template url
+ */
+@Component({
+ templateUrl: './NetsliceInstancesActionComponent.html',
+ styleUrls: ['./NetsliceInstancesActionComponent.scss']
+})
+/** Exporting a class @exports NetsliceInstancesActionComponent */
+export class NetsliceInstancesActionComponent {
+ /** To get the value from the vnfpackage via valuePrepareFunction default Property of ng-smarttable @public */
+ public value: NSTInstanceData;
+
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** Instance of the modal service @private */
+ private modalService: NgbModal;
+
+ /** Contains instance ID @private */
+ private instanceID: string;
+
+ /** Service holds the router information @private */
+ private router: Router;
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.modalService = this.injector.get(NgbModal);
+ this.router = this.injector.get(Router);
+ this.sharedService = this.injector.get(SharedService);
+ }
+ /**
+ * Lifecyle Hooks the trigger before component is instantiate
+ */
+ public ngOnInit(): void {
+ this.instanceID = this.value.identifier;
+ }
+
+ /** Shows information using modalservice @public */
+ public infoNetSliceInstance(): void {
+ this.modalService.open(ShowInfoComponent, { backdrop: 'static' }).componentInstance.params = {
+ id: this.instanceID,
+ page: 'net-slice-instance',
+ titleName: 'PAGE.NETSLICETEMPLATE.NETSLICETEMPLATEDETAILS'
+ };
+ }
+
+ /** Delete NetSlice Instance packages @public */
+ public deleteNetSliceInstance(forceAction: boolean): void {
+ const modalRef: NgbModalRef = this.modalService.open(DeleteComponent, { backdrop: 'static' });
+ modalRef.componentInstance.params = {forceDeleteType: forceAction};
+ modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
+ if (result) {
+ this.sharedService.callData();
+ }
+ }).catch();
+ }
+ /** History of operations for an Instanace @public */
+ public historyOfOperations(): void {
+ this.router.navigate(['/instances/netslice/history-operations/', this.instanceID]).catch(() => {
+ // Catch Navigation Error
+ });
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="btn-group list action" role="group">
+ <button type="button" class="btn btn-primary" (click)="instantiateNetSlice()" placement="top" container="body"
+ ngbTooltip="{{'INSTANTIATE' | translate}} NS">
+ <i class="fa fa-paper-plane icons"></i>
+ </button>
+ <button type="button" class="btn btn-primary" (click)="infoNetSlice()" placement="top" container="body"
+ ngbTooltip="{{'INFO' | translate}}">
+ <i class="fas fa-info icons"></i>
+ </button>
+ <button type="button" class="btn btn-primary" (click)="netSliceEdit()" placement="top" container="body" ngbTooltip="{{'EDIT' | translate}}">
+ <i class="fa fa-edit icons"></i>
+ </button>
+ <button type="button" class="btn btn-primary" (click)="deleteNetSliceTemplate()" placement="top" container="body"
+ ngbTooltip="{{'DELETE' | translate}}">
+ <i class="far fa-trash-alt icons"></i>
+ </button>
+</div>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file Netslice-packagesAction Component
+ */
+import { Component, Injector } from '@angular/core';
+import { Router } from '@angular/router';
+import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
+import { MODALCLOSERESPONSEDATA } from 'CommonModel';
+import { DeleteComponent } from 'DeleteComponent';
+import { InstantiateNetSliceTemplateComponent } from 'InstantiateNetSliceTemplate';
+import { NetworkSliceData } from 'NetworkSliceModel';
+import { SharedService } from 'SharedService';
+import { ShowInfoComponent } from 'ShowInfoComponent';
+
+/**
+ * Creating component
+ * @Component takes NetslicePackagesActionComponent.html as template url
+ */
+@Component({
+ selector: 'app-netslice-packages-action',
+ templateUrl: './NetslicePackagesActionComponent.html',
+ styleUrls: ['./NetslicePackagesActionComponent.scss']
+})
+/** Exporting a class @exports NetslicePackagesActionComponent */
+export class NetslicePackagesActionComponent {
+ /** To get the value from the vnfpackage via valuePrepareFunction default Property of ng-smarttable @public */
+ public value: NetworkSliceData;
+
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** Instance of the modal service @private */
+ private modalService: NgbModal;
+
+ /** Contains instance ID @private */
+ private instanceID: string;
+
+ /** Service holds the router information @private */
+ private router: Router;
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.modalService = this.injector.get(NgbModal);
+ this.router = this.injector.get(Router);
+ this.sharedService = this.injector.get(SharedService);
+ }
+
+ /** Lifecyle Hooks the trigger before component is instantiate @public */
+ public ngOnInit(): void {
+ this.instanceID = this.value.identifier;
+ }
+
+ /** Delete NetSliceTemplate packages @public */
+ public deleteNetSliceTemplate(): void {
+ const modalRef: NgbModalRef = this.modalService.open(DeleteComponent, {backdrop: 'static'});
+ modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
+ if (result) {
+ this.sharedService.callData();
+ }
+ }).catch();
+ }
+
+ /** Shows information using modalservice @public */
+ public infoNetSlice(): void {
+ this.modalService.open(ShowInfoComponent, { backdrop: 'static' }).componentInstance.params = {
+ id: this.instanceID,
+ page: 'net-slice-package',
+ titleName: 'PAGE.NETSLICETEMPLATE.NETSLICETEMPLATEDETAILS'
+ };
+ }
+
+ /** Set Edit for the @public */
+ public netSliceEdit(): void {
+ this.router.navigate(['/packages/netslice/edit/', this.instanceID]).catch(() => {
+ // Catch Navigation Error
+ });
+ }
+
+ /** Instantiate Net Slice using modalservice @public */
+ public instantiateNetSlice(): void {
+ this.modalService.open(InstantiateNetSliceTemplateComponent, { backdrop: 'static' });
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="btn-group list action" role="group">
+ <button type="button" class="btn btn-primary" (click)="metrics()" placement="top" container="body"
+ [disabled]="operationalStatus == 'failed' || configStatus == 'failed'" ngbTooltip="{{'METRICS' | translate}}">
+ <i class="fas fa-chart-bar icons"></i>
+ </button>
+ <button type="button" class="btn btn-primary" [disabled]="operationalStatus != 'running'" (click)="nsTopology()"
+ placement="top" container="body" ngbTooltip="{{'TOPOLOGY' | translate}}">
+ <i class="fa fa-sitemap fa-fw icons"></i>
+ </button>
+ <button type="button" class="btn btn-primary" (click)="deleteNSInstance(false)" placement="top" container="body"
+ ngbTooltip="{{'DELETE' | translate}}">
+ <i class="far fa-trash-alt icons"></i>
+ </button>
+ <div ngbDropdown class="btn-group">
+ <button type="button" class="btn btn-primary dropdown-toggle action-button" ngbDropdownToggle>
+ {{'ACTION' | translate}}
+ </button>
+ <div class="dropdown-menu" ngbDropdownMenu>
+ <button type="button" class="btn btn-primary dropdown-item" (click)="infoNs()" placement="left"
+ container="body" ngbTooltip="{{'INFO' | translate}}">
+ <i class="fas fa-info icons list" title="info"></i> {{'INFO' | translate}}
+ </button>
+ <button type="button" class="btn btn-primary dropdown-item" (click)="execNSPrimitiveModal()"
+ placement="left" container="body" ngbTooltip="{{'EXECNSPRIMITIVE' | translate}}"
+ [disabled]="operationalStatus == 'failed' || configStatus == 'failed'">
+ <i class="fas fa-magic"></i> {{'EXECNSPRIMITIVE' | translate}}
+ </button>
+ <button type="button" class="btn btn-primary dropdown-item" (click)="historyOfOperations()" placement="left"
+ container="body" ngbTooltip="{{'HISTORYOFOPERATIONS' | translate}}">
+ <i class="fas fa-history"></i> {{'HISTORYOFOPERATIONS' | translate}}
+ </button>
+ <button type="button" class="btn btn-primary dropdown-item text-danger" (click)="deleteNSInstance(true)"
+ placement="left" container="body" ngbTooltip="{{'FORCEDELETE' | translate}}">
+ <i class="fas fa-trash-alt icons text-danger"></i> {{'FORCEDELETE' | translate}}
+ </button>
+ </div>
+ </div>
+</div>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingMetricsResult"></app-loader>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file NS InstancesAction Component
+ */
+import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Injector } from '@angular/core';
+import { Router } from '@angular/router';
+import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateService } from '@ngx-translate/core';
+import { NotifierService } from 'angular-notifier';
+import { ERRORDATA, MODALCLOSERESPONSEDATA } from 'CommonModel';
+import { DeleteComponent } from 'DeleteComponent';
+import { environment } from 'environment';
+import { NSDDetails } from 'NSDModel';
+import { NSDInstanceData } from 'NSInstanceModel';
+import { NSPrimitiveComponent } from 'NSPrimitiveComponent';
+import { RestService } from 'RestService';
+import { SharedService } from 'SharedService';
+import { ShowInfoComponent } from 'ShowInfoComponent';
+/**
+ * Creating component
+ * @Component takes NSInstancesActionComponent.html as template url
+ */
+@Component({
+ templateUrl: './NSInstancesActionComponent.html',
+ styleUrls: ['./NSInstancesActionComponent.scss'],
+ changeDetection: ChangeDetectionStrategy.OnPush
+})
+/** Exporting a class @exports NSInstancesActionComponent */
+export class NSInstancesActionComponent {
+ /** To get the value from the nspackage via valuePrepareFunction default Property of ng-smarttable @public */
+ public value: NSDInstanceData;
+
+ /** Invoke service injectors @public */
+ public injector: Injector;
+
+ /** Instance of the modal service @public */
+ public restService: RestService;
+
+ /** Config Status Check @public */
+ public configStatus: string;
+
+ /** Operational Status Check @public */
+ public operationalStatus: string;
+
+ /** Check the loading results for loader status @public */
+ public isLoadingMetricsResult: boolean = false;
+
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+
+ /** Instance of the modal service @private */
+ private modalService: NgbModal;
+
+ /** Holds teh instance of AuthService class of type AuthService @private */
+ private router: Router;
+
+ /** Contains instance ID @private */
+ private instanceID: string;
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ /** Notifier service to popup notification @private */
+ private notifierService: NotifierService;
+
+ /** Contains tranlsate instance @private */
+ private translateService: TranslateService;
+
+ /** Detect changes for the User Input */
+ private cd: ChangeDetectorRef;
+
+ /** Set timeout @private */
+ private timeOut: number = 1000;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.modalService = this.injector.get(NgbModal);
+ this.restService = this.injector.get(RestService);
+ this.router = this.injector.get(Router);
+ this.sharedService = this.injector.get(SharedService);
+ this.notifierService = this.injector.get(NotifierService);
+ this.translateService = this.injector.get(TranslateService);
+ this.cd = this.injector.get(ChangeDetectorRef);
+ }
+
+ /**
+ * Lifecyle Hooks the trigger before component is instantiate
+ */
+ public ngOnInit(): void {
+ this.configStatus = this.value.ConfigStatus;
+ this.operationalStatus = this.value.OperationalStatus;
+ this.instanceID = this.value.identifier;
+ }
+
+ /** Shows information using modalservice @public */
+ public infoNs(): void {
+ this.modalService.open(ShowInfoComponent, { backdrop: 'static' }).componentInstance.params = {
+ id: this.instanceID,
+ page: 'ns-instance',
+ titleName: 'INSTANCEDETAILS'
+ };
+ }
+
+ /** Delete NS Instanace @public */
+ public deleteNSInstance(forceAction: boolean): void {
+ const modalRef: NgbModalRef = this.modalService.open(DeleteComponent, { backdrop: 'static' });
+ modalRef.componentInstance.params = { forceDeleteType: forceAction };
+ modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
+ if (result) {
+ this.sharedService.callData();
+ }
+ }).catch();
+ }
+
+ /** History of operations for an Instanace @public */
+ public historyOfOperations(): void {
+ this.router.navigate(['/instances/ns/history-operations/', this.instanceID]).catch(() => {
+ // Catch Navigation Error
+ });
+ }
+
+ /** NS Topology */
+ public nsTopology(): void {
+ this.router.navigate(['/instances/ns/', this.instanceID]).catch(() => {
+ // Catch Navigation Error
+ });
+ }
+
+ /** Exec NS Primitive @public */
+ public execNSPrimitiveModal(): void {
+ this.modalService.open(NSPrimitiveComponent).componentInstance.params = {
+ memberIndex: this.value.memberIndex,
+ nsConfig: this.value.nsConfig
+ };
+ }
+
+ /** Redirect to Grafana Metrics @public */
+ public metrics(): void {
+ this.isLoadingMetricsResult = true;
+ this.restService.getResource(environment.NSDINSTANCES_URL + '/' + this.instanceID).subscribe((nsData: NSDDetails[]) => {
+ nsData['vnfd-id'].forEach((vnfdID: string[]) => {
+ this.restService.getResource(environment.VNFPACKAGES_URL + '/' + vnfdID)
+ .subscribe((vnfd: {}[]) => {
+ if (vnfd['monitoring-param'] !== undefined && vnfd['monitoring-param'].length > 0) {
+ this.isLoadingMetricsResult = false;
+ const location: string = environment.GRAFANA_URL + '/' + this.instanceID + '/osm-ns-metrics-metrics';
+ window.open(location);
+ } else {
+ this.isLoadingMetricsResult = false;
+ this.notifierService.notify('error', this.translateService.instant('GRAFANA.METRICSERROR'));
+ }
+ setTimeout(() => {
+ this.cd.detectChanges();
+ }, this.timeOut);
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'get');
+ this.isLoadingMetricsResult = false;
+ });
+ });
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'get');
+ this.isLoadingMetricsResult = false;
+ });
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="btn-group list action" role="group">
+ <button type="button" class="btn btn-primary" (click)="instantiateNS()" placement="top" container="body"
+ ngbTooltip="{{'INSTANTIATE' | translate}} NS">
+ <i class="fa fa-paper-plane icons"></i>
+ </button>
+ <button type="button" class="btn btn-primary" (click)="composeNSPackages()" placement="top" container="body"
+ ngbTooltip="{{'TOPOLOGY' | translate}}">
+ <i class="fa fa-sitemap fa-fw Icon"></i>
+ </button>
+ <button type="button" class="btn btn-primary" (click)="deleteNSPackage()" placement="top" container="body"
+ ngbTooltip="{{'DELETE' | translate}}">
+ <i class="far fa-trash-alt icons"></i>
+ </button>
+ <div ngbDropdown class="btn-group">
+ <button type="button" class="btn btn-primary dropdown-toggle action-button" ngbDropdownToggle>
+ {{'ACTION' | translate}}
+ </button>
+ <div class="dropdown-menu" ngbDropdownMenu>
+ <button type="button" class="btn btn-primary dropdown-item" (click)="nsdEdit()" placement="left"
+ container="body" ngbTooltip="{{'EDIT' | translate}}">
+ <i class="fa fa-edit icons"></i> {{'EDIT' | translate}}
+ </button>
+ <button type="button" class="btn btn-primary dropdown-item" (click)="downloadNSPackage()" placement="left"
+ container="body" ngbTooltip="{{'DOWNLOAD' | translate}}">
+ <i class="fas fa-download icons"></i> {{'DOWNLOAD' | translate}}
+ </button>
+ <button type="button" class="btn btn-primary dropdown-item" (click)="cloneNSPackage()" placement="left"
+ container="body" ngbTooltip="{{'CLONE' | translate}}">
+ <i class="fa fa-clone icons"></i> {{'CLONE' | translate}}
+ </button>
+ <button type="button" class="btn btn-primary dropdown-item" (click)="showContent()" placement="left"
+ container="body" ngbTooltip="{{'CONTENT' | translate}}">
+ <i class="far fa-folder-open icons"></i> {{'CONTENT' | translate}}
+ </button>
+ </div>
+ </div>
+</div>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingDownloadResult"></app-loader>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file NS PackagesAction Component
+ */
+import { HttpHeaders } from '@angular/common/http';
+import { ChangeDetectorRef, Component, Injector } from '@angular/core';
+import { Router } from '@angular/router';
+import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateService } from '@ngx-translate/core';
+import { NotifierService } from 'angular-notifier';
+import { ClonePackageComponent } from 'ClonePackage';
+import { ERRORDATA, GETAPIURLHEADER, MODALCLOSERESPONSEDATA } from 'CommonModel';
+import { DeleteComponent } from 'DeleteComponent';
+import { environment } from 'environment';
+import { InstantiateNsComponent } from 'InstantiateNs';
+import { NSData } from 'NSDModel';
+import { RestService } from 'RestService';
+import { SharedService } from 'SharedService';
+import { ShowContentComponent } from 'ShowContent';
+
+/**
+ * Creating component
+ * @Component takes NsPackagesActionComponent.html as template url
+ */
+@Component({
+ selector: 'app-ns-packages-action',
+ templateUrl: './NsPackagesActionComponent.html',
+ styleUrls: ['./NsPackagesActionComponent.scss']
+})
+
+/** Exporting a class @exports NsPackagesActionComponent */
+export class NsPackagesActionComponent {
+ /** To get the value from the nspackage via valuePrepareFunction default Property of ng-smarttable @public */
+ public value: NSData;
+
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** Check the loading results for loader status @public */
+ public isLoadingDownloadResult: boolean = false;
+
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+
+ /** Instance of the rest service @private */
+ private restService: RestService;
+
+ /** Holds teh instance of AuthService class of type AuthService @private */
+ private router: Router;
+
+ /** Instance of the modal service @private */
+ private modalService: NgbModal;
+
+ /** Variables holds NS ID @private */
+ private nsdID: string;
+
+ /** Variables holds NS name @private */
+ private nsdName: string;
+
+ /** Controls the header form @private */
+ private headers: HttpHeaders;
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ /** Notifier service to popup notification @private */
+ private notifierService: NotifierService;
+
+ /** Contains tranlsate instance @private */
+ private translateService: TranslateService;
+
+ /** Detect changes for the User Input */
+ private cd: ChangeDetectorRef;
+
+ /** Set timeout @private */
+ private timeOut: number = 1000;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.restService = this.injector.get(RestService);
+ this.sharedService = this.injector.get(SharedService);
+ this.modalService = this.injector.get(NgbModal);
+ this.router = this.injector.get(Router);
+ this.notifierService = this.injector.get(NotifierService);
+ this.translateService = this.injector.get(TranslateService);
+ this.cd = this.injector.get(ChangeDetectorRef);
+ }
+
+ /** Lifecyle Hooks the trigger before component is instantiate @public */
+ public ngOnInit(): void {
+ this.headers = new HttpHeaders({
+ Accept: 'application/zip, application/json',
+ 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
+ });
+ this.nsdID = this.value.identifier;
+ this.nsdName = this.value.shortName;
+ }
+
+ /** Instantiate NS using modalservice @public */
+ public instantiateNS(): void {
+ this.modalService.open(InstantiateNsComponent, { backdrop: 'static' });
+ }
+
+ /** Delete NS Package @public */
+ public deleteNSPackage(): void {
+ const modalRef: NgbModalRef = this.modalService.open(DeleteComponent, { backdrop: 'static' });
+ modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
+ if (result) {
+ this.sharedService.callData();
+ }
+ }).catch();
+ }
+
+ /** Set instance for NSD Edit @public */
+ public nsdEdit(): void {
+ this.router.navigate(['/packages/ns/edit/', this.nsdID]).catch(() => {
+ // Catch Navigation Error
+ });
+ }
+
+ /** list out all the file content of a descriptors @public */
+ public showContent(): void {
+ this.modalService.open(ShowContentComponent, { backdrop: 'static' }).componentInstance.params = { id: this.nsdID, page: 'nsd' };
+ }
+
+ /** Download NS Package @public */
+ public downloadNSPackage(): void {
+ this.isLoadingDownloadResult = true;
+ const httpOptions: GETAPIURLHEADER = {
+ headers: this.headers,
+ responseType: 'blob'
+ };
+ this.restService.getResource(environment.NSDESCRIPTORS_URL + '/' + this.nsdID + '/nsd_content', httpOptions)
+ .subscribe((response: Blob) => {
+ const binaryData: Blob[] = [];
+ binaryData.push(response);
+ this.sharedService.downloadFiles(this.nsdName, binaryData, response.type);
+ this.isLoadingDownloadResult = false;
+ this.changeDetactionforDownload();
+ }, (error: ERRORDATA) => {
+ this.isLoadingDownloadResult = false;
+ this.notifierService.notify('error', this.translateService.instant('ERROR'));
+ this.changeDetactionforDownload();
+ if (typeof error.error === 'object') {
+ error.error.text().then((data: string): void => {
+ error.error = JSON.parse(data);
+ this.restService.handleError(error, 'getBlob');
+ });
+ }
+ });
+ }
+
+ /** Compose NS Packages @public */
+ public composeNSPackages(): void {
+ this.router.navigate(['/packages/ns/compose/', this.nsdID]).catch(() => {
+ // Catch Navigation Error
+ });
+ }
+
+ /** Change the detaction @public */
+ public changeDetactionforDownload(): void {
+ setTimeout(() => {
+ this.cd.detectChanges();
+ }, this.timeOut);
+ }
+
+ /** Clone NS Packages @public */
+ public cloneNSPackage(): void {
+ const cloneModal: NgbModalRef = this.modalService.open(ClonePackageComponent, { backdrop: 'static' });
+ cloneModal.componentInstance.params = { id: this.nsdID, page: 'nsd', name: this.nsdName };
+ cloneModal.result.then((result: MODALCLOSERESPONSEDATA) => {
+ if (result) {
+ this.sharedService.callData();
+ }
+ }).catch();
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="page-per-row">
+ <label class="mr-2 mt-2">
+ <b>{{'ENTRIES' | translate}}</b>
+ </label>
+ <select class="form-control custom-select" (change)="onSelectRow($event.target.value)">
+ <option *ngFor="let count of pageCount; let i = index" [value]="count.value" [selected]="count.value === getDefaultSelected">{{count.viewValue}}
+ </option>
+ </select>
+</div>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+.page-per-row {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-between;
+}
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+
+/**
+ * @file PagePerRow Model
+ */
+import { Component, EventEmitter, Injector, Output } from '@angular/core';
+import { TranslateService } from '@ngx-translate/core';
+import { PAGERSMARTTABLE } from 'CommonModel';
+import { SharedService } from 'SharedService';
+
+/**
+ * Creating component
+ * @Component takes PagePerRow.html as template url
+ */
+@Component({
+ selector: 'page-per-row',
+ templateUrl: './PagePerRow.html',
+ styleUrls: ['./PagePerRow.scss']
+})
+/** Exporting a class @exports PagePerRow */
+export class PagePerRow {
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** handle translate @public */
+ public translateService: TranslateService;
+
+ /** get the pagaintion default select value @public */
+ public getDefaultSelected: number;
+
+ /** Controls the pagination List Count form @public */
+ public pageCount: { value: number; viewValue: number; }[] =
+ [
+ { value: 10, viewValue: 10 },
+ { value: 25, viewValue: 25 },
+ { value: 50, viewValue: 50 },
+ { value: 100, viewValue: 100 }
+ ];
+
+ /** Contains all methods related to shared @private */
+ public sharedService: SharedService;
+
+ /** Event emitter to emit selected page number @public */
+ @Output() public pagePerRow: EventEmitter<number> = new EventEmitter();
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.translateService = this.injector.get(TranslateService);
+ this.sharedService = this.injector.get(SharedService);
+ }
+
+ /**
+ * Lifecyle Hooks the trigger before component is instantiate
+ */
+ public ngOnInit(): void {
+ const getPaginationValues: PAGERSMARTTABLE = this.sharedService.paginationPagerConfig();
+ this.getDefaultSelected = getPaginationValues.perPage;
+ }
+
+ /** Handles select event @public */
+ public onSelectRow(e: number): void {
+ this.pagePerRow.emit(e);
+ }
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file Page Per Row Module.
+ */
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { TranslateModule } from '@ngx-translate/core';
+import { PagePerRow } from 'PagePerRow';
+
+/**
+ * Creating @NgModule component for Modules
+ */
+@NgModule({
+ imports: [CommonModule, TranslateModule],
+ declarations: [PagePerRow],
+ exports: [PagePerRow]
+})
+/** Exporting a class @exports PagePerRowModule */
+export class PagePerRowModule {
+ /**
+ * Lifecyle Hooks the trigger before component is instantiate
+ */
+ public ngOnInit(): void {
+ // Empty Block
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<button class="btn btn-sm btn-primary border border-radius-default" placement="top" container="body"
+ ngbTooltip="{{'REFRESH' | translate}}" (click)="reloadPage()">
+ <i class="fas fa-sync"></i>
+</button>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file Page Reload Component
+ */
+import { Component, Injector } from '@angular/core';
+import { TranslateService } from '@ngx-translate/core';
+import { SharedService } from 'SharedService';
+/**
+ * Creating component
+ * @Component takes PageReload.html as template url
+ */
+@Component({
+ selector: 'page-reload',
+ templateUrl: './PageReload.html',
+ styleUrls: ['./PageReload.scss']
+})
+/** Exporting a class @exports PageReload */
+export class PageReload {
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** handle translate @public */
+ public translateService: TranslateService;
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.translateService = this.injector.get(TranslateService);
+ this.sharedService = this.injector.get(SharedService);
+ }
+
+ /**
+ * Lifecyle Hooks the trigger before component is instantiate
+ */
+ public ngOnInit(): void {
+ // Empty Block
+ }
+
+ /** Handles select event @public */
+ public reloadPage(): void {
+ this.sharedService.dataEvent.emit();
+ }
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file Page Per Row Module.
+ */
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateModule } from '@ngx-translate/core';
+import { PageReload } from 'PageReload';
+
+/**
+ * Creating @NgModule component for Modules
+ */
+@NgModule({
+ imports: [CommonModule, TranslateModule, NgbModule],
+ declarations: [PageReload],
+ exports: [PageReload]
+})
+/** Exporting a class @exports PageReloadModule */
+export class PageReloadModule {
+ /**
+ * Lifecyle Hooks the trigger before component is instantiate
+ */
+ public ngOnInit(): void {
+ // Empty Block
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="btn-group list action" role="group">
+ <button type="button" class="btn btn-primary" (click)="showInfo()" placement="top" container="body" ngbTooltip="{{'INFO' | translate}}">
+ <i class="fas fa-info icons"></i>
+ </button>
+ <button type="button" class="btn btn-primary" (click)="deletePDUInstance()" placement="top" container="body" ngbTooltip="{{'DELETE' | translate}}">
+ <i class="far fa-trash-alt icons"></i>
+ </button>
+</div>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file PDUInstancesActionComponent Component
+ */
+import { Component, Injector } from '@angular/core';
+import { Router } from '@angular/router';
+import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
+import { MODALCLOSERESPONSEDATA } from 'CommonModel';
+import { DeleteComponent } from 'DeleteComponent';
+import { PDUInstanceDetails } from 'PDUInstanceModel';
+import { SharedService } from 'SharedService';
+import { ShowInfoComponent } from 'ShowInfoComponent';
+
+/**
+ * Creating component
+ * @Component takes PDUInstancesActionComponent.html as template url
+ */
+@Component({
+ templateUrl: './PDUInstancesActionComponent.html',
+ styleUrls: ['./PDUInstancesActionComponent.scss']
+})
+/** Exporting a class @exports PDUInstancesActionComponent */
+export class PDUInstancesActionComponent {
+ /** To get the value from the PDU Instances via valuePrepareFunction default Property of ng-smarttable @public */
+ public value: PDUInstanceDetails;
+
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** Instance of the modal service @private */
+ private modalService: NgbModal;
+
+ /** Contains PDU Instance ID @private */
+ private pduInstanceID: string;
+
+ /** Service holds the router information @private */
+ private router: Router;
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.modalService = this.injector.get(NgbModal);
+ this.router = this.injector.get(Router);
+ this.sharedService = this.injector.get(SharedService);
+ }
+
+ /** Lifecyle Hooks the trigger before component is instantiate @public */
+ public ngOnInit(): void {
+ this.pduInstanceID = this.value.identifier;
+ }
+
+ /** Delete PDU Instances @public */
+ public deletePDUInstance(): void {
+ const modalRef: NgbModalRef = this.modalService.open(DeleteComponent, {backdrop: 'static'});
+ modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
+ if (result) {
+ this.sharedService.callData();
+ }
+ }).catch();
+ }
+
+ /** Shows PDU Instances information using modalservice @public */
+ public showInfo(): void {
+ this.modalService.open(ShowInfoComponent, { backdrop: 'static' }).componentInstance.params = {
+ id: this.pduInstanceID,
+ page: 'pdu-instances',
+ titleName: 'INSTANCEDETAILS'
+ };
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<a *ngIf="isPresent" class="link" [ngClass]="value.projectName === selectedProject ? 'activeProject' : ''"
+ href="javascript:void(0);"
+ (click)="value.projectName === selectedProject ? '' : this.projectService.switchProjectModal(value)" placement="right" container="body" ngbTooltip="{{ (value.projectName === selectedProject ? 'CURRENTPROJECT' : 'SWITCHPROJECT') | translate}}">
+ <span>{{value.projectName}}</span>
+ <i *ngIf="value.projectName === selectedProject" class="fas fa-check-circle text-success"></i>
+ <i *ngIf="value.projectName !== selectedProject" class="fas fa-exchange-alt text-danger"></i>
+</a>
+<span *ngIf="!isPresent">{{value.projectName}}</span>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+@import '../../../assets/scss/mixins/mixin';
+@import '../../../assets/scss/variable';
+.link{
+ text-decoration: none !important;
+ &.activeProject{
+ border-radius: 3px;
+ @include padding-value(2, 2, 2, 2);
+ text-decoration: none !important;
+ cursor: default;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file Project Link Component.
+ */
+import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Injector, OnInit } from '@angular/core';
+import { environment } from 'environment';
+import { ProjectData } from 'ProjectModel';
+import { ProjectService } from 'ProjectService';
+import { RestService } from 'RestService';
+import { UserDetail } from 'UserModel';
+/**
+ * Creating component
+ * @Component takes ProjectLinkComponent.html as template url
+ */
+@Component({
+ selector: 'app-project-link',
+ templateUrl: './ProjectLinkComponent.html',
+ styleUrls: ['./ProjectLinkComponent.scss'],
+ changeDetection: ChangeDetectionStrategy.OnPush
+})
+/** Exporting a class @exports ProjectLinkComponent */
+export class ProjectLinkComponent implements OnInit {
+ /** Invoke service injectors @public */
+ public injector: Injector;
+ /** Variables holds the selected project @public */
+ public selectedProject: string;
+ /** To get the value from the nspackage via valuePrepareFunction default Property of ng-smarttable @public */
+ public value: ProjectData;
+ /** Variables holds all the projects @public */
+ public projectList: {}[] = [];
+ /** Check the project is present for the user @public */
+ public isPresent: boolean = false;
+ /** Set timeout @private */
+ private timeOut: number = 10;
+ /** Instance of the rest service @private */
+ private restService: RestService;
+ /** Holds all project details @private */
+ private projectService: ProjectService;
+ /** Detect changes for the User Input */
+ private cd: ChangeDetectorRef;
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.projectService = this.injector.get(ProjectService);
+ this.restService = this.injector.get(RestService);
+ this.cd = this.injector.get(ChangeDetectorRef);
+ }
+
+ public ngOnInit(): void {
+ this.selectedProject = localStorage.getItem('project');
+ this.getAdminProjects();
+ }
+
+ /** Get the admin projects to be selectable @public */
+ public getAdminProjects(): void {
+ const username: string = localStorage.getItem('username');
+ this.restService.getResource(environment.USERS_URL + '/' + username).subscribe((projects: UserDetail) => {
+ this.projectList = projects.project_role_mappings;
+ this.isPresent = this.projectList.some((item: ProjectData) => item.project === this.value.project);
+ setTimeout(() => {
+ this.cd.detectChanges();
+ }, this.timeOut);
+ });
+ }
+
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="btn-group list action" role="group">
+ <div ngbDropdown class="btn-group">
+ <button type="button" class="btn btn-primary dropdown-toggle action-button" ngbDropdownToggle>
+ {{'ACTION' | translate}}
+ </button>
+ <div class="dropdown-menu" ngbDropdownMenu>
+ <button type="button" class="btn btn-primary dropdown-item" (click)="projectEdit()" placement="left"
+ container="body" ngbTooltip="{{'RENAME' | translate}}">
+ <i class="fa fa-edit icons"></i> {{'RENAME' | translate}}
+ </button>
+ <button type="button" class="btn btn-primary dropdown-item" (click)="projectDelete()" placement="left"
+ container="body" ngbTooltip="{{'DELETE' | translate}}">
+ <i class="fas fa-trash-alt icons"></i> {{'DELETE' | translate}}
+ </button>
+ </div>
+ </div>
+</div>
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file Projects Action Component
+ */
+import { Component, Injector } from '@angular/core';
+import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
+import { MODALCLOSERESPONSEDATA } from 'CommonModel';
+import { DeleteComponent } from 'DeleteComponent';
+import { ProjectCreateUpdateComponent } from 'ProjectCreateUpdate';
+import { ProjectData } from 'ProjectModel';
+import { SharedService } from 'SharedService';
+
+/**
+ * Creating component
+ * @Component takes ProjectsActionComponent.html as template url
+ */
+@Component({
+ selector: 'app-projects-action',
+ templateUrl: './ProjectsActionComponent.html',
+ styleUrls: ['./ProjectsActionComponent.scss']
+})
+/** Exporting a class @exports ProjectsActionComponent */
+export class ProjectsActionComponent {
+ /** To get the value from the nspackage via valuePrepareFunction default Property of ng-smarttable @public */
+ public value: ProjectData;
+
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** Instance of the modal service @private */
+ private modalService: NgbModal;
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.modalService = this.injector.get(NgbModal);
+ this.sharedService = this.injector.get(SharedService);
+ }
+
+ /** Delete project @public */
+ public projectDelete(): void {
+ const modalRef: NgbModalRef = this.modalService.open(DeleteComponent, { backdrop: 'static' });
+ modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
+ if (result) {
+ this.sharedService.callData();
+ }
+ }).catch();
+ }
+
+ /** Edit project @public */
+ public projectEdit(): void {
+ const modalRef: NgbModalRef = this.modalService.open(ProjectCreateUpdateComponent, { backdrop: 'static' });
+ modalRef.componentInstance.projectType = 'Edit';
+ modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
+ if (result) {
+ this.sharedService.callData();
+ }
+ }).catch();
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="btn-group list action" role="group">
+ <div ngbDropdown class="btn-group">
+ <button type="button" class="btn btn-primary dropdown-toggle action-button" ngbDropdownToggle>
+ {{'ACTION' | translate}}
+ </button>
+ <div class="dropdown-menu" ngbDropdownMenu>
+ <button type="button" class="btn btn-primary dropdown-item" (click)="editRole()" placement="left"
+ container="body" ngbTooltip="{{'EDIT' | translate}}">
+ <i class="fa fa-edit icons"></i> {{'EDIT' | translate}}
+ </button>
+ <button type="button" class="btn btn-primary dropdown-item" (click)="deleteRole()" placement="left"
+ container="body" ngbTooltip="{{'DELETE' | translate}}">
+ <i class="fas fa-trash-alt icons"></i> {{'DELETE' | translate}}
+ </button>
+ </div>
+ </div>
+</div>
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file Roles Action Component
+ */
+import { Component, Injector } from '@angular/core';
+import { Router } from '@angular/router';
+import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
+import { MODALCLOSERESPONSEDATA } from 'CommonModel';
+import { DeleteComponent } from 'DeleteComponent';
+import { RoleData } from 'RolesModel';
+import { SharedService } from 'SharedService';
+
+/**
+ * Creating component
+ * @Component takes RolesActionComponent.html as template url
+ */
+@Component({
+ selector: 'app-roles-action',
+ templateUrl: './RolesActionComponent.html',
+ styleUrls: ['./RolesActionComponent.scss']
+})
+/** Exporting a class @exports RolesActionComponent */
+export class RolesActionComponent {
+ /** To get the role data via valuePrepareFunction default Property of ng-smarttable @public */
+ public value: RoleData;
+
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** Instance of the modal service @private */
+ private modalService: NgbModal;
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ /** Holds the instance of roter service @private */
+ private router: Router;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.modalService = this.injector.get(NgbModal);
+ this.sharedService = this.injector.get(SharedService);
+ this.router = this.injector.get(Router);
+ }
+
+ /** Delete Role click handler @public */
+ public deleteRole(): void {
+ const modalRef: NgbModalRef = this.modalService.open(DeleteComponent, { backdrop: 'static' });
+ modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
+ if (result) {
+ this.sharedService.callData();
+ }
+ }).catch();
+ }
+
+ /** Edit Role click handler @public */
+ public editRole(): void {
+ this.router.navigate(['/roles/edit', this.value.identifier]).catch(() => {
+ // Catch Navigation Error
+ });
+ }
+
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="btn-group list action" role="group">
+ <button type="button" class="btn btn-primary" (click)="showSDNControllerInfo()" placement="top" container="body"
+ ngbTooltip="{{'INFO' | translate}}">
+ <i class="fas fa-info icons"></i>
+ </button>
+ <button type="button" class="btn btn-primary" (click)="deleteSDNController()" placement="top" container="body"
+ ngbTooltip="{{'DELETE' | translate}}">
+ <i class="far fa-trash-alt icons"></i>
+ </button>
+</div>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file SDN Controller Action Component
+ */
+import { Component, Injector } from '@angular/core';
+import { Router } from '@angular/router';
+import { NgbActiveModal, NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
+import { MODALCLOSERESPONSEDATA } from 'CommonModel';
+import { DeleteComponent } from 'DeleteComponent';
+import { SDNControllerInfoComponent } from 'SDNControllerInfoComponent';
+import { SDNControllerList } from 'SDNControllerModel';
+import { SharedService } from 'SharedService';
+
+/**
+ * Creating component
+ * @Component takes SDNControllerActionComponent.html as template url
+ */
+@Component({
+ templateUrl: './SDNControllerActionComponent.html',
+ styleUrls: ['./SDNControllerActionComponent.scss']
+})
+/** Exporting a class @exports SDNControllerActionComponent */
+export class SDNControllerActionComponent {
+ /** To get the value from the vnfpackage via valuePrepareFunction default Property of ng-smarttable @public */
+ public value: SDNControllerList;
+
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** Instance of the modal service @private */
+ private modalService: NgbModal;
+
+ /** Variables holds SDN ID @private */
+ private sdnID: string;
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.modalService = this.injector.get(NgbModal);
+ this.sharedService = this.injector.get(SharedService);
+ }
+
+ /** Lifecyle Hooks the trigger before component is instantiate @public */
+ public ngOnInit(): void {
+ this.sdnID = this.value.identifier;
+ }
+
+ /** Show SDN Controller Information @public */
+ public showSDNControllerInfo(): void {
+ this.modalService.open(SDNControllerInfoComponent, { backdrop: 'static' }).componentInstance.params = {
+ id: this.sdnID,
+ page: 'sdn-controller'
+ };
+ }
+
+ /** Delete SDN Controller @public */
+ public deleteSDNController(): void {
+ const modalRef: NgbModalRef = this.modalService.open(DeleteComponent, { backdrop: 'static' });
+ modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
+ if (result) {
+ this.sharedService.callData();
+ }
+ }).catch();
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="modal-header">
+ <h4 class="modal-title" id="modal-basic-title">{{titleName | translate}}</h4>
+ <button class="button-xs" type="button" class="close" (click)="activeModal.close()">
+ <i class="fas fa-times-circle text-danger"></i>
+ </button>
+</div>
+<div class="modal-body">
+ <div class="ngx-codemirror mb-2" *ngIf="defaults[mode] else noData">
+ <ngx-codemirror [options]="options" [ngModel]="defaults[mode]" [disabled]="readOnly" [autoFocus]="true">
+ </ngx-codemirror>
+ </div>
+ <ng-template #noData>{{'NODATAERROR' | translate}}
+ </ng-template>
+</div>
+<div class="modal-footer">
+ <button type="button" class="btn btn-danger" (click)="activeModal.close()">{{'CANCEL' | translate}}</button>
+</div>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file Info Ns Model
+ */
+import { HttpClient } from '@angular/common/http';
+import { Component, Injector, Input, OnInit } from '@angular/core';
+import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
+import 'codemirror/addon/dialog/dialog';
+import 'codemirror/addon/display/autorefresh';
+import 'codemirror/addon/display/fullscreen';
+import 'codemirror/addon/edit/closebrackets';
+import 'codemirror/addon/edit/matchbrackets';
+import 'codemirror/addon/fold/brace-fold';
+import 'codemirror/addon/fold/foldcode';
+import 'codemirror/addon/fold/foldgutter';
+import 'codemirror/addon/search/search';
+import 'codemirror/addon/search/searchcursor';
+import 'codemirror/keymap/sublime';
+import 'codemirror/lib/codemirror';
+import 'codemirror/mode/javascript/javascript';
+import 'codemirror/mode/markdown/markdown';
+import 'codemirror/mode/yaml/yaml';
+import { ERRORDATA, URLPARAMS } from 'CommonModel';
+import { DataService } from 'DataService';
+import { environment } from 'environment';
+import { NSDDetails } from 'NSDModel';
+import { RestService } from 'RestService';
+/** Set defaults json as type in information modal @constant */
+const defaults: {} = {
+ 'text/json': ''
+};
+/**
+ * Creating component
+ * @Component takes ShowInfoComponent.html as template url
+ */
+@Component({
+ templateUrl: './ShowInfoComponent.html',
+ styleUrls: ['./ShowInfoComponent.scss']
+})
+/** Exporting a class @exports ShowInfoComponent */
+export class ShowInfoComponent implements OnInit {
+ /** Invoke service injectors @public */
+ public injector: Injector;
+
+ /** dataService to pass the data from one component to another @public */
+ public dataService: DataService;
+
+ /** Default variables holds NS data @public */
+ public defaults: {} = defaults;
+
+ /** Varaibles to hold http client @public */
+ public httpClient: HttpClient;
+
+ /** Instance for active modal service @public */
+ public activeModal: NgbActiveModal;
+
+ /** variables readOnly holds boolean @public */
+ public readOnly: boolean = true;
+
+ /** variables to hold mode changes of editor @public */
+ public mode: string = 'text/json';
+
+ /** To Set Mode @public */
+ public modeDefault: string = 'javascript';
+
+ /** variables to hold options of editor @public */
+ public options: {} = {
+ mode: this.modeDefault,
+ showCursorWhenSelecting: true,
+ autofocus: true,
+ lineNumbers: true,
+ lineWrapping: true,
+ foldGutter: true,
+ gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
+ autoCloseBrackets: true,
+ matchBrackets: true,
+ theme: 'neat',
+ keyMap: 'sublime'
+ };
+
+ /** Reading the page Name @public */
+ public titleName: string;
+
+ /** Check the loading results @public */
+ public isLoadingResults: Boolean = false;
+
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+
+ /** Input contains component objects @private */
+ @Input() private params: URLPARAMS;
+
+ /** Instance of the rest service @private */
+ private restService: RestService;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.dataService = this.injector.get(DataService);
+ this.restService = this.injector.get(RestService);
+ this.activeModal = this.injector.get(NgbActiveModal);
+ }
+
+ /**
+ * Lifecyle Hooks the trigger before component is instantiate
+ */
+ public ngOnInit(): void {
+ this.isLoadingResults = true;
+ this.defaults['text/json'] = '';
+ this.titleName = this.params.titleName;
+ // Checks page and assign URL
+ if (this.params.page === 'ns-instance') {
+ this.restService.getResource(environment.NSINSTANCESCONTENT_URL + '/' + this.params.id).subscribe((nsData: NSDDetails[]) => {
+ this.defaults['text/json'] = JSON.stringify(nsData, null, '\t');
+ }, (error: ERRORDATA) => {
+ this.isLoadingResults = false;
+ this.restService.handleError(error, 'get');
+ }, () => {
+ this.isLoadingResults = false;
+ });
+ } else if (this.params.page === 'ns-history-operation') {
+ this.restService.getResource(environment.NSHISTORYOPERATIONS_URL + '/' +
+ this.params.id).subscribe((nsHistoryOpn: {}[]) => {
+ this.defaults['text/json'] = JSON.stringify(nsHistoryOpn, null, '\t');
+ }, (error: ERRORDATA) => {
+ this.isLoadingResults = false;
+ this.restService.handleError(error, 'get');
+ }, () => {
+ this.isLoadingResults = false;
+ });
+ } else if (this.params.page === 'vnf-instance') {
+ this.restService.getResource(environment.VNFINSTANCES_URL + '/' + this.params.id).subscribe((vnfData: {}[]) => {
+ this.defaults['text/json'] = JSON.stringify(vnfData, null, '\t');
+ }, (error: ERRORDATA) => {
+ this.isLoadingResults = false;
+ this.restService.handleError(error, 'get');
+ }, () => {
+ this.isLoadingResults = false;
+ });
+ } else if (this.params.page === 'net-slice-package') {
+ this.restService.getResource(environment.NETWORKSLICETEMPLATECONTENT_URL + '/' + this.params.id).subscribe((netSliceData: {}[]) => {
+ this.defaults['text/json'] = JSON.stringify(netSliceData, null, '\t');
+ }, (error: ERRORDATA) => {
+ this.isLoadingResults = false;
+ this.restService.handleError(error, 'get');
+ }, () => {
+ this.isLoadingResults = false;
+ });
+ } else if (this.params.page === 'net-slice-instance') {
+ this.restService.getResource(environment.NETWORKSLICEINSTANCESCONTENT_URL + '/' + this.params.id)
+ .subscribe((netSliceInstanceData: {}[]) => {
+ this.defaults['text/json'] = JSON.stringify(netSliceInstanceData, null, '\t');
+ }, (error: ERRORDATA) => {
+ this.isLoadingResults = false;
+ this.restService.handleError(error, 'get');
+ }, () => {
+ this.isLoadingResults = false;
+ });
+ } else if (this.params.page === 'nst-history-operation') {
+ this.restService.getResource(environment.NSTHISTORYOPERATIONS_URL + '/' +
+ this.params.id).subscribe((nstHistoryOpn: {}[]) => {
+ this.defaults['text/json'] = JSON.stringify(nstHistoryOpn, null, '\t');
+ }, (error: ERRORDATA) => {
+ this.isLoadingResults = false;
+ this.restService.handleError(error, 'get');
+ }, () => {
+ this.isLoadingResults = false;
+ });
+ } else if (this.params.page === 'pdu-instances') {
+ this.restService.getResource(environment.PDUINSTANCE_URL + '/' +
+ this.params.id).subscribe((pduInstanceOpn: {}[]) => {
+ this.defaults['text/json'] = JSON.stringify(pduInstanceOpn, null, '\t');
+ }, (error: ERRORDATA) => {
+ this.isLoadingResults = false;
+ this.restService.handleError(error, 'get');
+ }, () => {
+ this.isLoadingResults = false;
+ });
+ } else if (this.params.page === 'k8s-cluster') {
+ this.restService.getResource(environment.K8SCLUSTER_URL + '/' +
+ this.params.id).subscribe((k8sclusterOpn: {}[]) => {
+ this.defaults['text/json'] = JSON.stringify(k8sclusterOpn, null, '\t');
+ }, (error: ERRORDATA) => {
+ this.isLoadingResults = false;
+ this.restService.handleError(error, 'get');
+ }, () => {
+ this.isLoadingResults = false;
+ });
+ } else if (this.params.page === 'k8s-repo') {
+ this.restService.getResource(environment.K8REPOS_URL + '/' +
+ this.params.id).subscribe((k8srepoOpn: {}[]) => {
+ this.defaults['text/json'] = JSON.stringify(k8srepoOpn, null, '\t');
+ }, (error: ERRORDATA) => {
+ this.isLoadingResults = false;
+ this.restService.handleError(error, 'get');
+ }, () => {
+ this.isLoadingResults = false;
+ });
+ }
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<form [formGroup]="switchProjectForm" (ngSubmit)="switchProject()" autocomplete="off">
+ <div class="modal-header">
+ <h4 class="modal-title" id="modal-basic-title">{{'SWITCHPROJECT' | translate}}</h4>
+ <button class="button-xs" type="button" class="close" (click)="activeModal.close()">
+ <i class="fas fa-times-circle text-danger"></i>
+ </button>
+ </div>
+ <div class="modal-body">
+ <div class="form-group row">
+ <label class="col-sm-12 col-form-label mandatory-label" [ngClass]="{'text-danger': switchProjectForm.invalid === true && submitted === true}">{{'MANDATORYCHECK' | translate}}</label>
+ <label class="col-sm-6 col-form-label">{{'ENTER' | translate}} {{'PASSWORD' | translate}}*</label>
+ <div class="col-sm-6">
+ <input autocomplete="off" type="password" class="form-control" placeholder="{{'ENTER' | translate}} {{'PASSWORD' | translate}}" formControlName="password"
+ id="password" [ngClass]="{ 'is-invalid': submitted && f.password.errors }" required>
+ </div>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-danger" (click)="activeModal.close()">{{'CANCEL' | translate}}</button>
+ <button type="submit" class="btn btn-primary">{{'SUBMIT' | translate}}</button>
+ </div>
+</form>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file Switch Project Component
+ */
+import { HttpClient, HttpHeaders } from '@angular/common/http';
+import { Component, Injector, Input, OnInit } from '@angular/core';
+import { FormBuilder, FormGroup, Validators } from '@angular/forms';
+import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
+import { APIURLHEADER, ERRORDATA, LOCALSTORAGE, URLPARAMS } from 'CommonModel';
+import { DataService } from 'DataService';
+import { environment } from 'environment';
+import { RestService } from 'RestService';
+
+/**
+ * Creating component
+ * @Component takes SwitchProjectComponent.html as template url
+ */
+@Component({
+ templateUrl: './SwitchProjectComponent.html',
+ styleUrls: ['./SwitchProjectComponent.scss']
+})
+/** Exporting a class @exports SwitchProjectComponent */
+export class SwitchProjectComponent implements OnInit {
+ /** Invoke service injectors @public */
+ public injector: Injector;
+
+ /** dataService to pass the data from one component to another @public */
+ public dataService: DataService;
+
+ /** Varaibles to hold http client @public */
+ public httpClient: HttpClient;
+
+ /** Instance for active modal service @public */
+ public activeModal: NgbActiveModal;
+
+ /** FormGroup instance added to the form @ html @public */
+ public switchProjectForm: FormGroup;
+
+ /** Form submission Add */
+ public submitted: boolean = false;
+
+ /** Check the Projects loading results @public */
+ public isLoadingResults: boolean = false;
+
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+
+ /** Controls the header form @private */
+ private headers: HttpHeaders;
+
+ /** Input contains component objects @private */
+ @Input() private params: URLPARAMS;
+
+ /** Instance of the rest service @private */
+ private restService: RestService;
+
+ /** FormBuilder instance added to the formBuilder @private */
+ private formBuilder: FormBuilder;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.dataService = this.injector.get(DataService);
+ this.restService = this.injector.get(RestService);
+ this.activeModal = this.injector.get(NgbActiveModal);
+ this.formBuilder = this.injector.get(FormBuilder);
+ }
+
+ /** convenience getter for easy access to form fields */
+ get f(): FormGroup['controls'] { return this.switchProjectForm.controls; }
+
+ /**
+ * Lifecyle Hooks the trigger before component is instantiate
+ */
+ public ngOnInit(): void {
+ this.initializeForm();
+ }
+
+ /** initialize Forms @public */
+ public initializeForm(): void {
+ this.switchProjectForm = this.formBuilder.group({
+ password: ['', [Validators.required]]
+ });
+ }
+
+ /** Switch project @public */
+ public switchProject(): void {
+ this.submitted = true;
+ if (!this.switchProjectForm.invalid) {
+ this.isLoadingResults = true;
+ this.headers = new HttpHeaders({
+ 'Content-Type': 'application/json',
+ Accept: 'application/json',
+ 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
+ });
+ const payLoad: {} = JSON.stringify({
+ username: this.params.username,
+ password: this.switchProjectForm.value.password,
+ project_id: this.params.projectID
+ });
+ const apiURLHeader: APIURLHEADER = {
+ url: environment.GENERATETOKEN_URL,
+ httpOptions: { headers: this.headers }
+ };
+ this.restService.postResource(apiURLHeader, payLoad).subscribe((data: LOCALSTORAGE) => {
+ if (data) {
+ localStorage.setItem('id_token', data.id);
+ localStorage.setItem('project_id', this.params.projectID);
+ localStorage.setItem('expires', data.expires.toString());
+ localStorage.setItem('username', data.username);
+ localStorage.setItem('project', data.project_name);
+ localStorage.setItem('token_state', data.id);
+ this.activeModal.close();
+ location.reload();
+ this.isLoadingResults = false;
+ }
+ }, (error: ERRORDATA) => {
+ this.isLoadingResults = false;
+ this.restService.handleError(error, 'post');
+ this.activeModal.close();
+ });
+ }
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="btn-group list action" role="group">
+ <div ngbDropdown class="btn-group">
+ <button type="button" class="btn btn-primary dropdown-toggle action-button" ngbDropdownToggle>
+ {{'ACTION' | translate}}
+ </button>
+ <div class="dropdown-menu" ngbDropdownMenu>
+ <button type="button" class="btn btn-primary dropdown-item" (click)="editUserModal('editPassword')" placement="left" container="body"
+ ngbTooltip="{{'PAGE.USERS.EDITCREDENTIALS' | translate}}">
+ <i class="fa fa-edit icons"></i> {{'PAGE.USERS.EDITCREDENTIALS' | translate}}
+ </button>
+ <button type="button" class="btn btn-primary dropdown-item" (click)="editUserModal('editUserName')" placement="left" container="body"
+ ngbTooltip="{{'PAGE.USERS.EDITUSERNAME' | translate}}">
+ <i class="fas fa-user-edit"></i> {{'PAGE.USERS.EDITUSERNAME' | translate}}
+ </button>
+ <button type="button" class="btn btn-primary dropdown-item" (click)="projectRolesModal()" placement="left" container="body"
+ ngbTooltip="{{'PAGE.USERS.PROJECTSROLES' | translate}}">
+ <i class="fas fa-user-check"></i> {{'PAGE.USERS.PROJECTSROLES' | translate}}
+ </button>
+ <button type="button" class="btn btn-primary dropdown-item" (click)="deleteUser()" placement="left" container="body"
+ ngbTooltip="{{'DELETE' | translate}}">
+ <i class="far fa-trash-alt icons" title="delete"></i> {{'DELETE' | translate}}
+ </button>
+ </div>
+ </div>
+</div>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file Users Action Component
+ */
+import { Component, Injector } from '@angular/core';
+import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateService } from '@ngx-translate/core';
+import { AddEditUserComponent } from 'AddEditUserComponent';
+import { MODALCLOSERESPONSEDATA } from 'CommonModel';
+import { DeleteComponent } from 'DeleteComponent';
+import { ProjectRoleComponent } from 'ProjectRoleComponent';
+import { SharedService } from 'SharedService';
+import { UserData } from 'UserModel';
+/**
+ * Creating component
+ * @Component takes UsersActionComponent.html as template url
+ */
+@Component({
+ templateUrl: './UsersActionComponent.html',
+ styleUrls: ['./UsersActionComponent.scss']
+})
+/** Exporting a class @exports UsersActionComponent */
+export class UsersActionComponent {
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** To get the value from the Users action via valuePrepareFunction default Property of ng-smarttable @public */
+ public value: UserData;
+
+ /** handle translate @public */
+ public translateService: TranslateService;
+
+ /** Instance of the modal service @private */
+ private modalService: NgbModal;
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.modalService = this.injector.get(NgbModal);
+ this.sharedService = this.injector.get(SharedService);
+ this.translateService = this.injector.get(TranslateService);
+ }
+
+ /** Delete User Account @public */
+ public deleteUser(): void {
+ const modalRef: NgbModalRef = this.modalService.open(DeleteComponent, { backdrop: 'static' });
+ modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
+ if (result) {
+ this.sharedService.callData();
+ }
+ }).catch();
+ }
+
+ /** Edit User Account @public */
+ public editUserModal(editType: string): void {
+ const modalRef: NgbModalRef = this.modalService.open(AddEditUserComponent, { backdrop: 'static' });
+ modalRef.componentInstance.userID = this.value.identifier;
+ if (editType === 'editPassword') {
+ modalRef.componentInstance.userTitle = this.translateService.instant('PAGE.USERS.EDITCREDENTIALS');
+ } else {
+ modalRef.componentInstance.userTitle = this.translateService.instant('PAGE.USERS.EDITUSERNAME');
+ }
+ modalRef.componentInstance.userType = editType;
+ modalRef.componentInstance.userName = this.value.username;
+ modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
+ if (result) {
+ this.sharedService.callData();
+ }
+ }).catch();
+ }
+
+ /** Edit User Account @public */
+ public projectRolesModal(): void {
+ const modalRef: NgbModalRef = this.modalService.open(ProjectRoleComponent, { backdrop: 'static' });
+ modalRef.componentInstance.userID = this.value.identifier;
+ modalRef.componentInstance.userTitle = this.translateService.instant('PAGE.USERS.EDITPROJECTROLEMAPPING');
+ modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
+ if (result) {
+ this.sharedService.callData();
+ }
+ }).catch();
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="btn-group list action" role="group">
+ <ng-template #popTitle>
+ <span class="text-primary"><strong>{{'PAGE.DASHBOARD.RUNNINGINSTANCES' | translate}}</strong></span>
+ <button class="button-xs close" type="button" (click)="p.close()">
+ <i class="fas fa-times-circle text-danger"></i>
+ </button>
+ </ng-template>
+ <ng-template #popContent>
+ <ul class="list-group">
+ <li class="list-group-item text-left p-1 border-0" *ngFor="let instanceDetails of showInstanceDetails">
+ <a class="d-block text-truncate" target="_parent"
+ routerLink="/instances/ns/{{instanceDetails._id}}"><i class="fa-sitemap fas icons"></i> {{instanceDetails.name}}</a>
+ </li>
+ </ul>
+ </ng-template>
+ <button type="button" class="btn btn-primary" (click)="vimInfo()" placement="top" container="body"
+ ngbTooltip="{{'INFO' | translate}}">
+ <i class="fas fa-info icons"></i>
+ </button>
+ <button type="button" class="btn btn-primary" (click)="deleteVIMAccount()" placement="top" container="body"
+ ngbTooltip="{{'DELETE' | translate}}">
+ <i class="far fa-trash-alt icons"></i>
+ </button>
+ <button type="button" placement="left" container="body" [ngbPopover]="popContent" triggers="manual" #p="ngbPopover"
+ (click)="p.open()" [autoClose]="'outside'" [popoverTitle]="popTitle" class="btn btn-primary"
+ popoverClass="runninginstances" [disabled]="!showMapIcon">
+ <i class="fas fa-layer-group"></i>
+ </button>
+</div>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file Vim AccountsAction Component
+ */
+import { Component, Injector, OnInit } from '@angular/core';
+import { Router } from '@angular/router';
+import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
+import { MODALCLOSERESPONSEDATA } from 'CommonModel';
+import { DeleteComponent } from 'DeleteComponent';
+import { NSInstanceDetails } from 'NSInstanceModel';
+import { SharedService } from 'SharedService';
+import { VIMData } from 'VimAccountModel';
+
+/**
+ * Creating component
+ * @Component takes VimAccountsActionComponent.html as template url
+ */
+@Component({
+ selector: 'app-vim-accounts-action',
+ templateUrl: './VimAccountsActionComponent.html',
+ styleUrls: ['./VimAccountsActionComponent.scss']
+})
+/** Exporting a class @exports VimAccountsActionComponent */
+export class VimAccountsActionComponent implements OnInit {
+ /** To get the value from the vimAccounts via valuePrepareFunction default Property of ng-smarttable @public */
+ public value: VIMData;
+
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** To show Instances running @public */
+ public showMapIcon: boolean = false;
+
+ /** To show Details Instances running @public */
+ public showInstanceDetails: {}[];
+
+ /** Instance of the modal service @private */
+ private modalService: NgbModal;
+
+ /** Holds teh instance of AuthService class of type AuthService @private */
+ private router: Router;
+
+ /** Variables holds NS ID @private */
+ private vimID: string;
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.modalService = this.injector.get(NgbModal);
+ this.router = this.injector.get(Router);
+ this.sharedService = this.injector.get(SharedService);
+ }
+ /** Lifecyle Hooks the trigger before component is instantiate @public */
+ public ngOnInit(): void {
+ this.getInstancesDetails();
+ }
+
+ /** Delete VIM Account @public */
+ public deleteVIMAccount(): void {
+ const modalRef: NgbModalRef = this.modalService.open(DeleteComponent, {backdrop: 'static'});
+ modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
+ if (result) {
+ this.sharedService.callData();
+ }
+ }).catch();
+ }
+
+ /** On navigate to Info VimAccount @public */
+ public vimInfo(): void {
+ this.vimID = this.value.identifier;
+ this.router.navigate(['/vim/info', this.vimID]).catch(() => {
+ // Catch Navigation Error
+ });
+ }
+
+ /** To show the Instances Info for the particular VimAccount @public */
+ public getInstancesDetails(): void {
+ this.showInstanceDetails = [];
+ this.value.instancesData.filter((item: NSInstanceDetails) => {
+ if (item.datacenter === this.value.identifier) {
+ this.showMapIcon = true;
+ this.showInstanceDetails.push(item);
+ }
+ });
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="btn-group list action" role="group">
+ <button type="button" (click)="infoVNF()" class="btn btn-primary" placement="top" container="body"
+ ngbTooltip="{{'VNFR' | translate}}">
+ <i class="fas fa-info icons"></i>
+ </button>
+</div>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file VNF-instancesAction Component
+ */
+import { Component, Injector } from '@angular/core';
+import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
+import { ShowInfoComponent } from 'ShowInfoComponent';
+import { VNFInstanceData } from 'VNFInstanceModel';
+/**
+ * Creating component
+ * @Component takes VNFInstancesActionComponent.html as template url
+ */
+@Component({
+ templateUrl: './VNFInstancesActionComponent.html',
+ styleUrls: ['./VNFInstancesActionComponent.scss']
+})
+/** Exporting a class @exports VNFInstancesActionComponent */
+export class VNFInstancesActionComponent {
+ /** To get the value from the vnfpackage via valuePrepareFunction default Property of ng-smarttable @public */
+ public value: VNFInstanceData;
+
+ /** Invoke service injectors @public */
+ public injector: Injector;
+
+ /** Instance of the modal service @private */
+ private modalService: NgbModal;
+
+ /** Contains instance ID @private */
+ private instanceID: string;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.modalService = this.injector.get(NgbModal);
+ }
+
+ /**
+ * Lifecyle Hooks the trigger before component is instantiate
+ */
+ public ngOnInit(): void {
+ this.instanceID = this.value.identifier;
+ }
+
+ /** Shows information using modalservice @public */
+ public infoVNF(): void {
+ this.modalService.open(ShowInfoComponent, { backdrop: 'static' }).componentInstance.params = {
+ id: this.instanceID,
+ page: 'vnf-instance',
+ titleName: 'INSTANCEDETAILS'
+ };
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="btn-group list action" role="group">
+ <button type="button" class="btn btn-primary" placement="top" container="body" (click)="composeVNFPackages()"
+ ngbTooltip="{{'TOPOLOGY' | translate}}">
+ <i class="fa fa-sitemap fa-fw Icon"></i>
+ </button>
+ <button type="button" class="btn btn-primary" (click)="deleteVNFPackage()" placement="top" container="body"
+ ngbTooltip="{{'DELETE' | translate}}">
+ <i class="far fa-trash-alt icons"></i>
+ </button>
+ <div ngbDropdown class="btn-group">
+ <button type="button" class="btn btn-primary dropdown-toggle action-button" ngbDropdownToggle>
+ {{'ACTION' | translate}}
+ </button>
+ <div class="dropdown-menu" ngbDropdownMenu>
+ <button type="button" class="btn btn-primary dropdown-item" (click)="vnfdEdit()" placement="left"
+ container="body" ngbTooltip="{{'EDIT' | translate}}">
+ <i class="fa fa-edit icons"></i> {{'EDIT' | translate}}
+ </button>
+ <button type="button" class="btn btn-primary dropdown-item" (click)="downloadVNFPackage()" placement="left"
+ container="body" ngbTooltip="{{'DOWNLOAD' | translate}}">
+ <i class="fas fa-download icons"></i> {{'DOWNLOAD' | translate}}
+ </button>
+ <button type="button" class="btn btn-primary dropdown-item" (click)="cloneVNFPackage()" placement="left"
+ container="body" ngbTooltip="{{'CLONE' | translate}}">
+ <i class="fa fa-clone icons"></i> {{'CLONE' | translate}}
+ </button>
+ <button type="button" class="btn btn-primary dropdown-item" (click)="showContent()" placement="left"
+ container="body" ngbTooltip="{{'CONTENT' | translate}}">
+ <i class="far fa-folder-open icons"></i> {{'CONTENT' | translate}}
+ </button>
+ </div>
+ </div>
+</div>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingDownloadResult"></app-loader>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file VNF-packagesAction Component
+ */
+import { HttpHeaders } from '@angular/common/http';
+import { ChangeDetectorRef, Component, Injector } from '@angular/core';
+import { Router } from '@angular/router';
+import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateService } from '@ngx-translate/core';
+import { NotifierService } from 'angular-notifier';
+import { ClonePackageComponent } from 'ClonePackage';
+import { ERRORDATA, GETAPIURLHEADER, MODALCLOSERESPONSEDATA } from 'CommonModel';
+import { DeleteComponent } from 'DeleteComponent';
+import { environment } from 'environment';
+import { RestService } from 'RestService';
+import { SharedService } from 'SharedService';
+import { ShowContentComponent } from 'ShowContent';
+import { VNFData } from 'VNFDModel';
+
+/**
+ * Creating component
+ * @Component takes VNFPackagesActionComponent.html as template url
+ */
+@Component({
+ templateUrl: './VNFPackagesActionComponent.html',
+ styleUrls: ['./VNFPackagesActionComponent.scss']
+})
+/** Exporting a class @exports VNFPackagesActionComponent */
+export class VNFPackagesActionComponent {
+ /** To get the value from the vnfpackage via valuePrepareFunction default Property of ng-smarttable @public */
+ public value: VNFData;
+
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** Check the loading results for loader status @public */
+ public isLoadingDownloadResult: boolean = false;
+
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+
+ /** Instance of the rest service @private */
+ private restService: RestService;
+
+ /** Holds teh instance of AuthService class of type AuthService @private */
+ private router: Router;
+
+ /** Instance of the modal service @private */
+ private modalService: NgbModal;
+
+ /** Variables holds NS ID @private */
+ private vnfID: string;
+
+ /** Variables holds NS name @private */
+ private vnfName: string;
+
+ /** Controls the header form @private */
+ private headers: HttpHeaders;
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ /** Notifier service to popup notification @private */
+ private notifierService: NotifierService;
+
+ /** Contains tranlsate instance @private */
+ private translateService: TranslateService;
+
+ /** Detect changes for the User Input */
+ private cd: ChangeDetectorRef;
+
+ /** Set timeout @private */
+ private timeOut: number = 1000;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.restService = this.injector.get(RestService);
+ this.sharedService = this.injector.get(SharedService);
+ this.modalService = this.injector.get(NgbModal);
+ this.router = this.injector.get(Router);
+ this.notifierService = this.injector.get(NotifierService);
+ this.translateService = this.injector.get(TranslateService);
+ this.cd = this.injector.get(ChangeDetectorRef);
+ }
+
+ /**
+ * Lifecyle Hooks the trigger before component is instantiate
+ */
+ public ngOnInit(): void {
+ this.headers = new HttpHeaders({
+ Accept: 'application/zip, application/json',
+ 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
+ });
+ this.vnfID = this.value.identifier;
+ this.vnfName = this.value.shortName;
+ }
+
+ /** Delete VNF packages @public */
+ public deleteVNFPackage(): void {
+ const modalRef: NgbModalRef = this.modalService.open(DeleteComponent, { backdrop: 'static' });
+ modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
+ if (result) {
+ this.sharedService.callData();
+ }
+ }).catch();
+ }
+
+ /** Set instance for NSD Edit @public */
+ public vnfdEdit(): void {
+ this.router.navigate(['/packages/vnf/edit/', this.vnfID]).then((nav: {}) => {
+ // Navigated Successfully
+ }, (error: Error) => {
+ // Navigation Error Handler
+ });
+ }
+
+ /** list out all the file content of a descriptors @public */
+ public showContent(): void {
+ this.modalService.open(ShowContentComponent, { backdrop: 'static' }).componentInstance.params = { id: this.vnfID, page: 'vnfd' };
+ }
+
+ /** Download VNF Package @public */
+ public downloadVNFPackage(): void {
+ this.isLoadingDownloadResult = true;
+ const httpOptions: GETAPIURLHEADER = {
+ headers: this.headers,
+ responseType: 'blob'
+ };
+ this.restService.getResource(environment.VNFPACKAGES_URL + '/' + this.vnfID + '/package_content', httpOptions)
+ .subscribe((response: Blob) => {
+ this.isLoadingDownloadResult = false;
+ this.changeDetactionforDownload();
+ const binaryData: Blob[] = [];
+ binaryData.push(response);
+ this.sharedService.downloadFiles(this.vnfName, binaryData, response.type);
+ }, (error: ERRORDATA) => {
+ this.isLoadingDownloadResult = false;
+ this.notifierService.notify('error', this.translateService.instant('ERROR'));
+ this.changeDetactionforDownload();
+ if (typeof error.error === 'object') {
+ error.error.text().then((data: string): void => {
+ error.error = JSON.parse(data);
+ this.restService.handleError(error, 'getBlob');
+ });
+ }
+ });
+ }
+
+ /** Compose VNF Packages @public */
+ public composeVNFPackages(): void {
+ this.router.navigate(['/packages/vnf/compose/', this.vnfID]).catch();
+ }
+
+ /** Change the detaction @public */
+ public changeDetactionforDownload(): void {
+ setTimeout(() => {
+ this.cd.detectChanges();
+ }, this.timeOut);
+ }
+
+ /** Clone NS Packages @public */
+ public cloneVNFPackage(): void {
+ const cloneModal: NgbModalRef = this.modalService.open(ClonePackageComponent, { backdrop: 'static' });
+ cloneModal.componentInstance.params = { id: this.vnfID, page: 'vnfd', name: this.vnfName };
+ cloneModal.result.then((result: MODALCLOSERESPONSEDATA) => {
+ if (result) {
+ this.sharedService.callData();
+ }
+ }).catch();
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="btn-group list action" role="group">
+ <button type="button" class="btn btn-primary" (click)="showWIMAccountInfo()" placement="top" container="body"
+ ngbTooltip="{{'INFO' | translate}}">
+ <i class="fas fa-info icons"></i>
+ </button>
+ <button type="button" class="btn btn-primary" (click)="deleteWIMAccount()" placement="top" container="body"
+ ngbTooltip="{{'DELETE' | translate}}">
+ <i class="far fa-trash-alt icons"></i>
+ </button>
+</div>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file WIM AccountsAction Component
+ */
+import { Component, Injector } from '@angular/core';
+import { Router } from '@angular/router';
+import { NgbActiveModal, NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
+import { MODALCLOSERESPONSEDATA } from 'CommonModel';
+import { DeleteComponent } from 'DeleteComponent';
+import { SharedService } from 'SharedService';
+import { WIMAccountInfoComponent } from 'WIMAccountInfo';
+import { WIMValue } from 'WIMAccountModel';
+
+/**
+ * Creating component
+ * @Component takes WIMAccountsActionComponent.html as template url
+ */
+@Component({
+ templateUrl: './WIMAccountsActionComponent.html',
+ styleUrls: ['./WIMAccountsActionComponent.scss']
+})
+/** Exporting a class @exports WIMAccountsActionComponent */
+export class WIMAccountsActionComponent {
+ /** To get the value from the vnfpackage via valuePrepareFunction default Property of ng-smarttable @public */
+ public value: WIMValue;
+
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** Instance of the modal service @private */
+ private modalService: NgbModal;
+
+ /** Variables holds WIM ID @private */
+ private wimID: string;
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.modalService = this.injector.get(NgbModal);
+ this.sharedService = this.injector.get(SharedService);
+ }
+
+ /** Lifecyle Hooks the trigger before component is instantiate @public */
+ public ngOnInit(): void {
+ this.wimID = this.value.identifier;
+ }
+
+ /** Show WIM account information @public */
+ public showWIMAccountInfo(): void {
+ this.modalService.open(WIMAccountInfoComponent, { backdrop: 'static' }).componentInstance.params = {
+ id: this.wimID,
+ page: 'wim-accounts'
+ };
+ }
+
+ /** Delete WIM Account @public */
+ public deleteWIMAccount(): void {
+ const modalRef: NgbModalRef = this.modalService.open(DeleteComponent, { backdrop: 'static' });
+ modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
+ if (result) {
+ this.sharedService.callData();
+ }
+ }).catch();
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<router-outlet></router-outlet>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file Vim Account Component.
+ */
+import { Component, Injector } from '@angular/core';
+import { Router, RouterEvent } from '@angular/router';
+
+/**
+ * Creating component
+ * @Component takes VimAccountsComponent.html as template url
+ */
+@Component({
+ selector: 'app-vim-accounts',
+ templateUrl: './VimAccountsComponent.html',
+ styleUrls: ['./VimAccountsComponent.scss']
+})
+/** Exporting a class @exports VimAccountsComponent */
+export class VimAccountsComponent {
+ /** Invoke service injectors @public */
+ public injector: Injector;
+
+ /** Holds teh instance of AuthService class of type AuthService @private */
+ private router: Router;
+
+ // creates packages component
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.router = this.injector.get(Router);
+ this.router.events.subscribe((event: RouterEvent) => {
+ this.redirectToList(event.url);
+ });
+ }
+
+ /** Return to list NS Package List */
+ public redirectToList(getURL: string): void {
+ if (getURL === '/vim') {
+ this.router.navigate(['/vim/details']).catch();
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file Vim Account module.
+ */
+import { CommonModule } from '@angular/common';
+import { HttpClientModule } from '@angular/common/http';
+import { NgModule } from '@angular/core';
+import { FormsModule } from '@angular/forms';
+import { ReactiveFormsModule } from '@angular/forms';
+import { RouterModule, Routes } from '@angular/router';
+import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
+import { NgSelectModule } from '@ng-select/ng-select';
+import { TranslateModule } from '@ngx-translate/core';
+import { DataService } from 'DataService';
+import { InfoVimComponent } from 'InfoVim';
+import { LoaderModule } from 'LoaderModule';
+import { NewVimaccountComponent } from 'NewVimaccount';
+import { Ng2SmartTableModule } from 'ng2-smart-table';
+import { PagePerRowModule } from 'PagePerRowModule';
+import { PageReloadModule } from 'PageReloadModule';
+import { VimAccountDetailsComponent } from 'VimAccountDetails';
+import { VimAccountsComponent } from 'VimAccountsComponent';
+
+/** To halndle project information */
+const projectInfo: {} = { title: '{project}', url: '/' };
+
+/** const values for dashboard Routes */
+const routes: Routes = [
+ {
+ path: '',
+ component: VimAccountsComponent,
+ children: [
+ {
+ path: 'details',
+ data: {
+ breadcrumb: [{ title: 'PAGE.DASHBOARD.DASHBOARD', url: '/' }, { title: 'PAGE.DASHBOARD.PROJECTS', url: '/projects' },
+ projectInfo, { title: 'VIMACCOUNTS', url: null }]
+ },
+ component: VimAccountDetailsComponent
+ },
+ {
+ path: 'info/:id',
+ data: {
+ breadcrumb: [{ title: 'PAGE.DASHBOARD.DASHBOARD', url: '/' }, { title: 'PAGE.DASHBOARD.PROJECTS', url: '/projects' },
+ projectInfo, { title: 'VIMACCOUNTS', url: '/vim/details' }, { title: '{id}', url: null }]
+ },
+ component: InfoVimComponent
+ },
+ {
+ path: 'new',
+ data: {
+ breadcrumb: [{ title: 'PAGE.DASHBOARD.DASHBOARD', url: '/' }, { title: 'PAGE.DASHBOARD.PROJECTS', url: '/projects' },
+ projectInfo, { title: 'VIMACCOUNTS', url: '/vim/details' }, { title: 'PAGE.VIMDETAILS.NEWVIM', url: null }]
+ },
+ component: NewVimaccountComponent
+ }
+ ]
+ }
+];
+
+/**
+ * Creating @NgModule component for Modules
+ */
+@NgModule({
+ imports: [ReactiveFormsModule.withConfig({ warnOnNgModelWithFormControl: 'never' }), FormsModule, CommonModule,
+ HttpClientModule, NgSelectModule, Ng2SmartTableModule, TranslateModule, RouterModule.forChild(routes), NgbModule,
+ PagePerRowModule, LoaderModule, PageReloadModule],
+ declarations: [VimAccountsComponent, InfoVimComponent, VimAccountDetailsComponent, NewVimaccountComponent],
+ providers: [DataService],
+ entryComponents: [InfoVimComponent]
+})
+/** Exporting a class @exports VimAccountsModule */
+export class VimAccountsModule {
+ /** Variables declared to avoid state-less class */
+ private vimModule: string;
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="row d-flex flex-row justify-content-between">
+ <div class="d-flex align-items-center header-style">{{'PAGE.VIMDETAILS.VIMACCOUNTDETAILS' | translate}}</div>
+</div>
+<div class="context-style bg-white mt-2 vim-details">
+ <div class="row">
+ <div class="col-sm-6 text-dark mb-2 font-weight-bold" *ngFor="let details of vimDetails">
+ <label class="col-sm-5 col-form-label">{{ details.title | translate}}</label>
+ <span class="col-sm-5">{{details.value}}</span>
+ </div>
+ </div>
+</div>
+<div class="col-12">
+ <button type="button" class="btn btn-block border-0 bg-light text-dark" (click)="isCollapsed = !isCollapsed"
+ [attr.aria-expanded]="!isCollapsed">
+ {{'PAGE.VIMDETAILS.CONFIGPARAMETERS' | translate}}
+ </button>
+</div>
+<div id="demo" class="collapse context-style p-2" [ngbCollapse]="isCollapsed">
+ <div class="row">
+ <div class="col-sm-6 text-dark mb-2 font-weight-bold" *ngFor="let details of configParams">
+ <label class="col-sm-5 col-form-label">{{ details.title | translate}}:</label>
+ <span class="col-sm-5"> {{(details.value !== undefined)?details.value : '--'}} </span>
+ </div>
+ </div>
+</div>
+<div class="modal-footer list">
+ <button (click)="onVimAccountBack()"
+ class="btn btn-danger pull-right">{{'PAGE.VIMDETAILS.BACKTOVIMACCOUNTS' | translate}}</button>
+</div>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file Info VIM Page
+ */
+import { Component, Injector, OnInit } from '@angular/core';
+import { ActivatedRoute, Router } from '@angular/router';
+import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
+import { ERRORDATA } from 'CommonModel';
+import { DataService } from 'DataService';
+import { environment } from 'environment';
+import * as HttpStatus from 'http-status-codes';
+import { RestService } from 'RestService';
+import { isNullOrUndefined } from 'util';
+import { CONFIG, VimAccountDetails, VIMData } from 'VimAccountModel';
+
+/**
+ * Creating component
+ * @Component InfoVimComponent.html as template url
+ */
+@Component({
+ selector: 'app-info-vim',
+ templateUrl: './InfoVimComponent.html',
+ styleUrls: ['./InfoVimComponent.scss']
+})
+/** Exporting a class @exports InfoVimComponent */
+export class InfoVimComponent implements OnInit {
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** vimAccountDetails to populate in InfoVIM Page @private */
+ public vimAccountDetails: VimAccountDetails;
+
+ /** Information Top Left @public */
+ public configParams: {}[] = [];
+
+ /** Showing more details of collapase */
+ public isCollapsed: boolean = true;
+
+ /** Contains vim details @public */
+ public vimDetails: {}[];
+
+ /** Check the Projects loading results @public */
+ public isLoadingResults: boolean = false;
+
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+
+ /** variables contains paramsID @private */
+ private paramsID: string;
+
+ /** Instance of the rest service @private */
+ private restService: RestService;
+
+ /** Holds the instance of router class @private */
+ private router: Router;
+
+ /** dataService to pass the data from one component to another @private */
+ private dataService: DataService;
+
+ /** vimId to populate in InfoVIM Page @private */
+ private vimId: string;
+
+ /** Holds teh instance of AuthService class of type AuthService @private */
+ private activatedRoute: ActivatedRoute;
+
+ /** Utilizes modal service for any modal operations @private */
+ private modalService: NgbModal;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.restService = this.injector.get(RestService);
+ this.dataService = this.injector.get(DataService);
+ this.activatedRoute = this.injector.get(ActivatedRoute);
+ this.modalService = this.injector.get(NgbModal);
+ this.router = this.injector.get(Router);
+ }
+
+ /**
+ * Lifecyle Hooks the trigger before component is instantiate
+ */
+ public ngOnInit(): void {
+ // tslint:disable-next-line:no-backbone-get-set-outside-model
+ this.paramsID = this.activatedRoute.snapshot.paramMap.get('id');
+ this.dataService.currentMessage.subscribe((data: VIMData) => {
+ this.vimId = data.identifier;
+ });
+ this.generateData();
+ }
+
+ /** Routing to VIM Account Details Page @public */
+ public onVimAccountBack(): void {
+ this.router.navigate(['vim/details']).catch(() => {
+ // Error Cached
+ });
+ }
+
+ /** Generate Data function @public */
+ public generateData(): void {
+ this.isLoadingResults = true;
+ this.restService.getResource(environment.VIMACCOUNTS_URL + '/' + this.paramsID)
+ .subscribe((vimAccountsData: VimAccountDetails) => {
+ this.showDetails(vimAccountsData);
+ if (vimAccountsData.config !== undefined) {
+ if (vimAccountsData.vim_type === 'openstack') {
+ this.showOpenstackConfig(vimAccountsData.config);
+ } else if (vimAccountsData.vim_type === 'aws') {
+ this.awsConfig(vimAccountsData.config);
+ } else if (vimAccountsData.vim_type === 'openvim' || vimAccountsData.vim_type === 'opennebula') {
+ this.openVIMOpenNebulaConfig(vimAccountsData.config);
+ } else if (vimAccountsData.vim_type === 'vmware') {
+ this.vmwareConfig(vimAccountsData.config);
+ } else if (vimAccountsData.vim_type === 'azure') {
+ this.azureConfig(vimAccountsData.config);
+ }
+ }
+ this.isLoadingResults = false;
+ }, (error: ERRORDATA) => {
+ this.isLoadingResults = false;
+ if (error.error.status === HttpStatus.NOT_FOUND || error.error.status === HttpStatus.UNAUTHORIZED) {
+ this.router.navigateByUrl('404', { skipLocationChange: true }).catch();
+ } else {
+ this.restService.handleError(error, 'get');
+ }
+ });
+ }
+
+ /** show general vim detailed information @public */
+ public showDetails(vimAccountsData: VimAccountDetails): void {
+ this.vimDetails = [
+ {
+ title: 'PAGE.VIMDETAILS.NAME',
+ value: vimAccountsData.name
+ },
+ {
+ title: 'PAGE.VIMDETAILS.VIMUSERNAME',
+ value: vimAccountsData.vim_user
+ },
+ {
+ title: 'PAGE.VIMDETAILS.VIMURL',
+ value: vimAccountsData.vim_url
+ },
+ {
+ title: 'PAGE.VIMDETAILS.VIMTYPE',
+ value: vimAccountsData.vim_type
+ },
+ {
+ title: 'PAGE.VIMDETAILS.TENANTNAME',
+ value: vimAccountsData.vim_tenant_name
+ },
+ {
+ title: 'PAGE.VIMDETAILS.DESCRIPTION',
+ value: vimAccountsData.description
+ },
+ {
+ title: 'PAGE.VIMDETAILS.SCHEMATYPE',
+ value: vimAccountsData.schema_type
+ },
+ {
+ title: 'PAGE.VIMDETAILS.SCHEMAVERSION',
+ value: vimAccountsData.schema_version
+ }
+ ];
+ }
+
+ /** Openstack Config @public */
+ public showOpenstackConfig(config: CONFIG): void {
+ if (!isNullOrUndefined(config)) {
+ Object.keys(config).forEach((key: string) => {
+ if (Array.isArray(config[key])) {
+ config[key] = JSON.stringify(config[key]);
+ }
+ });
+ }
+ let location: string = config.location;
+ if (!isNullOrUndefined(location)) {
+ const locationArr: string[] = config.location.split(',');
+ if (Array.isArray(locationArr)) {
+ location = locationArr[0];
+ }
+ }
+
+ this.configParams = [
+ {
+ title: 'PAGE.VIMDETAILS.SDNCONTROLLER',
+ value: config.sdn_controller
+ },
+ {
+ title: 'PAGE.VIMDETAILS.SDNPORTMAPPING',
+ value: config.sdn_port_mapping
+ },
+ {
+ title: 'PAGE.VIMDETAILS.VIMNETWORKNAME',
+ value: config.vim_network_name
+ },
+ {
+ title: 'PAGE.VIMDETAILS.SECURITYGROUPS',
+ value: config.security_groups
+ },
+ {
+ title: 'PAGE.VIMDETAILS.AVAILABILITYZONE',
+ value: config.availabilityZone
+ },
+ {
+ title: 'PAGE.VIMDETAILS.REGIONALNAME',
+ value: config.region_name
+ },
+ {
+ title: 'PAGE.VIMDETAILS.INSECURE',
+ value: config.insecure
+ },
+ {
+ title: 'PAGE.VIMDETAILS.USEEXISTINGFLAVOURS',
+ value: config.use_existing_flavors
+ },
+ {
+ title: 'PAGE.VIMDETAILS.USEINTERNALENDPOINT',
+ value: config.use_internal_endpoint
+ },
+ {
+ title: 'PAGE.VIMDETAILS.ADDITIONALCONFIG',
+ value: config.additional_conf
+ },
+ {
+ title: 'PAGE.VIMDETAILS.APIVERSION',
+ value: config.APIversion
+ },
+ {
+ title: 'PAGE.VIMDETAILS.PROJECTDOMAINID',
+ value: config.project_domain_id
+ },
+ {
+ title: 'PAGE.VIMDETAILS.PROJECTDOMAINNAME',
+ value: config.project_domain_name
+ },
+ {
+ title: 'PAGE.VIMDETAILS.USERDOMAINID',
+ value: config.user_domain_id
+ },
+ {
+ title: 'PAGE.VIMDETAILS.USERDOMAINUSER',
+ value: config.user_domain_name
+ },
+ {
+ title: 'PAGE.VIMDETAILS.KEYPAIR',
+ value: config.keypair
+ },
+ {
+ title: 'PAGE.VIMDETAILS.DATAPLANEPHYSICALNET',
+ value: config.dataplane_physical_net
+ },
+ {
+ title: 'PAGE.VIMDETAILS.USEFLOATINGIP',
+ value: config.use_floating_ip
+ },
+ {
+ title: 'PAGE.VIMDETAILS.MICROVERSION',
+ value: config.microversion
+ },
+ {
+ title: 'PAGE.VIMDETAILS.VIMLOCATION',
+ value: location
+ }
+ ];
+ }
+
+ /** AWS Config @public */
+ public awsConfig(config: CONFIG): void {
+ this.configParams = [
+ {
+ title: 'PAGE.VIMDETAILS.SDNCONTROLLER',
+ value: config.sdn_controller
+ },
+ {
+ title: 'PAGE.VIMDETAILS.VPCCIDRBLOCK',
+ value: config.vpc_cidr_block
+ },
+ {
+ title: 'PAGE.VIMDETAILS.SDNPORTMAPPING',
+ value: config.sdn_port_mapping
+ },
+ {
+ title: 'PAGE.VIMDETAILS.SECURITYGROUPS',
+ value: config.security_groups
+ },
+ {
+ title: 'PAGE.VIMDETAILS.VIMNETWORKNAME',
+ value: config.vim_network_name
+ },
+ {
+ title: 'PAGE.VIMDETAILS.KEYPAIR',
+ value: config.keypair
+ },
+ {
+ title: 'PAGE.VIMDETAILS.REGIONALNAME',
+ value: config.region_name
+ },
+ {
+ title: 'PAGE.VIMDETAILS.FLAVORIINFO',
+ value: config.flavor_info
+ },
+ {
+ title: 'PAGE.VIMDETAILS.ADDITIONALCONFIG',
+ value: config.additional_conf
+ }
+ ];
+ }
+
+ /** Open vim and open nebula config @public */
+ public openVIMOpenNebulaConfig(config: CONFIG): void {
+ this.configParams = [
+ {
+ title: 'PAGE.VIMDETAILS.SDNCONTROLLER',
+ value: config.sdn_controller
+ },
+ {
+ title: 'PAGE.VIMDETAILS.SDNPORTMAPPING',
+ value: config.sdn_port_mapping
+ },
+ {
+ title: 'PAGE.VIMDETAILS.VIMNETWORKNAME',
+ value: config.vim_network_name
+ },
+ {
+ title: 'PAGE.VIMDETAILS.ADDITIONALCONFIG',
+ value: config.additional_conf
+ }
+ ];
+ }
+
+ /** vmware config @public */
+ public vmwareConfig(config: CONFIG): void {
+ this.configParams = [
+ {
+ title: 'PAGE.VIMDETAILS.SDNCONTROLLER',
+ value: config.sdn_controller
+ },
+ {
+ title: 'PAGE.VIMDETAILS.ORGNAME',
+ value: config.orgname
+ },
+ {
+ title: 'PAGE.VIMDETAILS.SDNPORTMAPPING',
+ value: config.sdn_port_mapping
+ },
+ {
+ title: 'PAGE.VIMDETAILS.VCENTERIP',
+ value: config.vcenter_ip
+ },
+ {
+ title: 'PAGE.VIMDETAILS.VIMNETWORKNAME',
+ value: config.vim_network_name
+ },
+ {
+ title: 'PAGE.VIMDETAILS.VCENTERPORT',
+ value: config.vcenter_port
+ },
+ {
+ title: 'PAGE.VIMDETAILS.ADMINUSERNAME',
+ value: config.admin_username
+ },
+ {
+ title: 'PAGE.VIMDETAILS.VCENTERUSER',
+ value: config.vcenter_user
+ },
+ {
+ title: 'PAGE.VIMDETAILS.ADMINPASSWORD',
+ value: config.admin_password
+ },
+ {
+ title: 'PAGE.VIMDETAILS.VCENTERPASSWORD',
+ value: config.vcenter_password
+ },
+ {
+ title: 'PAGE.VIMDETAILS.NSXMANAGER',
+ value: config.nsx_manager
+ },
+ {
+ title: 'PAGE.VIMDETAILS.VROPSSITE',
+ value: config.vrops_site
+ },
+ {
+ title: 'PAGE.VIMDETAILS.NSXUSER',
+ value: config.nsx_user
+ },
+ {
+ title: 'PAGE.VIMDETAILS.VROPSUSER',
+ value: config.vrops_user
+ },
+ {
+ title: 'PAGE.VIMDETAILS.NSXPASSWORD',
+ value: config.nsx_password
+ },
+ {
+ title: 'PAGE.VIMDETAILS.VROPSPASSWORD',
+ value: config.vrops_password
+ },
+ {
+ title: 'PAGE.VIMDETAILS.ADDITIONALCONFIG',
+ value: config.additional_conf
+ }
+ ];
+ }
+
+ /** Azure Config @public */
+ public azureConfig(config: CONFIG): void {
+ this.configParams = [
+ {
+ title: 'PAGE.VIMDETAILS.SUBSCRIPTIONID',
+ value: config.subscription_id
+ },
+ {
+ title: 'PAGE.VIMDETAILS.REGIONALNAME',
+ value: config.region_name
+ },
+ {
+ title: 'PAGE.VIMDETAILS.RESOURCEGROUP',
+ value: config.resource_group
+ },
+ {
+ title: 'PAGE.VIMDETAILS.VNETNAME',
+ value: config.vnet_name
+ },
+ {
+ title: 'PAGE.VIMDETAILS.FLAVORSPATTERN',
+ value: config.flavors_pattern
+ }
+ ];
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<form [formGroup]="vimNewAccountForm" (ngSubmit)="newVimAccountSubmit()" autocomplete="off">
+ <div class="row d-flex flex-row justify-content-between">
+ <div class="d-flex align-items-center header-style">{{'PAGE.VIMDETAILS.NEWVIMACCOUNT' | translate}} </div>
+ </div>
+ <div class="context-style bg-white p-3">
+ <div class="row form-group content-style">
+ <label class="col-sm-12 col-form-label mandatory-label"
+ [ngClass]="{'text-danger': vimNewAccountForm.invalid === true && submitted === true}">{{'MANDATORYCHECK' | translate}}</label>
+ <div class="col-sm-3">
+ <label for="name">{{'PAGE.VIMDETAILS.NAME' | translate}}*</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control" placeholder="{{'PAGE.VIMDETAILS.NAME' | translate}}"
+ type="text" formControlName="name" id="name"
+ [ngClass]="{ 'is-invalid': submitted && f.name.errors }">
+ </div>
+ <div class="col-sm-3">
+ <label for="vim_tenant_name">{{'PAGE.VIMDETAILS.TENANTNAME' | translate}}*</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.TENANTNAME' | translate}}" type="text"
+ formControlName="vim_tenant_name" id="vim_tenant_name"
+ [ngClass]="{ 'is-invalid': submitted && f.vim_tenant_name.errors }">
+ </div>
+ </div>
+ <div class="row form-group content-style">
+ <div class="col-sm-3">
+ <label for="vim_type">{{'PAGE.VIMDETAILS.VIMTYPE' | translate}}*</label>
+ </div>
+ <div class="col-sm-3">
+ <ng-select bindLabel="title" bindValue="value" [items]="vimType" placeholder="{{'SELECT' | translate}}"
+ formControlName="vim_type" id="vim_type" [(ngModel)]="selectedVimType"
+ [ngClass]="{ 'is-invalid': submitted && f.vim_type.errors }">
+ </ng-select>
+ </div>
+ <div class="col-sm-3">
+ <label for="description">{{'PAGE.VIMDETAILS.DESCRIPTION' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <textarea class="form-control" placeholder="{{'PAGE.VIMDETAILS.DESCRIPTION' | translate}}" type="text"
+ formControlName="description" id="description"></textarea>
+ </div>
+ </div>
+ <div class="row form-group content-style">
+ <div class="col-sm-3">
+ <label for="vim_url">{{'PAGE.VIMDETAILS.VIMURL' | translate}}*</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control" placeholder="{{'PAGE.VIMDETAILS.VIMURL' | translate}}"
+ type="url" formControlName="vim_url" id="vim_url"
+ [ngClass]="{ 'is-invalid': submitted && f.vim_url.errors }">
+ <div *ngIf="vimNewAccountForm.invalid" class="invalid-feedback">
+ <div *ngIf="f.vim_url.errors && f.vim_url.value">{{'DOMVALIDATIONS.INVALIDURL' | translate}}</div>
+ </div>
+ </div>
+ <div class="col-sm-3">
+ <label for="schema_type">{{'PAGE.VIMDETAILS.SCHEMATYPE' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.SCHEMATYPE' | translate}}" type="text" formControlName="schema_type"
+ id="schema_type">
+ </div>
+ </div>
+ <div class="row form-group content-style">
+ <div class="col-sm-3">
+ <label for="vim_user">{{'PAGE.VIMDETAILS.VIMUSERNAME' | translate}}*</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.VIMUSERNAME' | translate}}" type="text" formControlName="vim_user"
+ id="vim_user" [ngClass]="{ 'is-invalid': submitted && f.vim_user.errors }">
+ </div>
+ </div>
+ <div class="row form-group content-style">
+ <div class="col-sm-3">
+ <label for="vim_password">{{'PAGE.VIMDETAILS.VIMPASSWORD' | translate}}*</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control" placeholder="VIM Password" type="password"
+ formControlName="vim_password" id="vim_password"
+ [ngClass]="{ 'is-invalid': submitted && f.vim_password.errors }">
+ </div>
+ </div>
+ <div class="row" [hidden]="!selectedVimType">
+ <div class="col-12">
+ <button type="button" class="btn btn-block border-0 bg-light text-dark"
+ (click)="isCollapsed = !isCollapsed"
+ [attr.aria-expanded]="!isCollapsed">{{'PAGE.VIMDETAILS.CONFIGPARAMETERS' | translate}}</button>
+ </div>
+ </div>
+ <div formGroupName="vimconfig" id="configurationparameters" class="collapse mt-3" [ngbCollapse]="isCollapsed">
+ <div class="row" [hidden]="!selectedVimType">
+ <div class="col-sm-3">
+ <label>{{'UPLOADCONFIG' | translate}}</label>
+ </div>
+ <div class="col-sm-3 form-group">
+ <div class="custom-file">
+ <input type="file" #fileInput class="custom-file-input"
+ (change)="filesDropped($event.target.files)" id="customFile">
+ <label class="custom-file-label" #fileInputLabel
+ for="customFile">{{'CHOOSEFILE' | translate}}</label>
+ </div>
+ </div>
+ </div>
+ <div *ngIf="selectedVimType == 'openstack'">
+ <div class="row form-group content-style">
+ <div class="col-sm-3">
+ <label for="sdn_controller">{{'PAGE.VIMDETAILS.SDNCONTROLLER' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.SDNCONTROLLER' | translate}}" type="text"
+ formControlName="sdn_controller" id="sdn_controller">
+ </div>
+ <div class="col-sm-3">
+ <label for="APIversion">{{'PAGE.VIMDETAILS.APIVERSION' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.APIVERSION' | translate}}" type="text"
+ formControlName="APIversion" id="APIversion">
+ </div>
+ </div>
+ <div class="row form-group content-style">
+ <div class="col-sm-3">
+ <label for="sdn_port_mapping">{{'PAGE.VIMDETAILS.SDNPORTMAPPING' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.SDNPORTMAPPING' | translate}}" type="text"
+ formControlName="sdn_port_mapping" id="sdn_port_mapping">
+ </div>
+ <div class="col-sm-3">
+ <label for="project_domain_id">{{'PAGE.VIMDETAILS.PROJECTDOMAINID' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.PROJECTDOMAINID' | translate}}" type="text"
+ formControlName="project_domain_id" id="project_domain_id">
+ </div>
+ </div>
+ <div class="row form-group content-style">
+ <div class="col-sm-3">
+ <label for="vim_network_name">{{'PAGE.VIMDETAILS.VIMNETWORKNAME' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.VIMNETWORKNAME' | translate}}" type="text"
+ formControlName="vim_network_name" id="vim_network_name">
+ </div>
+ <div class="col-sm-3">
+ <label for="project_domain_name">{{'PAGE.VIMDETAILS.PROJECTDOMAINNAME' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.PROJECTDOMAINNAME' | translate}}" type="text"
+ formControlName="project_domain_name" id="project_domain_name">
+ </div>
+ </div>
+ <div class="row form-group content-style">
+ <div class="col-sm-3">
+ <label for="config_vim_ype">{{'PAGE.VIMDETAILS.VIMTYPE' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.VIM_TYPE' | translate}}" type="text"
+ formControlName="config_vim_ype" id="config_vim_ype">
+ </div>
+ <div class="col-sm-3">
+ <label for="user_domain_id">{{'PAGE.VIMDETAILS.USERDOMAINID' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.USERDOMAINID' | translate}}" type="text"
+ formControlName="user_domain_id" id="user_domain_id">
+ </div>
+ </div>
+ <div class="row form-group content-style">
+ <div class="col-sm-3">
+ <label for="security_groups">{{'PAGE.VIMDETAILS.SECURITYGROUPS' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.SECURITYGROUPS' | translate}}" type="text"
+ formControlName="security_groups" id="security_groups">
+ </div>
+ <div class="col-sm-3">
+ <label for="user_domain_name">{{'PAGE.VIMDETAILS.USERDOMAINUSER' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.USERDOMAINUSER' | translate}}" type="text"
+ formControlName="user_domain_name" id="user_domain_name">
+ </div>
+ </div>
+ <div class="row form-group content-style">
+ <div class="col-sm-3">
+ <label for="availabilityZone">{{'PAGE.VIMDETAILS.AVAILABILITYZONE' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.AVAILABILITYZONE' | translate}}" type="text"
+ formControlName="availabilityZone" id="availabilityZone">
+ </div>
+ <div class="col-sm-3">
+ <label for="keypair">{{'PAGE.VIMDETAILS.KEYPAIR' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.KEYPAIR' | translate}}" type="text"
+ formControlName="keypair" id="keypair">
+ </div>
+ </div>
+ <div class="row form-group content-style">
+ <div class="col-sm-3">
+ <label for="region_name">{{'PAGE.VIMDETAILS.REGIONALNAME' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.REGIONALNAME' | translate}}" type="text"
+ formControlName="region_name" id="region_name">
+ </div>
+ <div class="col-sm-3">
+ <label
+ for="dataplane_physical_net">{{'PAGE.VIMDETAILS.DATAPLANEPHYSICALNET' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.DATAPLANEPHYSICALNET' | translate}}" type="text"
+ formControlName="dataplane_physical_net" id="dataplane_physical_net">
+ </div>
+ </div>
+ <div class="row form-group content-style">
+ <div class="col-sm-3">
+ <label for="insecure">{{'PAGE.VIMDETAILS.INSECURE' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <ng-select [items]="boolValue" bindLabel="name" bindValue="id"
+ placeholder="{{'PAGE.VIMDETAILS.INSECURE' | translate}}" formControlName="insecure"
+ id="insecure">
+ </ng-select>
+ </div>
+ <div class="col-sm-3">
+ <label for="use_floating_ip">{{'PAGE.VIMDETAILS.USEFLOATINGIP' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <ng-select [items]="boolValue" bindLabel="name" bindValue="id" id="use_floating_ip"
+ placeholder="{{'PAGE.VIMDETAILS.USEFLOATINGIP' | translate}}"
+ formControlName="use_floating_ip">
+ </ng-select>
+ </div>
+ </div>
+ <div class="row form-group content-style">
+ <div class="col-sm-3">
+ <label for="use_internal_endpoint">{{'PAGE.VIMDETAILS.USEINTERNALENDPOINT' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <ng-select [items]="boolValue" bindLabel="name" bindValue="id"
+ placeholder="{{'PAGE.VIMDETAILS.USEINTERNALENDPOINT' | translate}}"
+ formControlName="use_internal_endpoint" id="use_internal_endpoint">
+ </ng-select>
+ </div>
+ <div class="col-sm-3">
+ <label for="microversion">{{'PAGE.VIMDETAILS.MICROVERSION' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.MICROVERSION' | translate}}" type="text"
+ formControlName="microversion" id="microversion">
+ </div>
+ </div>
+ <div class="row form-group content-style">
+ <div class="col-sm-3">
+ <label for="additional_conf">{{'PAGE.VIMDETAILS.ADDITIONALCONFIG' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.ADDITIONALCONFIGPLACEHOLDER' | translate}}" type="text"
+ formControlName="additional_conf" id="additional_conf">
+ </div>
+ <div class="col-sm-3">
+ <label for="use_existing_flavors">{{'PAGE.VIMDETAILS.USEEXISTINGFLAVOURS' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <ng-select [items]="boolValue" bindLabel="name" bindValue="id"
+ placeholder="{{'PAGE.VIMDETAILS.USEEXISTINGFLAVOURS' | translate}}"
+ formControlName="use_existing_flavors" id="use_existing_flavors">
+ </ng-select>
+ </div>
+ </div>
+ <div class="row form-group content-style">
+ <div class="col-sm-3">
+ <label for="location">{{'PAGE.VIMDETAILS.VIMLOCATION' | translate}}</label>
+ </div>
+ <div class="col-sm-9">
+ <ng-select [items]="getVIMLocation" bindLabel="label" bindValue="value"
+ placeholder="{{'PAGE.VIMDETAILS.VIMLOCATION' | translate}}" formControlName="location"
+ id="location" (keydown.enter)="fetchLocationLatLong($event.target.value)">
+ </ng-select>
+ <small>{{'PAGE.VIM.LOACTIONINFO' | translate}}</small>
+ </div>
+ </div>
+ </div>
+ <div *ngIf="selectedVimType == 'openvim' || selectedVimType == 'opennebula'">
+ <div class="row form-group content-style">
+ <div class="col-sm-3">
+ <label for="sdn_controller">{{'PAGE.VIMDETAILS.SDNCONTROLLER' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.SDNCONTROLLER' | translate}}" type="text"
+ formControlName="sdn_controller" id="sdn_controller">
+ </div>
+ </div>
+ <div class="row form-group content-style">
+ <div class="col-sm-3">
+ <label for="sdn_port_mapping">{{'PAGE.VIMDETAILS.SDNPORTMAPPING' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.SDNPORTMAPPING' | translate}}" type="text"
+ formControlName="sdn_port_mapping" id="sdn_port_mapping">
+ </div>
+ </div>
+ <div class="row form-group content-style">
+ <div class="col-sm-3">
+ <label for="vim_network_name">{{'PAGE.VIMDETAILS.VIMNETWORKNAME' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.VIMNETWORKNAME' | translate}}" type="text"
+ formControlName="vim_network_name" id="vim_network_name">
+ </div>
+ </div>
+ <div class="row form-group content-style">
+ <div class="col-sm-3">
+ <label for="additional_conf">{{'PAGE.VIMDETAILS.ADDITIONALCONFIG' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.ADDITIONALCONFIGPLACEHOLDER' | translate}}" type="text"
+ formControlName="additional_conf" id="additional_conf">
+ </div>
+ </div>
+ </div>
+ <div *ngIf="selectedVimType == 'vmware'">
+ <div class="row form-group content-style">
+ <div class="col-sm-3">
+ <label for="sdn_controller">{{'PAGE.VIMDETAILS.SDNCONTROLLER' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.SDNCONTROLLER' | translate}}" type="text"
+ formControlName="sdn_controller" id="sdn_controller">
+ </div>
+ <div class="col-sm-3">
+ <label for="orgname">{{'PAGE.VIMDETAILS.ORGNAME' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.ORGNAME' | translate}}" type="text"
+ formControlName="orgname" id="orgname">
+ </div>
+ </div>
+ <div class="row form-group content-style">
+ <div class="col-sm-3">
+ <label for="sdn_port_mapping">{{'PAGE.VIMDETAILS.SDNPORTMAPPING' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.SDNPORTMAPPING' | translate}}" type="text"
+ formControlName="sdn_port_mapping" id="sdn_port_mapping">
+ </div>
+ <div class="col-sm-3">
+ <label for="vcenter_ip">{{'PAGE.VIMDETAILS.VCENTERIP' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.VCENTERIP' | translate}}" type="text"
+ formControlName="vcenter_ip" id="vcenter_ip">
+ </div>
+ </div>
+ <div class="row form-group content-style">
+ <div class="col-sm-3">
+ <label for="vim_network_name">{{'PAGE.VIMDETAILS.VIMNETWORKNAME' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.VIMNETWORKNAME' | translate}}" type="text"
+ formControlName="vim_network_name" id="vim_network_name">
+ </div>
+ <div class="col-sm-3">
+ <label for="vcenter_port">{{'PAGE.VIMDETAILS.VCENTERPORT' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.VCENTERPORT' | translate}}" type="text"
+ formControlName="vcenter_port" id="vcenter_port">
+ </div>
+ </div>
+ <div class="row form-group content-style">
+ <div class="col-sm-3">
+ <label for="admin_username">{{'PAGE.VIMDETAILS.ADMINUSERNAME' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.ADMINUSERNAME' | translate}}" type="text"
+ formControlName="admin_username" id="admin_username">
+ </div>
+ <div class="col-sm-3">
+ <label for="vcenter_user">{{'PAGE.VIMDETAILS.VCENTERUSER' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.VCENTERUSER' | translate}}" type="text"
+ formControlName="vcenter_user" id="vcenter_user">
+ </div>
+ </div>
+ <div class="row form-group content-style">
+ <div class="col-sm-3">
+ <label for="admin_password">{{'PAGE.VIMDETAILS.ADMINPASSWORD' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.ADMINPASSWORD' | translate}}" type="text"
+ formControlName="admin_password" id="admin_password">
+ </div>
+ <div class="col-sm-3">
+ <label for="vcenter_password">{{'PAGE.VIMDETAILS.VCENTERPASSWORD' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.VCENTERPASSWORD' | translate}}" type="text"
+ formControlName="vcenter_password" id="vcenter_password">
+ </div>
+ </div>
+ <div class="row form-group content-style">
+ <div class="col-sm-3">
+ <label for="nsx_manager">{{'PAGE.VIMDETAILS.NSXMANAGER' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.NSXMANAGER' | translate}}" type="text"
+ formControlName="nsx_manager" id="nsx_manager">
+ </div>
+ <div class="col-sm-3">
+ <label for="vrops_site">{{'PAGE.VIMDETAILS.VROPSSITE' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.VROPSSITE' | translate}}" type="text"
+ formControlName="vrops_site" id="vrops_site">
+ </div>
+ </div>
+ <div class="row form-group content-style">
+ <div class="col-sm-3">
+ <label for="nsx_user">{{'PAGE.VIMDETAILS.NSXUSER' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.NSXUSER' | translate}}" type="text"
+ formControlName="nsx_user" id="nsx_user">
+ </div>
+ <div class="col-sm-3">
+ <label for="vrops_user">{{'PAGE.VIMDETAILS.VROPSUSER' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.VROPSUSER' | translate}}" type="text"
+ formControlName="vrops_user" id="vrops_user">
+ </div>
+ </div>
+ <div class="row form-group content-style">
+ <div class="col-sm-3">
+ <label for="nsx_password">{{'PAGE.VIMDETAILS.NSXPASSWORD' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.NSXPASSWORD' | translate}}" type="text"
+ formControlName="nsx_password" id="nsx_password">
+ </div>
+ <div class="col-sm-3">
+ <label for="vrops_password">{{'PAGE.VIMDETAILS.VROPSPASSWORD' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.VROPSPASSWORD' | translate}}" type="text"
+ formControlName="vrops_password" id="vrops_password">
+ </div>
+ </div>
+ <div class="row form-group content-style">
+ <div class="col-sm-3">
+ <label for="additional_conf">{{'PAGE.VIMDETAILS.ADDITIONALCONFIG' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.ADDITIONALCONFIGPLACEHOLDER' | translate}}" type="text"
+ formControlName="additional_conf" id="additional_conf">
+ </div>
+ </div>
+ </div>
+ <div *ngIf="selectedVimType == 'aws'">
+ <div class="row form-group content-style">
+ <div class="col-sm-3">
+ <label for="sdn_controller">{{'PAGE.VIMDETAILS.SDNCONTROLLER' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.SDNCONTROLLER' | translate}}" type="text"
+ formControlName="sdn_controller" id="sdn_controller">
+ </div>
+ <div class="col-sm-3">
+ <label for="vpc_cidr_block">{{'PAGE.VIMDETAILS.VPCCIDRBLOCK' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.VPCCIDRBLOCK' | translate}}" type="text"
+ formControlName="vpc_cidr_block" id="vpc_cidr_block">
+ </div>
+ </div>
+ <div class="row form-group content-style">
+ <div class="col-sm-3">
+ <label for="sdn_port_mapping">{{'PAGE.VIMDETAILS.SDNPORTMAPPING' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.SDNPORTMAPPING' | translate}}" type="text"
+ formControlName="sdn_port_mapping" id="sdn_port_mapping">
+ </div>
+ <div class="col-sm-3">
+ <label for="security_groups">{{'PAGE.VIMDETAILS.SECURITYGROUPS' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.SECURITYGROUPS' | translate}}" type="text"
+ formControlName="security_groups" id="security_groups">
+ </div>
+ </div>
+ <div class="row form-group content-style">
+ <div class="col-sm-3">
+ <label for="vim_network_name">{{'PAGE.VIMDETAILS.VIMNETWORKNAME' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.VIMNETWORKNAME' | translate}}" type="text"
+ formControlName="vim_network_name" id="vim_network_name">
+ </div>
+ <div class="col-sm-3">
+ <label for="keypair">{{'PAGE.VIMDETAILS.KEYPAIR' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.KEYPAIR' | translate}}" type="text"
+ formControlName="keypair" id="keypair">
+ </div>
+ </div>
+ <div class="row form-group content-style">
+ <div class="col-sm-3">
+ <label for="region_name">{{'PAGE.VIMDETAILS.REGIONALNAME' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.REGIONALNAME' | translate}}" type="text"
+ formControlName="region_name" id="region_name">
+ </div>
+ <div class="col-sm-3">
+ <label for="flavor_info">{{'PAGE.VIMDETAILS.FLAVORIINFO' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.FLAVORIINFO' | translate}}" type="text"
+ formControlName="flavor_info" id="flavor_info">
+ </div>
+ </div>
+ <div class="row form-group content-style">
+ <div class="col-sm-3">
+ <label for="additional_conf">{{'PAGE.VIMDETAILS.ADDITIONALCONFIG' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.ADDITIONALCONFIGPLACEHOLDER' | translate}}" type="text"
+ formControlName="additional_conf" id="additional_conf">
+ </div>
+ </div>
+ </div>
+ <div *ngIf="selectedVimType == 'azure'">
+ <div class="row form-group content-style">
+ <div class="col-sm-3">
+ <label for="subscription_id">{{'PAGE.VIMDETAILS.SUBSCRIPTIONID' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.SUBSCRIPTIONID' | translate}}" type="text"
+ formControlName="subscription_id" id="subscription_id">
+ </div>
+ <div class="col-sm-3">
+ <label for="region_name">{{'PAGE.VIMDETAILS.REGIONALNAME' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.REGIONALNAME' | translate}}" type="text"
+ formControlName="region_name" id="region_name">
+ </div>
+ </div>
+ <div class="row form-group content-style">
+ <div class="col-sm-3">
+ <label for="resource_group">{{'PAGE.VIMDETAILS.RESOURCEGROUP' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.RESOURCEGROUP' | translate}}" type="text"
+ formControlName="resource_group" id="resource_group">
+ </div>
+ <div class="col-sm-3">
+ <label for="vnet_name">{{'PAGE.VIMDETAILS.VNETNAME' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.VNETNAME' | translate}}" type="text"
+ formControlName="vnet_name" id="vnet_name">
+ </div>
+ </div>
+ <div class="row form-group content-style">
+ <div class="col-sm-3">
+ <label for="flavors_pattern">{{'PAGE.VIMDETAILS.FLAVORSPATTERN' | translate}}</label>
+ </div>
+ <div class="col-sm-3">
+ <input autocomplete="off" class="form-control"
+ placeholder="{{'PAGE.VIMDETAILS.FLAVORSPATTERN' | translate}}" type="text"
+ formControlName="flavors_pattern" id="flavors_pattern">
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <button type="button" (click)="onVimAccountBack()"
+ class="btn btn-danger">{{'PAGE.VIMDETAILS.BACKTOVIMACCOUNTS' | translate}}</button>
+ <button type="submit" class="btn btn-primary">{{'CREATE' | translate}}</button>
+ </div>
+</form>
+<app-loader [waitingMessage]="message" *ngIf="isLocationLoadingResults"></app-loader>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file Vim Account Component.
+ */
+import { HttpHeaders } from '@angular/common/http';
+import { Component, ElementRef, Injector, OnInit, ViewChild } from '@angular/core';
+import { FormBuilder, FormGroup, Validators } from '@angular/forms';
+import { Router } from '@angular/router';
+import { TranslateService } from '@ngx-translate/core';
+import { NotifierService } from 'angular-notifier';
+import { APIURLHEADER, ERRORDATA, TYPESECTION, VIM_TYPES } from 'CommonModel';
+import { environment } from 'environment';
+import * as jsyaml from 'js-yaml';
+import { RestService } from 'RestService';
+import { SharedService } from 'SharedService';
+import { isNullOrUndefined } from 'util';
+import { FEATURES, VIMLOCATION, VIMLOCATIONDATA } from 'VimAccountModel';
+
+/**
+ * Creating component
+ * @Component takes NewVimaccountComponent.html as template url
+ */
+@Component({
+ selector: 'app-new-vimaccount',
+ templateUrl: './NewVimaccountComponent.html',
+ styleUrls: ['./NewVimaccountComponent.scss']
+})
+/** Exporting a class @exports NewVimaccountComponent */
+export class NewVimaccountComponent implements OnInit {
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** FormGroup vim New Account added to the form @ html @public */
+ public vimNewAccountForm: FormGroup;
+
+ /** Supported Vim type for the dropdown */
+ public vimType: TYPESECTION[];
+
+ /** Supported Vim type for the dropdown */
+ public selectedVimType: string;
+
+ /** Supported true and false value for the dropdown */
+ public boolValue: {}[];
+
+ /** Form submission Add */
+ public submitted: boolean = false;
+
+ /** Showing more details of collapase */
+ public isCollapsed: boolean = false;
+
+ /** Vim location values @public */
+ public getVIMLocation: VIMLOCATIONDATA[] = [];
+
+ /** Check the Projects loading results @public */
+ public isLocationLoadingResults: boolean = false;
+
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+
+ /** set the longitude value of the selected place @public */
+ public setLong: number;
+
+ /** set the latitude value of the selected place @public */
+ public setLat: number;
+
+ /** Element ref for fileInput @public */
+ @ViewChild('fileInput', { static: true }) public fileInput: ElementRef;
+
+ /** Element ref for fileInput @public */
+ @ViewChild('fileInputLabel', { static: true }) public fileInputLabel: ElementRef;
+
+ /** Instance of the rest service @private */
+ private restService: RestService;
+
+ /** Holds the instance of router class @private */
+ private router: Router;
+
+ /** Controls the header form @private */
+ private headers: HttpHeaders;
+
+ /** FormBuilder instance added to the formBuilder @private */
+ private formBuilder: FormBuilder;
+
+ /** Notifier service to popup notification @private */
+ private notifierService: NotifierService;
+
+ /** Contains tranlsate instance @private */
+ private translateService: TranslateService;
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ /** Contains configuration key variables @private */
+ private configKeys: string[] = [];
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.restService = this.injector.get(RestService);
+ this.formBuilder = this.injector.get(FormBuilder);
+ this.router = this.injector.get(Router);
+ this.notifierService = this.injector.get(NotifierService);
+ this.translateService = this.injector.get(TranslateService);
+ this.sharedService = this.injector.get(SharedService);
+
+ /** Initializing Form Action */
+ this.vimNewAccountForm = this.formBuilder.group({
+ name: [null, Validators.required],
+ vim_type: [null, Validators.required],
+ vim_tenant_name: [null, Validators.required],
+ description: [null],
+ vim_url: [null, [Validators.required, Validators.pattern(this.sharedService.REGX_URL_PATTERN)]],
+ schema_type: [''],
+ vim_user: [null, Validators.required],
+ vim_password: [null, Validators.required],
+ vimconfig: this.paramsBuilder()
+ });
+ }
+
+ /** Generate params for config @public */
+ public paramsBuilder(): FormGroup {
+ return this.formBuilder.group({
+ use_existing_flavors: [null],
+ location: [null],
+ sdn_controller: [null],
+ APIversion: [null],
+ sdn_port_mapping: [null],
+ project_domain_id: [null],
+ vim_network_name: [null],
+ project_domain_name: [null],
+ config_vim_ype: [null],
+ user_domain_id: [null],
+ security_groups: [null],
+ user_domain_name: [null],
+ availabilityZone: [null],
+ keypair: [null],
+ region_name: [null],
+ dataplane_physical_net: [null],
+ insecure: [null],
+ use_floating_ip: [null],
+ microversion: [null],
+ use_internal_endpoint: [null],
+ additional_conf: [null],
+ orgname: [null],
+ vcenter_ip: [null],
+ vcenter_port: [null],
+ admin_username: [null],
+ vcenter_user: [null],
+ admin_password: [null],
+ vcenter_password: [null],
+ nsx_manager: [null],
+ vrops_site: [null],
+ nsx_user: [null],
+ vrops_user: [null],
+ nsx_password: [null],
+ vrops_password: [null],
+ vpc_cidr_block: [null],
+ flavor_info: [null],
+ subscription_id: [null],
+ resource_group: [null],
+ vnet_name: [null],
+ flavors_pattern: [null]
+ });
+ }
+
+ /** convenience getter for easy access to form fields */
+ get f(): FormGroup['controls'] { return this.vimNewAccountForm.controls; }
+
+ /**
+ * Lifecyle Hooks the trigger before component is instantiate
+ */
+ public ngOnInit(): void {
+ this.vimType = VIM_TYPES;
+ this.boolValue = [
+ { id: '', name: 'None' },
+ { id: true, name: 'True' },
+ { id: false, name: 'False' }
+ ];
+ this.headers = new HttpHeaders({
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
+ });
+ }
+
+ /** On modal submit newVimAccountSubmit will called @public */
+ public newVimAccountSubmit(): void {
+ this.submitted = true;
+ if (!this.vimNewAccountForm.invalid) {
+ this.isLocationLoadingResults = true;
+ this.configKeys.forEach((key: string) => {
+ this.vimNewAccountForm.controls.vimconfig.get(key).setValue(JSON.parse(this.vimNewAccountForm.controls.vimconfig.get(key).value));
+ });
+ this.sharedService.cleanForm(this.vimNewAccountForm);
+ Object.keys(this.vimNewAccountForm.value.vimconfig).forEach((key: string) => {
+ if (this.vimNewAccountForm.value.vimconfig[key] === undefined || this.vimNewAccountForm.value.vimconfig[key] === null ||
+ this.vimNewAccountForm.value.vimconfig[key] === '') {
+ delete this.vimNewAccountForm.value.vimconfig[key];
+ }
+ });
+ this.vimNewAccountForm.value.config = this.vimNewAccountForm.value.vimconfig;
+ delete this.vimNewAccountForm.value.vimconfig;
+ const apiURLHeader: APIURLHEADER = {
+ url: environment.VIMACCOUNTS_URL,
+ httpOptions: { headers: this.headers }
+ };
+ this.restService.postResource(apiURLHeader, this.vimNewAccountForm.value)
+ .subscribe((result: {}) => {
+ this.notifierService.notify('success', this.translateService.instant('PAGE.VIM.CREATEDSUCCESSFULLY'));
+ this.isLocationLoadingResults = false;
+ this.router.navigate(['vim/details']).catch(() => {
+ // Error Cached;
+ });
+ // Post the New Vim data and reflect in the VIM Details Page.
+ }, (error: ERRORDATA) => {
+ this.configKeys.forEach((key: string) => {
+ this.vimNewAccountForm.controls.vimconfig.get(key)
+ .setValue(JSON.stringify(this.vimNewAccountForm.controls.vimconfig.get(key).value));
+ });
+ this.restService.handleError(error, 'post');
+ this.isLocationLoadingResults = false;
+ });
+ }
+ }
+
+ /** Routing to VIM Account Details Page @public */
+ public onVimAccountBack(): void {
+ this.router.navigate(['vim/details']).catch(() => {
+ // Error Cached
+ });
+ }
+
+ /** Fetching the location with name,latitude,longitude @public */
+ public fetchLocationLatLong(value: string): void {
+ this.isLocationLoadingResults = true;
+ const newVIMLocation: VIMLOCATIONDATA[] = [];
+ const locationTrack: string = environment.MAPLATLONGAPI_URL;
+ const locationAPIURL: string = locationTrack.replace('{value}', value);
+ this.restService.getResource(locationAPIURL).subscribe((result: VIMLOCATION) => {
+ result.features.forEach((getFeturesResult: FEATURES) => {
+ if ('extent' in getFeturesResult.properties) {
+ getFeturesResult.properties.extent.forEach((extentResult: number, index: number) => {
+ if (index === 0) {
+ this.setLong = extentResult;
+ }
+ if (index === 1) {
+ this.setLat = extentResult;
+ }
+ });
+ } else {
+ getFeturesResult.geometry.coordinates.forEach((coordinateResult: number, index: number) => {
+ if (index === 0) {
+ this.setLong = coordinateResult;
+ }
+ if (index === 1) {
+ this.setLat = coordinateResult;
+ }
+ });
+ }
+ newVIMLocation.push({
+ label: getFeturesResult.properties.name + ',' + getFeturesResult.properties.state + ', ' + getFeturesResult.properties.country,
+ value: getFeturesResult.properties.name + ',' + this.setLong + ',' + this.setLat
+ });
+ });
+ this.getVIMLocation = newVIMLocation;
+ this.isLocationLoadingResults = false;
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'get');
+ this.isLocationLoadingResults = false;
+ });
+ }
+
+ /** Drag and drop feature and fetchind the details of files @private */
+ public filesDropped(files: FileList): void {
+ this.configKeys = [];
+ if (files && files.length === 1) {
+ this.sharedService.getFileString(files, 'yaml').then((fileContent: string): void => {
+ const getJson: string = jsyaml.load(fileContent, { json: true });
+ Object.keys(getJson).forEach((item: string) => {
+ if (!isNullOrUndefined(this.vimNewAccountForm.controls.vimconfig.get(item))) {
+ if (typeof getJson[item] === 'object') {
+ // tslint:disable-next-line: no-backbone-get-set-outside-model
+ this.vimNewAccountForm.controls.vimconfig.get(item).setValue(JSON.stringify(getJson[item]));
+ this.configKeys.push(item);
+ } else {
+ // tslint:disable-next-line: no-backbone-get-set-outside-model
+ this.vimNewAccountForm.controls.vimconfig.get(item).setValue(getJson[item]);
+ }
+ }
+ });
+ }).catch((err: string): void => {
+ if (err === 'typeError') {
+ this.notifierService.notify('error', this.translateService.instant('YAMLFILETYPEERRROR'));
+ } else {
+ this.notifierService.notify('error', this.translateService.instant('ERROR'));
+ }
+ this.fileInputLabel.nativeElement.innerText = this.translateService.instant('CHOOSEFILE');
+ this.fileInput.nativeElement.value = null;
+ });
+ } else if (files && files.length > 1) {
+ this.notifierService.notify('error', this.translateService.instant('DROPFILESVALIDATION'));
+ }
+ this.fileInputLabel.nativeElement.innerText = files[0].name;
+ this.fileInput.nativeElement.value = null;
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="row d-flex align-items-center justify-content-between">
+ <div class="col-sm-4">
+ <div class="d-flex align-items-center header-style">{{'VIMACCOUNTS' | translate}}</div>
+ </div>
+ <div class="col-sm-8 text-right">
+ <div class="btn-group list mr-2" role="group">
+ <button class="btn btn-primary" type="button" (click)="mapView()" placement="top" container="body"
+ ngbTooltip="{{'MAPVIEW' | translate}}" [hidden]="showList" [disabled]="vimData.length == 0">
+ <i class="fas fa-map-marker-alt"></i>
+ {{'MAPVIEW' | translate}}
+ </button>
+ <button class="btn btn-primary" type="button" (click)="listView()" placement="top" container="body"
+ ngbTooltip="{{'LISTVIEW' | translate}}" [hidden]="showMap">
+ <i class="fas fa-list"></i>
+ {{'LISTVIEW' | translate}}
+ </button>
+ </div>
+ <span class="button">
+ <button class="btn btn-primary" type="button" placement="top" container="body"
+ ngbTooltip="{{'PAGE.VIMDETAILS.NEWVIM' | translate}}" (click)="composeVIM()">
+ <i class="fas fa-plus-circle" aria-hidden="true"></i>
+ {{'PAGE.VIMDETAILS.NEWVIM' | translate}}
+ </button>
+ </span>
+ </div>
+</div>
+<div class="row mt-2 mb-0 list-utilites-actions" [hidden]="showList">
+ <div class="col-auto mr-auto">
+ <nav class="custom-items-config">
+ <span><i class="fas fa-clock text-warning"></i>{{operationalStateFirstStep}}</span>
+ <span><i class="fas fa-check-circle text-success"></i>{{operationalStateSecondStep}}</span>
+ <span><i class="fas fa-times-circle text-danger"></i>{{operationalStateThirdStep}}</span>
+ </nav>
+ </div>
+ <page-per-row class="mr-2" (pagePerRow)="onChange($event)"></page-per-row>
+ <page-reload></page-reload>
+</div>
+<div class="smarttable-style bg-white mt-1" [hidden]="showList">
+ <ng2-smart-table [ngClass]="checkDataClass" [settings]="settings" [source]="dataSource" (userRowSelect)="onUserRowSelect($event)">
+ </ng2-smart-table>
+</div>
+<br>
+<div id="map" class="row map" [hidden]="showMap"></div>
+<div id="popup" class="ol-popup" [hidden]="!popupShow">
+ <button id="popup-closer" class="button-xs close m-1" type="button" aria-label="Close">
+ <i class="fas fa-times-circle text-danger"></i>
+ </button>
+ <div id="popup-content" [innerHTML]="popupData"></div>
+</div>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+@import '../../../assets/scss/mixins/mixin';
+@import '../../../assets/scss/variable';
+.map {
+ height: 60vh;
+ width: 100%;
+ .ol-popup {
+ @include background(null, $white, null, null, null);
+ -webkit-filter: drop-shadow(0 1px 4px rgba(0,0,0,0.2));
+ filter: drop-shadow(0 1px 4px rgba(0,0,0,0.2));
+ @include border(all, 1, solid, $gray-80);
+ @include position_value(absolute, $top: null, $right: null, $bottom: 12px, $left: -50px);
+ @include wh-value(280px, null);
+ @include font-style(normal);
+ @include font(null, .765625rem, 400);
+ @include line-height(1.5);
+ text-align: start;
+ text-decoration: none;
+ letter-spacing: normal;
+ word-break: normal;
+ word-spacing: normal;
+ white-space: normal;
+ line-break: auto;
+ word-wrap: break-word;
+ @include roundedCorners(2px);
+ &:after, &:before{
+ top: 100%;
+ @include border(all, 1, solid, transparent);
+ content: " ";
+ height: 0;
+ width: 0;
+ position: absolute;
+ pointer-events: none;
+ }
+ &:after {
+ border-top-color: $white;
+ border-width: 10px;
+ left: 48px;
+ margin-left: -10px;
+ }
+ &:before {
+ border-top-color: $gray-80;
+ border-width: 11px;
+ left: 48px;
+ margin-left: -11px;
+ }
+ }
+ .ol-popup-closer {
+ text-decoration: none;
+ position: absolute;
+ top: 2px;
+ right: 8px;
+ &:after {
+ content: "✖";
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file Vim Account Component.
+ */
+import { Component, Injector, OnInit } from '@angular/core';
+import { Router } from '@angular/router';
+import { TranslateService } from '@ngx-translate/core';
+import { CONFIGCONSTANT, CONSTANTNUMBER, ERRORDATA, VIM_TYPES } from 'CommonModel';
+import { DataService } from 'DataService';
+import { environment } from 'environment';
+import { LocalDataSource } from 'ng2-smart-table';
+import { NSInstanceDetails } from 'NSInstanceModel';
+import Feature from 'ol/Feature';
+import Point from 'ol/geom/Point';
+import { defaults as defaultInteractions } from 'ol/interaction';
+import { Tile as TileLayer, Vector as VectorLayer } from 'ol/layer';
+import Map from 'ol/Map';
+import Overlay from 'ol/Overlay';
+import { fromLonLat } from 'ol/proj.js';
+import OSM from 'ol/source/OSM';
+import VectorSource from 'ol/source/Vector';
+import { Icon, Style } from 'ol/style';
+import View from 'ol/View';
+import { RestService } from 'RestService';
+import { Subscription } from 'rxjs';
+import { SharedService } from 'SharedService';
+import { VimAccountDetails, VIMData } from 'VimAccountModel';
+import { VimAccountsActionComponent } from 'VimAccountsAction';
+/**
+ * Creating component
+ * @Component takes VimAccountDetailsComponent.html as template url
+ */
+@Component({
+ selector: 'app-vim-account-details',
+ templateUrl: './VimAccountDetailsComponent.html',
+ styleUrls: ['./VimAccountDetailsComponent.scss']
+})
+/** Exporting a class @exports VimAccountDetailsComponent */
+export class VimAccountDetailsComponent implements OnInit {
+ /** To inject services @public */
+ public injector: Injector;
+ /** handle translate @public */
+ public translateService: TranslateService;
+ /** initially show the map container@public */
+ public showMap: boolean;
+ /** hide and show popup @public */
+ public popupShow: boolean = false;
+ /** Data of smarttable populate through LocalDataSource @public */
+ public dataSource: LocalDataSource = new LocalDataSource();
+ /** Columns list of the smart table @public */
+ public columnLists: object = {};
+ /** Settings for smarttable to populate the table with columns @public */
+ public settings: object = {};
+ /** initially hide the list@private */
+ public showList: boolean;
+ /** to store locations name @public */
+ public getLocation: GetLocation[];
+ /** Contains content for map popup @public */
+ public popupData: string;
+ /** Check the loading results @public */
+ public isLoadingResults: boolean = true;
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+ /** Class for empty and present data @public */
+ public checkDataClass: string;
+ /** Formation of appropriate Data for LocalDatasource @public */
+ public vimData: VIMData[];
+ /** operational State init data @public */
+ public operationalStateFirstStep: string = CONFIGCONSTANT.vimOperationalStateFirstStep;
+ /** operational State running data @public */
+ public operationalStateSecondStep: string = CONFIGCONSTANT.vimOperationalStateStateSecondStep;
+ /** operational State failed data @public */
+ public operationalStateThirdStep: string = CONFIGCONSTANT.vimOperationalStateThirdStep;
+ /** NS Instances operational State failed data @public */
+ public nsinstancesoperationalStateRunning: string = CONFIGCONSTANT.operationalStateSecondStep;
+ /** Instance of the rest service @private */
+ private restService: RestService;
+ /** dataService to pass the data from one component to another @private */
+ private dataService: DataService;
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+ /** Holds the instance of router class @private */
+ private router: Router;
+ /** ns INstance Data @private */
+ private nsData: NSInstanceDetails[];
+ /** map object @private */
+ private map: Map;
+ /** used to bind marker @private */
+ private vectorSource: VectorSource;
+ /** used to bind vectorSource @private */
+ private vectorLayer: VectorLayer;
+ /** marker @private */
+ private marker: Feature;
+ /** latitude @private */
+ private lat: number;
+ /** longitude @private */
+ private lng: number;
+ /** each vector layer of marker is pushed to layers array @private */
+ private layers: VectorLayer[] = [];
+ /** locationData @private */
+ private locationData: VimAccountDetails[];
+ /** popup array @private */
+ private overLay: Overlay[] = [];
+ /** Instance of subscriptions @private */
+ private generateDataSub: Subscription;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.restService = this.injector.get(RestService);
+ this.dataService = this.injector.get(DataService);
+ this.sharedService = this.injector.get(SharedService);
+ this.router = this.injector.get(Router);
+ this.translateService = this.injector.get(TranslateService);
+ }
+ /** Lifecyle Hooks the trigger before component is instantiate @public */
+ public ngOnInit(): void {
+ this.osmMapView();
+ this.listView();
+ this.generateColumns();
+ this.generateSettings();
+ this.generateData();
+ this.generateDataSub = this.sharedService.dataEvent.subscribe(() => { this.generateData(); });
+ }
+
+ /** smart table Header Colums @public */
+ public generateColumns(): void {
+ this.columnLists = {
+ name: { title: this.translateService.instant('NAME'), width: '15%', sortDirection: 'asc' },
+ identifier: { title: this.translateService.instant('IDENTIFIER'), width: '25%' },
+ type: {
+ title: this.translateService.instant('TYPE'), width: '15%',
+ filter: {
+ type: 'list',
+ config: {
+ selectText: 'Select',
+ list: VIM_TYPES
+ }
+ }
+ },
+ operationalState: {
+ title: this.translateService.instant('OPERATIONALSTATUS'), width: '15%', type: 'html',
+ filter: {
+ type: 'list',
+ config: {
+ selectText: 'Select',
+ list: [
+ { value: this.operationalStateFirstStep, title: this.operationalStateFirstStep },
+ { value: this.operationalStateSecondStep, title: this.operationalStateSecondStep },
+ { value: this.operationalStateThirdStep, title: this.operationalStateThirdStep }
+ ]
+ }
+ },
+ valuePrepareFunction: (cell: VIMData, row: VIMData): string => {
+ if (row.operationalState === this.operationalStateFirstStep) {
+ return `<span class="icon-label" title="${row.operationalState}">
+ <i class="fas fa-clock text-warning"></i>
+ </span>`;
+ } else if (row.operationalState === this.operationalStateSecondStep) {
+ return `<span class="icon-label" title="${row.operationalState}">
+ <i class="fas fa-check-circle text-success"></i>
+ </span>`;
+ } else if (row.operationalState === this.operationalStateThirdStep) {
+ return `<span class="icon-label" title="${row.operationalState}">
+ <i class="fas fa-times-circle text-danger"></i>
+ </span>`;
+ } else {
+ return `<span>${row.operationalState}</span>`;
+ }
+ }
+ },
+ description: { title: this.translateService.instant('DESCRIPTION'), width: '25%' },
+ Actions: {
+ name: 'Action', width: '5%', filter: false, sort: false, title: this.translateService.instant('ACTIONS'), type: 'custom',
+ valuePrepareFunction: (cell: VIMData, row: VIMData): VIMData => row,
+ renderComponent: VimAccountsActionComponent
+ }
+ };
+ }
+
+ /** smart table Data Settings @public */
+ public generateSettings(): void {
+ this.settings = {
+ edit: {
+ editButtonContent: '<i class="fa fa-edit" title="Edit"></i>',
+ confirmSave: true
+ },
+ delete: {
+ deleteButtonContent: '<i class="far fa-trash-alt" title="delete"></i>',
+ confirmDelete: true
+ },
+ columns: this.columnLists,
+ actions: {
+ add: false,
+ edit: false,
+ delete: false,
+ position: 'right'
+ },
+ attr: this.sharedService.tableClassConfig(),
+ pager: this.sharedService.paginationPagerConfig(),
+ noDataMessage: this.translateService.instant('NODATAMSG')
+ };
+ }
+
+ /** smart table listing manipulation @public */
+ public onChange(perPageValue: number): void {
+ this.dataSource.setPaging(1, perPageValue, true);
+ }
+
+ /** smart table listing manipulation @public */
+ public onUserRowSelect(event: MessageEvent): void {
+ Object.assign(event.data, { page: 'vim-account' });
+ this.dataService.changeMessage(event.data);
+ }
+
+ /** on Navigate to Composer Page @public */
+ public composeVIM(): void {
+ this.router.navigate(['vim/new']).catch(() => {
+ //empty block
+ });
+ }
+
+ /** To show map conatainer @public */
+ public mapView(): void {
+ this.showList = true;
+ this.showMap = false;
+ }
+ /** To show listview @public */
+ public listView(): void {
+ this.showMap = true;
+ this.showList = false;
+ }
+ /** Load the datasource appropriatetype @public */
+ public loadDatasource(getdata: VIMData[]): void {
+ if (getdata.length > 0) {
+ this.checkDataClass = 'dataTables_present';
+ } else {
+ this.checkDataClass = 'dataTables_empty';
+ }
+ this.dataSource.load(getdata).then((data: boolean) => {
+ //empty block
+ }).catch(() => {
+ //empty block
+ });
+ }
+
+ /** Generate generateVIMData object from loop and return for the datasource @public */
+ public generateVIMData(vimAccountData: VimAccountDetails): VIMData {
+ return {
+ name: vimAccountData.name,
+ identifier: vimAccountData._id,
+ type: vimAccountData.vim_type,
+ operationalState: vimAccountData._admin.operationalState,
+ description: vimAccountData.description,
+ instancesData: this.nsData
+ };
+ }
+
+ /**
+ * Lifecyle hook which get trigger on component destruction
+ */
+ public ngOnDestroy(): void {
+ this.generateDataSub.unsubscribe();
+ }
+
+ /** Fetching the data from server to Load in the smarttable @protected */
+ private generateData(): void {
+ this.isLoadingResults = true;
+ this.vimData = [];
+ this.getNSData().then((): void => {
+ this.restService.getResource(environment.VIMACCOUNTS_URL).subscribe((vimAccountsData: VimAccountDetails[]) => {
+ this.locationData = vimAccountsData;
+ vimAccountsData.forEach((vimAccountData: VimAccountDetails) => {
+ const vimDataObj: VIMData = this.generateVIMData(vimAccountData);
+ this.vimData.push(vimDataObj);
+ });
+ this.loadDatasource(this.vimData);
+ this.removeLayersOverLay();
+ this.arrayOfLocation();
+ this.isLoadingResults = false;
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'get');
+ this.isLoadingResults = false;
+ });
+ }).catch((error: ERRORDATA): void => {
+ this.restService.handleError(error, 'get');
+ this.isLoadingResults = false;
+ });
+ }
+
+ /** fetching the nsdata @private */
+ private async getNSData(): Promise<Boolean> {
+ return new Promise<Boolean>((resolve: Function, reject: Function): void => {
+ this.nsData = [];
+ this.restService.getResource(environment.NSDINSTANCES_URL).subscribe((nsdInstancesData: NSInstanceDetails[]) => {
+ const nsRunningInstancesData: NSInstanceDetails[] = nsdInstancesData.filter((instancesData: NSInstanceDetails) =>
+ instancesData['operational-status'] === this.nsinstancesoperationalStateRunning);
+ this.nsData = nsRunningInstancesData;
+ resolve(true);
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'get');
+ resolve(true);
+ });
+ });
+ }
+
+ /** create map view @private */
+ private osmMapView(): void {
+ this.map = new Map({
+ target: 'map',
+ layers: [new TileLayer({
+ source: new OSM()
+ })],
+ interactions: defaultInteractions({
+ mouseWheelZoom: true
+ }),
+ view: new View({
+ center: fromLonLat([CONSTANTNUMBER.osmapviewlong, CONSTANTNUMBER.osmapviewlat]),
+ zoom: 3
+ })
+ });
+ }
+
+ /** remove the layers and overlay @private */
+ private removeLayersOverLay(): void {
+ this.layers.forEach((layer: VectorLayer) => {
+ this.map.removeLayer(layer);
+ });
+ this.overLay.forEach((lay: Overlay) => {
+ this.map.removeOverlay(lay);
+ });
+ }
+
+ /** filter locations from vimaccounts @private */
+ private arrayOfLocation(): void {
+ this.getLocation = [];
+ this.locationData.filter((item: VimAccountDetails) => {
+ if (item.hasOwnProperty('config')) {
+ if (item.config.hasOwnProperty('location')) {
+ this.getLocation.push({ name: item.name, location: item.config.location, id: item._id });
+ }
+ }
+ });
+ if (this.getLocation !== []) {
+ this.getLocation.filter((loc: GetLocation) => {
+ if (loc.location !== '') {
+ const getLatLong: string[] = loc.location.split(',');
+ this.lng = +getLatLong[CONSTANTNUMBER.splitLongitude];
+ this.lat = +getLatLong[CONSTANTNUMBER.splitLatitude];
+ this.addMarker(getLatLong[0], loc.id, loc.name);
+ }
+ });
+ }
+ }
+ /** add markers on map @private */
+ private addMarker(loc: string, id: string, name: string): void {
+ const container: HTMLElement = document.getElementById('popup');
+ const closer: HTMLElement = document.getElementById('popup-closer');
+ this.popupShow = true;
+ const overlay: Overlay = this.addOverlay(container);
+ this.marker = this.addFeature(loc, id, name);
+ this.setStyleMarker();
+ this.setVectorSource();
+ this.setVectorLayer();
+ this.map.addLayer(this.vectorLayer);
+ this.layers.push(this.vectorLayer);
+ if (this.layers.length === 1) {
+ this.markerClickEvent(closer, overlay);
+ }
+ }
+ /** Create an overlay to anchor the popup to the map @private */
+ private addOverlay(container: HTMLElement): Overlay {
+ return new Overlay({
+ element: container,
+ autoPan: true,
+ autoPanAnimation: {
+ duration: 250
+ }
+ });
+ }
+ /** Return the Feature of creating a marker in the map @private */
+ private addFeature(loc: string, id: string, name: string): Feature {
+ return new Feature({
+ geometry: new Point(fromLonLat([this.lng, this.lat])),
+ location: loc,
+ Id: id,
+ vimName: name
+ });
+ }
+ /** Set the style of the marker @private */
+ private setStyleMarker(): void {
+ this.marker.setStyle(new Style({
+ image: new Icon(({
+ crossOrigin: 'anonymous',
+ src: 'assets/images/map-icon.png'
+ }))
+ }));
+ }
+ /** Set the map vector source @private */
+ private setVectorSource(): void {
+ this.vectorSource = new VectorSource({
+ features: [this.marker]
+ });
+ }
+ /** Set the map vector layer @private */
+ private setVectorLayer(): void {
+ this.vectorLayer = new VectorLayer({
+ source: this.vectorSource
+ });
+ }
+ /** Add a click handler to the map to render the popup. @private */
+ private markerClickEvent(closer: HTMLElement, overlay: Overlay): void {
+ // tslint:disable-next-line: no-any
+ this.map.on('singleclick', (evt: any) => {
+ const feature: Feature = this.map.forEachFeatureAtPixel(evt.pixel,
+ (f: Feature) => {
+ return f;
+ });
+ if (feature) {
+ this.setCoordinates(feature, overlay);
+ } else {
+ this.map.removeOverlay(overlay);
+ }
+ });
+ /** Handle close event for overlay */
+ closer.onclick = (): boolean => {
+ overlay.setPosition(undefined);
+ closer.blur();
+ return false;
+ };
+ }
+ /** Set the coordinates point if the feature is available @private */
+ // tslint:disable-next-line: no-any
+ private setCoordinates(feature: any, overlay: Overlay): void {
+ this.popupData = '';
+ this.popupData += '<h3 class="popover-header">' + feature.values_.vimName + '</h3>';
+ this.popupData += '<ul class="list-unstyled m-2">';
+ const instnaceData: NSInstanceDetails[] = this.nsData.filter((item: NSInstanceDetails) => {
+ if (item.datacenter === feature.values_.Id) {
+ this.popupData += '<li class="m-2"><a class="d-block text-truncate" target="_parent" href="instances/ns/' + item._id + '">'
+ + item.name + '</a></li>';
+ return item;
+ }
+ });
+ if (instnaceData.length === 0) {
+ this.popupData += '<li class="m-2">' + this.translateService.instant('PAGE.DASHBOARD.NOINSTANCES') + '</li>';
+ }
+ this.popupData += '</ul>';
+ const coordinates: number[] = feature.getGeometry().getCoordinates();
+ overlay.setPosition(coordinates);
+ this.overLay.push(overlay);
+ this.map.addOverlay(overlay);
+ }
+}
+
+/** interface for get location */
+interface GetLocation {
+ location: string;
+ id: string;
+ name?: string;
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<router-outlet></router-outlet>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file WIM Account Component.
+ */
+import { Component, Injector } from '@angular/core';
+import { Router, RouterEvent } from '@angular/router';
+
+/**
+ * Creating component
+ * @Component takes WIMAccountsComponent.html as template url
+ */
+@Component({
+ templateUrl: './WIMAccountsComponent.html',
+ styleUrls: ['./WIMAccountsComponent.scss']
+})
+/** Exporting a class @exports WIMAccountsComponent */
+export class WIMAccountsComponent {
+ /** Invoke service injectors @public */
+ public injector: Injector;
+
+ /** Holds teh instance of AuthService class of type AuthService @private */
+ private router: Router;
+
+ // creates packages component
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.router = this.injector.get(Router);
+ this.router.events.subscribe((event: RouterEvent) => {
+ this.redirectToList(event.url);
+ });
+ }
+
+ /** Return to list NS Package List */
+ public redirectToList(getURL: string): void {
+ if (getURL === '/wim') {
+ this.router.navigate(['/wim/details']).catch();
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file WIM Account module.
+ */
+import { CommonModule } from '@angular/common';
+import { HttpClientModule } from '@angular/common/http';
+import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
+import { FormsModule } from '@angular/forms';
+import { ReactiveFormsModule } from '@angular/forms';
+import { RouterModule, Routes } from '@angular/router';
+import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
+import { NgSelectModule } from '@ng-select/ng-select';
+import { TranslateModule } from '@ngx-translate/core';
+import { DataService } from 'DataService';
+import { LoaderModule } from 'LoaderModule';
+import { NewWIMAccountComponent } from 'NewWIMAccount';
+import { Ng2SmartTableModule } from 'ng2-smart-table';
+import { PagePerRowModule } from 'PagePerRowModule';
+import { PageReloadModule } from 'PageReloadModule';
+import { WIMAccountDetailsComponent } from 'WIMAccountDetails';
+import { WIMAccountInfoComponent } from 'WIMAccountInfo';
+import { WIMAccountsComponent } from 'WIMAccountsComponent';
+
+/** To halndle project information */
+const projectInfo: {} = { title: '{project}', url: '/' };
+
+/** const values for dashboard Routes */
+const routes: Routes = [
+ {
+ path: '',
+ component: WIMAccountsComponent,
+ children: [
+ {
+ path: 'details',
+ data: {
+ breadcrumb: [{ title: 'PAGE.DASHBOARD.DASHBOARD', url: '/' }, { title: 'PAGE.DASHBOARD.PROJECTS', url: '/projects' },
+ projectInfo, { title: 'WIMACCOUNTS', url: null }]
+ },
+ component: WIMAccountDetailsComponent
+ }
+ ]
+ }
+];
+
+/**
+ * Creating @NgModule component for Modules
+ */
+@NgModule({
+ imports: [ReactiveFormsModule.withConfig({ warnOnNgModelWithFormControl: 'never' }), FormsModule, CommonModule,
+ HttpClientModule, NgSelectModule, Ng2SmartTableModule, TranslateModule, RouterModule.forChild(routes), NgbModule,
+ PagePerRowModule, LoaderModule, PageReloadModule],
+ declarations: [WIMAccountsComponent, WIMAccountInfoComponent, WIMAccountDetailsComponent, NewWIMAccountComponent],
+ providers: [DataService],
+ schemas: [CUSTOM_ELEMENTS_SCHEMA],
+ entryComponents: [WIMAccountInfoComponent, NewWIMAccountComponent]
+})
+/** Exporting a class @exports WIMAccountsModule */
+export class WIMAccountsModule {
+ /** Variables declared to avoid state-less class */
+ private wimModule: string;
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<form [formGroup]="wimNewAccountForm" (ngSubmit)="newWimAccountSubmit()" autocomplete="off">
+ <div class="modal-header">
+ <h4 class="modal-title" id="modal-basic-title">{{'PAGE.WIMACCOUNTS.NEWWIM' | translate}}</h4>
+ <button class="button-xs" type="button" class="close" aria-label="Close" (click)="activeModal.close()">
+ <i class="fas fa-times-circle text-danger"></i>
+ </button>
+ </div>
+ <div class="modal-body modal-body-custom-height">
+ <div class="form-group row">
+ <label class="col-sm-12 col-form-label mandatory-label"
+ [ngClass]="{'text-danger': wimNewAccountForm.invalid === true && submitted === true}">{{'MANDATORYCHECK' | translate}}</label>
+ <label class="col-sm-4 col-form-label" for="name">{{'NAME' | translate}}*</label>
+ <div class="col-sm-8">
+ <input autocomplete="off" class="form-control" placeholder="{{'NAME' | translate}}" type="text"
+ formControlName="name" id="name" [ngClass]="{ 'is-invalid': submitted && f.name.errors }" required>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label" for="wim_type">{{'TYPE' | translate}}*</label>
+ <div class="col-sm-8">
+ <ng-select bindLabel="title" bindValue="value" [items]="wimType" placeholder="{{'SELECT' | translate}}"
+ formControlName="wim_type" id="wim_type" [(ngModel)]="wimTypeMod"
+ [ngClass]="{ 'is-invalid': submitted && f.wim_type.errors }" required>
+ </ng-select>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label" for="wim_url">{{'URL' | translate}}*</label>
+ <div class="col-sm-8">
+ <input autocomplete="off" class="form-control" placeholder="{{'URL' | translate}}" type="url"
+ formControlName="wim_url" id="wim_url" [ngClass]="{ 'is-invalid': submitted && f.wim_url.errors }"
+ required>
+ <div *ngIf="wimNewAccountForm.invalid" class="invalid-feedback">
+ <div *ngIf="f.wim_url.errors && f.wim_url.value">{{'DOMVALIDATIONS.INVALIDURL' | translate}}</div>
+ </div>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label" for="user">{{'PAGE.WIMACCOUNTS.USERNAME' | translate}}*</label>
+ <div class="col-sm-8">
+ <input autocomplete="off" class="form-control" placeholder="{{'PAGE.WIMACCOUNTS.USERNAME' | translate}}"
+ type="text" formControlName="user" id="user"
+ [ngClass]="{ 'is-invalid': submitted && f.user.errors }" required>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label" for="password">{{'PAGE.WIMACCOUNTS.PASSWORD' | translate}}*</label>
+ <div class="col-sm-8">
+ <input autocomplete="off" class="form-control" placeholder="{{'PAGE.WIMACCOUNTS.PASSWORD' | translate}}"
+ type="password" formControlName="password" id="password"
+ [ngClass]="{ 'is-invalid': submitted && f.password.errors }" required>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label" for="description">{{'DESCRIPTION' | translate}}</label>
+ <div class="col-sm-8">
+ <textarea class="form-control" placeholder="{{'DESCRIPTION' | translate}}" type="text"
+ formControlName="description" id="description"></textarea>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-4 col-form-label" for="config">{{'CONFIG' | translate}}</label>
+ <div class="col-sm-8">
+ <textarea class="form-control" placeholder="{{'YAMLCONFIG' | translate}}" formControlName="config"
+ id="config"></textarea>
+ <div class="fileupload-text mt-1 mb-1">{{'FILEUPLOADLABEL' | translate}}</div>
+ <div class="custom-file">
+ <input type="file" #fileInputConfig class="custom-file-input"
+ (change)="configFile($event.target.files)" id="customFile">
+ <label class="custom-file-label" #fileInputConfigLabel for="customFile">{{'CHOOSEFILE' | translate}}</label>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-danger" (click)="activeModal.close()">{{'CANCEL' | translate}}</button>
+ <button type="submit" class="btn btn-primary">{{'CREATE' | translate}}</button>
+ </div>
+</form>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file WIM Account Component.
+ */
+import { HttpHeaders } from '@angular/common/http';
+import { Component, ElementRef, Injector, OnInit, ViewChild } from '@angular/core';
+import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
+import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateService } from '@ngx-translate/core';
+import { NotifierService } from 'angular-notifier';
+import { APIURLHEADER, ERRORDATA, MODALCLOSERESPONSEDATA, TYPESECTION, WIM_TYPES } from 'CommonModel';
+import { environment } from 'environment';
+import * as jsyaml from 'js-yaml';
+import { RestService } from 'RestService';
+import { SharedService } from 'SharedService';
+import { isNullOrUndefined } from 'util';
+
+/**
+ * Creating component
+ * @Component takes NewWIMAccountComponent.html as template url
+ */
+@Component({
+ templateUrl: './NewWIMAccountComponent.html',
+ styleUrls: ['./NewWIMAccountComponent.scss']
+})
+/** Exporting a class @exports NewWIMAccountComponent */
+export class NewWIMAccountComponent implements OnInit {
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** Setting wim types in array @public */
+ public wimType: TYPESECTION[];
+
+ /** Set WIM Type select to empty @public */
+ public wimTypeMod: string = null;
+
+ /** New WIM account form controls using formgroup @public */
+ public wimNewAccountForm: FormGroup;
+
+ /** Form submission Add */
+ public submitted: boolean = false;
+
+ /** Instance for active modal service @public */
+ public activeModal: NgbActiveModal;
+
+ /** Check the loading results for loader status @public */
+ public isLoadingResults: boolean = false;
+
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+
+ /** Element ref for fileInputConfig @public */
+ @ViewChild('fileInputConfig', { static: true }) public fileInputConfig: ElementRef;
+
+ /** Element ref for fileInputConfig @public */
+ @ViewChild('fileInputConfigLabel', { static: true }) public fileInputConfigLabel: ElementRef;
+
+ /** Instance of the rest service @private */
+ private restService: RestService;
+
+ /** Controls the header form @private */
+ private headers: HttpHeaders;
+
+ /** FormBuilder instance added to the formBuilder @private */
+ private formBuilder: FormBuilder;
+
+ /** Notifier service to popup notification @private */
+ private notifierService: NotifierService;
+
+ /** Contains tranlsate instance @private */
+ private translateService: TranslateService;
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.restService = this.injector.get(RestService);
+ this.formBuilder = this.injector.get(FormBuilder);
+ this.notifierService = this.injector.get(NotifierService);
+ this.translateService = this.injector.get(TranslateService);
+ this.activeModal = this.injector.get(NgbActiveModal);
+ this.sharedService = this.injector.get(SharedService);
+
+ /** Initializing Form Action */
+ this.wimNewAccountForm = this.formBuilder.group({
+ name: ['', Validators.required],
+ wim_type: ['', Validators.required],
+ wim_url: ['', [Validators.required, Validators.pattern(this.sharedService.REGX_URL_PATTERN)]],
+ user: ['', Validators.required],
+ password: ['', Validators.required],
+ description: [null],
+ config: [null]
+ });
+ }
+
+ /** convenience getter for easy access to form fields */
+ get f(): FormGroup['controls'] { return this.wimNewAccountForm.controls; }
+
+ /**
+ * Lifecyle Hooks the trigger before component is instantiate
+ */
+ public ngOnInit(): void {
+ this.wimType = WIM_TYPES;
+ this.headers = new HttpHeaders({
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
+ });
+ }
+
+ /** On modal submit newWimAccountSubmit will called @public */
+ public newWimAccountSubmit(): void {
+ this.submitted = true;
+ const modalData: MODALCLOSERESPONSEDATA = {
+ message: 'Done'
+ };
+ this.sharedService.cleanForm(this.wimNewAccountForm);
+ if (this.wimNewAccountForm.value.description === '') {
+ this.wimNewAccountForm.value.description = null;
+ }
+ if (isNullOrUndefined(this.wimNewAccountForm.value.config) || this.wimNewAccountForm.value.config === '') {
+ delete this.wimNewAccountForm.value.config;
+ } else {
+ const validJSON: boolean = this.sharedService.checkJson(this.wimNewAccountForm.value.config);
+ if (validJSON) {
+ this.wimNewAccountForm.value.config = JSON.parse(this.wimNewAccountForm.value.config);
+ } else {
+ this.notifierService.notify('error', this.translateService.instant('INVALIDCONFIG'));
+ return;
+ }
+ }
+ if (!this.wimNewAccountForm.invalid) {
+ this.isLoadingResults = true;
+ const apiURLHeader: APIURLHEADER = {
+ url: environment.WIMACCOUNTS_URL,
+ httpOptions: { headers: this.headers }
+ };
+ this.restService.postResource(apiURLHeader, this.wimNewAccountForm.value)
+ .subscribe((result: {}) => {
+ this.activeModal.close(modalData);
+ this.isLoadingResults = false;
+ this.notifierService.notify('success', this.translateService.instant('PAGE.WIMACCOUNTS.CREATEDSUCCESSFULLY'));
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'post');
+ this.isLoadingResults = false;
+ });
+ }
+ }
+
+ /** Config file process @private */
+ public configFile(files: FileList): void {
+ if (files && files.length === 1) {
+ this.sharedService.getFileString(files, 'yaml').then((fileContent: string): void => {
+ const getConfigJson: string = jsyaml.load(fileContent, { json: true });
+ // tslint:disable-next-line: no-backbone-get-set-outside-model
+ this.wimNewAccountForm.get('config').setValue(JSON.stringify(getConfigJson));
+ }).catch((err: string): void => {
+ if (err === 'typeError') {
+ this.notifierService.notify('error', this.translateService.instant('YAMLFILETYPEERRROR'));
+ } else {
+ this.notifierService.notify('error', this.translateService.instant('ERROR'));
+ }
+ this.fileInputConfigLabel.nativeElement.innerText = this.translateService.instant('CHOOSEFILE');
+ this.fileInputConfig.nativeElement.value = null;
+ });
+ } else if (files && files.length > 1) {
+ this.notifierService.notify('error', this.translateService.instant('DROPFILESVALIDATION'));
+ }
+ this.fileInputConfigLabel.nativeElement.innerText = files[0].name;
+ this.fileInputConfig.nativeElement.value = null;
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="row d-flex flex-row justify-content-between">
+ <div class="d-flex align-items-center header-style">{{'WIMACCOUNTS' | translate}}</div>
+ <span class="button">
+ <button class="btn btn-primary" type="button" placement="top" container="body" ngbTooltip="{{'PAGE.WIMACCOUNTS.NEWWIM' | translate}}"
+ (click)="composeWIM()">
+ <i class="fas fa-plus-circle" aria-hidden="true"></i> {{'PAGE.WIMACCOUNTS.NEWWIM' | translate}}
+ </button>
+ </span>
+</div>
+<div class="row mt-2 mb-0 list-utilites-actions">
+ <div class="col-auto mr-auto">
+ <nav class="custom-items-config">
+ <span><i class="fas fa-clock text-warning"></i>{{operationalStateFirstStep}}</span>
+ <span><i class="fas fa-check-circle text-success"></i>{{operationalStateSecondStep}}</span>
+ <span><i class="fas fa-times-circle text-danger"></i>{{operationalStateThirdStep}}</span>
+ </nav>
+ </div>
+ <page-per-row class="mr-2" (pagePerRow)="onChange($event)"></page-per-row>
+ <page-reload></page-reload>
+</div>
+<div class="smarttable-style bg-white mt-1">
+ <ng2-smart-table [ngClass]="checkDataClass" [settings]="settings" [source]="dataSource" (userRowSelect)="onUserRowSelect($event)">
+ </ng2-smart-table>
+</div>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file WIM Account Component.
+ */
+import { Component, Injector, OnDestroy, OnInit } from '@angular/core';
+import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateService } from '@ngx-translate/core';
+import { CONFIGCONSTANT, ERRORDATA, MODALCLOSERESPONSEDATA, WIM_TYPES } from 'CommonModel';
+import { DataService } from 'DataService';
+import { environment } from 'environment';
+import { NewWIMAccountComponent } from 'NewWIMAccount';
+import { LocalDataSource } from 'ng2-smart-table';
+import { RestService } from 'RestService';
+import { Subscription } from 'rxjs';
+import { SharedService } from 'SharedService';
+import { WIMAccountData, WIMAccountModel } from 'WIMAccountModel';
+import { WIMAccountsActionComponent } from 'WIMAccountsAction';
+/**
+ * Creating component
+ * @Component takes WIMAccountDetailsComponent.html as template url
+ */
+@Component({
+ templateUrl: './WIMAccountDetailsComponent.html',
+ styleUrls: ['./WIMAccountDetailsComponent.scss']
+})
+/** Exporting a class @exports WIMAccountDetailsComponent */
+export class WIMAccountDetailsComponent implements OnInit, OnDestroy {
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** handle translate @public */
+ public translateService: TranslateService;
+
+ /** Data of smarttable populate through LocalDataSource @public */
+ public dataSource: LocalDataSource = new LocalDataSource();
+
+ /** Columns list of the smart table @public */
+ public columnLists: object = {};
+
+ /** Settings for smarttable to populate the table with columns @public */
+ public settings: object = {};
+
+ /** Check the loading results @public */
+ public isLoadingResults: boolean = true;
+
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+
+ /** Class for empty and present data @public */
+ public checkDataClass: string;
+
+ /** operational State init data @public */
+ public operationalStateFirstStep: string = CONFIGCONSTANT.wimOperationalStateFirstStep;
+
+ /** operational State running data @public */
+ public operationalStateSecondStep: string = CONFIGCONSTANT.wimOperationalStateStateSecondStep;
+
+ /** operational State failed data @public */
+ public operationalStateThirdStep: string = CONFIGCONSTANT.wimOperationalStateThirdStep;
+
+ /** Instance of the rest service @private */
+ private restService: RestService;
+
+ /** dataService to pass the data from one component to another @private */
+ private dataService: DataService;
+
+ /** Formation of appropriate Data for LocalDatasource @private */
+ private wimData: {}[] = [];
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ /** Instance of the modal service @private */
+ private modalService: NgbModal;
+
+ /** Instance of subscriptions @private */
+ private generateDataSub: Subscription;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.restService = this.injector.get(RestService);
+ this.dataService = this.injector.get(DataService);
+ this.sharedService = this.injector.get(SharedService);
+ this.translateService = this.injector.get(TranslateService);
+ this.modalService = this.injector.get(NgbModal);
+ }
+ /** Lifecyle Hooks the trigger before component is instantiate @public */
+ public ngOnInit(): void {
+ this.generateColumns();
+ this.generateSettings();
+ this.generateData();
+ this.generateDataSub = this.sharedService.dataEvent.subscribe(() => { this.generateData(); });
+ }
+
+ /** smart table Header Colums @public */
+ public generateColumns(): void {
+ this.columnLists = {
+ name: { title: this.translateService.instant('NAME'), width: '20%', sortDirection: 'asc' },
+ identifier: { title: this.translateService.instant('IDENTIFIER'), width: '20%' },
+ type: {
+ title: this.translateService.instant('TYPE'), width: '15%',
+ filter: {
+ type: 'list',
+ config: {
+ selectText: 'Select',
+ list: WIM_TYPES
+ }
+ }
+ },
+ operationalState: {
+ title: this.translateService.instant('OPERATIONALSTATUS'), width: '15%', type: 'html',
+ filter: {
+ type: 'list',
+ config: {
+ selectText: 'Select',
+ list: [
+ { value: this.operationalStateFirstStep, title: this.operationalStateFirstStep },
+ { value: this.operationalStateSecondStep, title: this.operationalStateSecondStep },
+ { value: this.operationalStateThirdStep, title: this.operationalStateThirdStep }
+ ]
+ }
+ },
+ valuePrepareFunction: (cell: WIMAccountData, row: WIMAccountData): string => {
+ if (row.operationalState === this.operationalStateFirstStep) {
+ return `<span class="icon-label" title="${row.operationalState}">
+ <i class="fas fa-clock text-warning"></i>
+ </span>`;
+ } else if (row.operationalState === this.operationalStateSecondStep) {
+ return `<span class="icon-label" title="${row.operationalState}">
+ <i class="fas fa-check-circle text-success"></i>
+ </span>`;
+ } else if (row.operationalState === this.operationalStateThirdStep) {
+ return `<span class="icon-label" title="${row.operationalState}">
+ <i class="fas fa-times-circle text-danger"></i>
+ </span>`;
+ } else {
+ return `<span>${row.operationalState}</span>`;
+ }
+ }
+ },
+ description: { title: this.translateService.instant('DESCRIPTION'), width: '25%' },
+ Actions: {
+ name: 'Action', width: '5%', filter: false, sort: false, title: this.translateService.instant('ACTIONS'), type: 'custom',
+ valuePrepareFunction: (cell: WIMAccountData, row: WIMAccountData): WIMAccountData => row,
+ renderComponent: WIMAccountsActionComponent
+ }
+ };
+ }
+
+ /** smart table Data Settings @public */
+ public generateSettings(): void {
+ this.settings = {
+ edit: {
+ editButtonContent: '<i class="fa fa-edit" title="Edit"></i>', confirmSave: true
+ },
+ delete: {
+ deleteButtonContent: '<i class="far fa-trash-alt" title="delete"></i>', confirmDelete: true
+ },
+ columns: this.columnLists,
+ actions: {
+ add: false, edit: false, delete: false, position: 'right'
+ },
+ attr: this.sharedService.tableClassConfig(),
+ pager: this.sharedService.paginationPagerConfig(),
+ noDataMessage: this.translateService.instant('NODATAMSG')
+ };
+ }
+
+ /** smart table listing manipulation @public */
+ public onChange(perPageValue: number): void {
+ this.dataSource.setPaging(1, perPageValue, true);
+ }
+
+ /** smart table listing manipulation @public */
+ public onUserRowSelect(event: MessageEvent): void {
+ Object.assign(event.data, { page: 'wim-account' });
+ this.dataService.changeMessage(event.data);
+ }
+
+ /** Compose new WIM Accounts @public */
+ public composeWIM(): void {
+ const modalRef: NgbModalRef = this.modalService.open(NewWIMAccountComponent, { backdrop: 'static' });
+ modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
+ if (result) {
+ this.sharedService.callData();
+ }
+ }).catch();
+ }
+
+ /** Generate generateWIMData object from loop and return for the datasource @public */
+ public generateWIMData(wimAccountData: WIMAccountModel): WIMAccountData {
+ return {
+ name: wimAccountData.name,
+ identifier: wimAccountData._id,
+ type: wimAccountData.wim_type,
+ operationalState: wimAccountData._admin.operationalState,
+ description: wimAccountData.description
+ };
+ }
+
+ /**
+ * Lifecyle hook which get trigger on component destruction
+ */
+ public ngOnDestroy(): void {
+ this.generateDataSub.unsubscribe();
+ }
+
+ /** Fetching the data from server to Load in the smarttable @protected */
+ protected generateData(): void {
+ this.isLoadingResults = true;
+ this.wimData = [];
+ this.restService.getResource(environment.WIMACCOUNTS_URL).subscribe((wimAccountsDetails: {}[]) => {
+ wimAccountsDetails.forEach((wimAccountsData: WIMAccountModel) => {
+ const wimDataObj: WIMAccountData = this.generateWIMData(wimAccountsData);
+ this.wimData.push(wimDataObj);
+ });
+ if (this.wimData.length > 0) {
+ this.checkDataClass = 'dataTables_present';
+ } else {
+ this.checkDataClass = 'dataTables_empty';
+ }
+ this.dataSource.load(this.wimData).then((data: {}) => {
+ this.isLoadingResults = false;
+ }).catch();
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'get');
+ this.isLoadingResults = false;
+ });
+ }
+}
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<div class="modal-header">
+ <h4 class="modal-title" id="modal-basic-title">{{'PAGE.WIMACCOUNTS.WIMDETAILS' | translate}}</h4>
+ <button class="button-xs" type="button" class="close" aria-label="Close" (click)="activeModal.close()">
+ <i class="fas fa-times-circle text-danger"></i>
+ </button>
+</div>
+<div class="modal-body modal-body-custom-height p-0">
+ <table class="table table-striped table-layout-fixed mb-0" *ngIf="wimDetails">
+ <tr>
+ <td colspan="2">
+ <b>{{'ID' | translate}}:</b> {{(wimDetails._id)?wimDetails._id:''}}
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2">
+ <b>{{'DETAILEDSTATUS' | translate}}:</b> {{(wimDetails._admin['detailed-status'])?wimDetails._admin['detailed-status']:''}}
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <b>{{'OPERATIONALSTATE' | translate}}:</b><span class="ml-1 badge" [ngClass]="{'badge-info':wimDetails._admin.operationalState === operationalStateFirstStep,
+ 'badge-success':wimDetails._admin.operationalState === operationalStateSecondStep,
+ 'badge-danger':wimDetails._admin.operationalState === operationalStateThirdStep}">
+ {{(wimDetails._admin.operationalState)?wimDetails._admin.operationalState:''}}
+ </span>
+ </td>
+ <td>
+ <b>{{'PAGE.WIMACCOUNTS.SCHEMAVERSION' | translate}}:</b> {{(wimDetails.schema_version)?wimDetails.schema_version:''}}
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <b>{{'NAME' | translate}}:</b> {{(wimDetails.name)?wimDetails.name:''}}
+ </td>
+ <td>
+ <b>{{'TYPE' | translate}}:</b> {{(wimDetails.wim_type)?wimDetails.wim_type:''}}
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <b>{{'URL' | translate}}:</b> {{(wimDetails.wim_url)?wimDetails.wim_url:''}}
+ </td>
+ <td>
+ <b>{{'DESCRIPTION' | translate}}:</b> {{(wimDetails.description)?wimDetails.description:''}}
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <b>{{'CREATED' | translate}}:</b> {{(wimDetails._admin.created)?this.sharedService.convertEpochTime(wimDetails._admin.created):''}}
+ </td>
+ <td>
+ <b>{{'MODIFIED' | translate}}:</b> {{(wimDetails._admin.modified)?this.sharedService.convertEpochTime(wimDetails._admin.modified):''}}
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2">
+ <b>{{'DEPLOYED' | translate}}</b> <br>
+ <b>{{'PAGE.WIMACCOUNTS.RO' | translate}}:</b> {{(wimDetails._admin.deployed.RO)?wimDetails._admin.deployed.RO:''}} <br>
+ <b>{{'PAGE.WIMACCOUNTS.ROACCOUNT' | translate}}:</b> {{(wimDetails._admin.deployed['RO-account'])?wimDetails._admin.deployed['RO-account']:''}}
+ </td>
+ </tr>
+ </table>
+</div>
+<div class="modal-footer">
+ <button type="button" class="btn btn-danger" (click)="activeModal.close()">{{'CANCEL' | translate}}</button>
+</div>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+*/
+/**
+ * @file Info WIM Page
+ */
+import { Component, Injector, Input, OnInit } from '@angular/core';
+import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
+import { CONFIGCONSTANT, ERRORDATA, URLPARAMS } from 'CommonModel';
+import { environment } from 'environment';
+import { RestService } from 'RestService';
+import { SharedService } from 'SharedService';
+import { WIMAccountModel } from 'WIMAccountModel';
+
+/**
+ * Creating component
+ * @Component takes WIMAccountInfoComponent.html as template url
+ */
+@Component({
+ templateUrl: './WIMAccountInfoComponent.html',
+ styleUrls: ['./WIMAccountInfoComponent.scss']
+})
+/** Exporting a class @exports WIMAccountInfoComponent */
+export class WIMAccountInfoComponent implements OnInit {
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** Input contains component objects @public */
+ @Input() public params: URLPARAMS;
+
+ /** Contains WIM details @public */
+ public wimDetails: WIMAccountModel;
+
+ /** Instance for active modal service @public */
+ public activeModal: NgbActiveModal;
+
+ /** Check the loading results for loader status @public */
+ public isLoadingResults: boolean = true;
+
+ /** operational State init data @public */
+ public operationalStateFirstStep: string = CONFIGCONSTANT.wimOperationalStateFirstStep;
+
+ /** operational State running data @public */
+ public operationalStateSecondStep: string = CONFIGCONSTANT.wimOperationalStateStateSecondStep;
+
+ /** operational State failed data @public */
+ public operationalStateThirdStep: string = CONFIGCONSTANT.wimOperationalStateThirdStep;
+
+ /** Give the message for the loading @public */
+ public message: string = 'PLEASEWAIT';
+
+ /** Instance of the rest service @private */
+ private restService: RestService;
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.restService = this.injector.get(RestService);
+ this.activeModal = this.injector.get(NgbActiveModal);
+ this.sharedService = this.injector.get(SharedService);
+ }
+
+ /**
+ * Lifecyle Hooks the trigger before component is instantiate
+ */
+ public ngOnInit(): void {
+ this.generateData();
+ }
+
+ /** Generate Data function @public */
+ public generateData(): void {
+ this.restService.getResource(environment.WIMACCOUNTS_URL + '/' + this.params.id).subscribe((wimDetails: WIMAccountModel) => {
+ this.wimDetails = wimDetails;
+ this.isLoadingResults = false;
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'get');
+ this.isLoadingResults = false;
+ });
+ }
+}
--- /dev/null
+{
+ "rolePermissions": [
+ {
+ "title": "Default",
+ "permissions": [
+ {
+ "operation": "default",
+ "value": "NA"
+ }
+ ]
+ },
+ {
+ "title": "Admin",
+ "permissions": [
+ {
+ "operation": "admin",
+ "value": "NA"
+ },
+ {
+ "operation": "admin:get",
+ "value": "NA"
+ },
+ {
+ "operation": "admin:post",
+ "value": "NA"
+ },
+ {
+ "operation": "admin:patch",
+ "value": "NA"
+ },
+ {
+ "operation": "admin:put",
+ "value": "NA"
+ },
+ {
+ "operation": "admin:delete",
+ "value": "NA"
+ }
+ ]
+ },
+ {
+ "title": "NS Descriptors",
+ "permissions": [
+ {
+ "operation": "nsds",
+ "value": "NA"
+ },
+ {
+ "operation": "nsds:get",
+ "value": "NA"
+ },
+ {
+ "operation": "nsds:post",
+ "value": "NA"
+ },
+ {
+ "operation": "nsds:id:get",
+ "value": "NA"
+ },
+ {
+ "operation": "nsds:id:put",
+ "value": "NA"
+ },
+ {
+ "operation": "nsds:id:delete",
+ "value": "NA"
+ },
+ {
+ "operation": "nsds:id:patch",
+ "value": "NA"
+ },
+ {
+ "operation": "nsds:content:post",
+ "value": "NA"
+ },
+ {
+ "operation": "nsds:id:content:get",
+ "value": "NA"
+ },
+ {
+ "operation": "nsds:id:content:put",
+ "value": "NA"
+ },
+ {
+ "operation": "nsds:id:nsd:get",
+ "value": "NA"
+ },
+ {
+ "operation": "nsds:id:nsd_artifact:get",
+ "value": "NA"
+ }
+ ]
+ },
+ {
+ "title": "VNF Descriptors",
+ "permissions": [
+ {
+ "operation": "vnfds",
+ "value": "NA"
+ },
+ {
+ "operation": "vnfds:post",
+ "value": "NA"
+ },
+ {
+ "operation": "vnfds:content:post",
+ "value": "NA"
+ },
+ {
+ "operation": "vnfds:id:get",
+ "value": "NA"
+ },
+ {
+ "operation": "vnfds:id:put",
+ "value": "NA"
+ },
+ {
+ "operation": "vnfds:id:delete",
+ "value": "NA"
+ },
+ {
+ "operation": "vnfds:id:patch",
+ "value": "NA"
+ },
+ {
+ "operation": "vnfds:id:content:get",
+ "value": "NA"
+ },
+ {
+ "operation": "vnfds:id:content:put",
+ "value": "NA"
+ },
+ {
+ "operation": "vnfds:id:vnfd:get",
+ "value": "NA"
+ },
+ {
+ "operation": "vnfds:id:vnfd_artifact:get",
+ "value": "NA"
+ },
+ {
+ "operation": "vnfds:id:action:post",
+ "value": "NA"
+ },
+ {
+ "operation": "vnfds:vnfpkgops:get",
+ "value": "NA"
+ },
+ {
+ "operation": "vnfds:vnfpkgops:id:get",
+ "value": "NA"
+ }
+ ]
+ },
+ {
+ "title": "NS Instances",
+ "permissions": [
+ {
+ "operation": "ns_instances",
+ "value": "NA"
+ },
+ {
+ "operation": "ns_instances:get",
+ "value": "NA"
+ },
+ {
+ "operation": "ns_instances:post",
+ "value": "NA"
+ },
+ {
+ "operation": "ns_instances:content:post",
+ "value": "NA"
+ },
+ {
+ "operation": "ns_instances:id:get",
+ "value": "NA"
+ },
+ {
+ "operation": "ns_instances:id:delete",
+ "value": "NA"
+ },
+ {
+ "operation": "ns_instances:id:instantiate:post",
+ "value": "NA"
+ },
+ {
+ "operation": "ns_instances:id:terminate:post",
+ "value": "NA"
+ },
+ {
+ "operation": "ns_instances:id:action:post",
+ "value": "NA"
+ },
+ {
+ "operation": "ns_instances:id:scale:post",
+ "value": "NA"
+ },
+ {
+ "operation": "ns_instances:opps:get",
+ "value": "NA"
+ },
+ {
+ "operation": "ns_instances:opps:id:get",
+ "value": "NA"
+ }
+ ]
+ },
+ {
+ "title": "VNF Instances",
+ "permissions": [
+ {
+ "operation": "vnf_instances",
+ "value": "NA"
+ },
+ {
+ "operation": "vnf_instances:get",
+ "value": "NA"
+ },
+ {
+ "operation": "vnf_instances:id:get",
+ "value": "NA"
+ }
+ ]
+ },
+ {
+ "title": "VIMs",
+ "permissions": [
+ {
+ "operation": "vims",
+ "value": "NA"
+ },
+ {
+ "operation": "vims:get",
+ "value": "NA"
+ },
+ {
+ "operation": "vims:post",
+ "value": "NA"
+ },
+ {
+ "operation": "vims:id:get",
+ "value": "NA"
+ },
+ {
+ "operation": "vims:id:delete",
+ "value": "NA"
+ },
+ {
+ "operation": "vims:id:patch",
+ "value": "NA"
+ }
+ ]
+ },
+ {
+ "title": "VIMs Accounts",
+ "permissions": [
+ {
+ "operation": "vim_accounts",
+ "value": "NA"
+ },
+ {
+ "operation": "vim_accounts:get",
+ "value": "NA"
+ },
+ {
+ "operation": "vim_accounts:post",
+ "value": "NA"
+ },
+ {
+ "operation": "vim_accounts:id:get",
+ "value": "NA"
+ },
+ {
+ "operation": "vim_accounts:id:delete",
+ "value": "NA"
+ },
+ {
+ "operation": "vim_accounts:id:patch",
+ "value": "NA"
+ }
+ ]
+ },
+ {
+ "title": "SDN Controllers",
+ "permissions": [
+ {
+ "operation": "sdn_controllers",
+ "value": "NA"
+ },
+ {
+ "operation": "sdn_controllers:get",
+ "value": "NA"
+ },
+ {
+ "operation": "sdn_controllers:post",
+ "value": "NA"
+ },
+ {
+ "operation": "sdn_controllers:id:get",
+ "value": "NA"
+ },
+ {
+ "operation": "sdn_controllers:id:delete",
+ "value": "NA"
+ },
+ {
+ "operation": "sdn_controllers:id:patch",
+ "value": "NA"
+ }
+ ]
+ },
+ {
+ "title": "WIMs",
+ "permissions": [
+ {
+ "operation": "wims",
+ "value": "NA"
+ },
+ {
+ "operation": "wims:get",
+ "value": "NA"
+ },
+ {
+ "operation": "wims:post",
+ "value": "NA"
+ },
+ {
+ "operation": "wims:id:get",
+ "value": "NA"
+ },
+ {
+ "operation": "wims:id:delete",
+ "value": "NA"
+ },
+ {
+ "operation": "wims:id:patch",
+ "value": "NA"
+ }
+ ]
+ },
+ {
+ "title": "WIMs Accounts",
+ "permissions": [
+ {
+ "operation": "wim_accounts",
+ "value": "NA"
+ },
+ {
+ "operation": "wim_accounts:get",
+ "value": "NA"
+ },
+ {
+ "operation": "wim_accounts:post",
+ "value": "NA"
+ },
+ {
+ "operation": "wim_accounts:id:get",
+ "value": "NA"
+ },
+ {
+ "operation": "wim_accounts:id:delete",
+ "value": "NA"
+ },
+ {
+ "operation": "wim_accounts:id:patch",
+ "value": "NA"
+ }
+ ]
+ },
+ {
+ "title": "PDUDs",
+ "permissions": [
+ {
+ "operation": "pduds",
+ "value": "NA"
+ },
+ {
+ "operation": "pduds:get",
+ "value": "NA"
+ },
+ {
+ "operation": "pduds:post",
+ "value": "NA"
+ },
+ {
+ "operation": "pduds:put",
+ "value": "NA"
+ },
+ {
+ "operation": "pduds:delete",
+ "value": "NA"
+ },
+ {
+ "operation": "pduds:patch",
+ "value": "NA"
+ },
+ {
+ "operation": "pduds:id:get",
+ "value": "NA"
+ },
+ {
+ "operation": "pduds:id:post",
+ "value": "NA"
+ },
+ {
+ "operation": "pduds:id:put",
+ "value": "NA"
+ },
+ {
+ "operation": "pduds:id:delete",
+ "value": "NA"
+ },
+ {
+ "operation": "pduds:id:patch",
+ "value": "NA"
+ }
+ ]
+ },
+ {
+ "title": "Network Slice Templates",
+ "permissions": [
+ {
+ "operation": "slice_templates",
+ "value": "NA"
+ },
+ {
+ "operation": "slice_templates:get",
+ "value": "NA"
+ },
+ {
+ "operation": "slice_templates:content:post",
+ "value": "NA"
+ },
+ {
+ "operation": "slice_templates:id:get",
+ "value": "NA"
+ },
+ {
+ "operation": "slice_templates:id:put",
+ "value": "NA"
+ },
+ {
+ "operation": "slice_templates:id:delete",
+ "value": "NA"
+ },
+ {
+ "operation": "slice_templates:id:patch",
+ "value": "NA"
+ },
+ {
+ "operation": "slice_templates:content:get",
+ "value": "NA"
+ },
+ {
+ "operation": "slice_templates:content:put",
+ "value": "NA"
+ },
+ {
+ "operation": "slice_templates:id:nst:get",
+ "value": "NA"
+ },
+ {
+ "operation": "slice_templates:id:nst_artifact:get",
+ "value": "NA"
+ }
+ ]
+ },
+ {
+ "title": "Network Slice Instances",
+ "permissions": [
+ {
+ "operation": "slice_instances",
+ "value": "NA"
+ },
+ {
+ "operation": "slice_instances:get",
+ "value": "NA"
+ },
+ {
+ "operation": "slice_instances:content:post",
+ "value": "NA"
+ },
+ {
+ "operation": "slice_instances:id:get",
+ "value": "NA"
+ },
+ {
+ "operation": "slice_instances:id:delete",
+ "value": "NA"
+ },
+ {
+ "operation": "slice_instances:post",
+ "value": "NA"
+ },
+ {
+ "operation": "slice_instances:id:instantiate:post",
+ "value": "NA"
+ },
+ {
+ "operation": "slice_instances:id:terminate:post",
+ "value": "NA"
+ },
+ {
+ "operation": "slice_instances:id:action:post",
+ "value": "NA"
+ },
+ {
+ "operation": "slice_instances:opps:get",
+ "value": "NA"
+ },
+ {
+ "operation": "slice_instances:opps:id:get",
+ "value": "NA"
+ }
+ ]
+ },
+ {
+ "title": "K8 Clusters",
+ "permissions": [
+ {
+ "operation": "k8sclusters",
+ "value": "NA"
+ },
+ {
+ "operation": "k8sclusters:get",
+ "value": "NA"
+ },
+ {
+ "operation": "k8sclusters:post",
+ "value": "NA"
+ },
+ {
+ "operation": "k8sclusters:id:get",
+ "value": "NA"
+ },
+ {
+ "operation": "k8sclusters:id:delete",
+ "value": "NA"
+ },
+ {
+ "operation": "k8sclusters:id:patch",
+ "value": "NA"
+ }
+ ]
+ },
+ {
+ "title": "K8 Repos",
+ "permissions": [
+ {
+ "operation": "k8srepos",
+ "value": "NA"
+ },
+ {
+ "operation": "k8srepos:get",
+ "value": "NA"
+ },
+ {
+ "operation": "k8srepos:post",
+ "value": "NA"
+ },
+ {
+ "operation": "k8srepos:id:get",
+ "value": "NA"
+ },
+ {
+ "operation": "k8srepos:id:delete",
+ "value": "NA"
+ }
+ ]
+ },
+ {
+ "title": "Users",
+ "permissions": [
+ {
+ "operation": "users",
+ "value": "NA"
+ },
+ {
+ "operation": "users:get",
+ "value": "NA"
+ },
+ {
+ "operation": "users:post",
+ "value": "NA"
+ },
+ {
+ "operation": "users:id:get",
+ "value": "NA"
+ },
+ {
+ "operation": "users:id:delete",
+ "value": "NA"
+ },
+ {
+ "operation": "users:id:patch",
+ "value": "NA"
+ },
+ {
+ "operation": "domains:get",
+ "value": "NA"
+ }
+ ]
+ },
+ {
+ "title": "Projects",
+ "permissions": [
+ {
+ "operation": "projects",
+ "value": "NA"
+ },
+ {
+ "operation": "projects:get",
+ "value": "NA"
+ },
+ {
+ "operation": "projects:post",
+ "value": "NA"
+ },
+ {
+ "operation": "projects:id:get",
+ "value": "NA"
+ },
+ {
+ "operation": "projects:id:patch",
+ "value": "NA"
+ },
+ {
+ "operation": "projects:id:delete",
+ "value": "NA"
+ }
+ ]
+ },
+ {
+ "title": "Roles",
+ "permissions": [
+ {
+ "operation": "roles",
+ "value": "NA"
+ },
+ {
+ "operation": "roles:get",
+ "value": "NA"
+ },
+ {
+ "operation": "roles:post",
+ "value": "NA"
+ },
+ {
+ "operation": "roles:id:get",
+ "value": "NA"
+ },
+ {
+ "operation": "roles:id:delete",
+ "value": "NA"
+ },
+ {
+ "operation": "roles:id:patch",
+ "value": "NA"
+ }
+ ]
+ },
+ {
+ "title": "Tokens",
+ "permissions": [
+ {
+ "operation": "tokens",
+ "value": "NA"
+ },
+ {
+ "operation": "tokens:get",
+ "value": "NA"
+ },
+ {
+ "operation": "tokens:post",
+ "value": "NA"
+ },
+ {
+ "operation": "tokens:delete",
+ "value": "NA"
+ },
+ {
+ "operation": "tokens:id:get",
+ "value": "NA"
+ },
+ {
+ "operation": "tokens:id:delete",
+ "value": "NA"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "OSM": "OSM",
+ "APPVERSION": "App Version",
+ "OSMVERSION": "OSM Version",
+ "OSMSOURCEMANO": "Open Source MANO",
+ "ADMIN": "Admin",
+ "ENTRIES": "Einträge",
+ "COMPOSE": "Komponieren a",
+ "CREATE": "Erstellen",
+ "SELECT": "Wählen",
+ "CANCEL": "Stornieren",
+ "SAVE": "speichern",
+ "COUNT": "Anzahl",
+ "IMAGE": "Bild",
+ "IPPROFILEREF": "IP-Profil Ref",
+ "ACTION": "Aktion",
+ "ADD": "Hinzufügen",
+ "EDIT": "Bearbeiten",
+ "APPLY": "Sich bewerben",
+ "FORCE": "Macht",
+ "DOWNLOAD": "Herunterladen",
+ "CONTENT": "Inhalt",
+ "DELETE": "Löschen",
+ "FORCEDELETE": "Löschen erzwingen",
+ "RENAME": "Umbenennen",
+ "INFO": "Info",
+ "NSPACKAGES": "NS Pakete",
+ "VNFPACKAGES": "VNF Pakete",
+ "INSTANCES": "Instanzen",
+ "INSTANTIATE": "Instanziieren",
+ "NSINSTANCES": "NS Instanzen",
+ "VNFINSTANCES": "VNF Instanzen",
+ "PDUINSTANCES": "PDU Instanzen",
+ "VIMACCOUNTS": "VIM Konten",
+ "WIMACCOUNTS": "WIM-Konten",
+ "SDNCONTROLLER": "SDN Reglerin",
+ "NETSLICE": "Netslice",
+ "PROJECT": "Projekt",
+ "DOMAIN": "Domain",
+ "PACKAGES": "Pakete",
+ "MODIFIED": "Geändert",
+ "NODATAMSG": "Keine Daten in der Tabelle verfügbar",
+ "SHORTNAME": "Kurzer Name",
+ "IDENTIFIER": "Kennung",
+ "DESCRIPTION": "Beschreibung",
+ "VENDOR": "Verkäuferin",
+ "VERSION": "Ausführung",
+ "ACTIONS": "Aktionen",
+ "NAME": "Name",
+ "USAGESTATE": "Nutzungsstatus",
+ "MODIFICATIONDATE": "Änderungsdatum",
+ "CREATEDDATE": "Erstellungsdatum",
+ "OPERATIONALSTATUS": "Betriebs Status",
+ "OPERATIONALSTATE": "Betriebszustand",
+ "CONFIGSTATUS": "Konfigurations Status",
+ "DETAILEDSTATUS": "Detaillierter Status",
+ "NSDNAME": "Nsd name",
+ "NSTNAME": "Nst name",
+ "TYPE": "Art",
+ "VNFD": "VNFD",
+ "VNF": "VNF",
+ "MEMBERINDEX": "Mitglieds Index",
+ "NS": "NS",
+ "CREATEDAT": "Hergestellt in",
+ "CREATED": "Erstellt",
+ "ALL": "Alle",
+ "ID": "Id",
+ "OPERATIONSTATE": "Betriebszustand",
+ "STARTTIME": "Startzeit",
+ "STATUSENTEREDTIME": "Status Eingegebene Zeit",
+ "HISTORYOFOPERATIONS": "Geschichte der Operationen",
+ "UPDATE": "Aktualisieren",
+ "READONLYMODE": "Nur-Lese-Modus",
+ "CURRENTLY": "Zur Zeit",
+ "ON": "Auf",
+ "OFF": "aus",
+ "IN": "im",
+ "FILES": "Dateien",
+ "NEW": "Neu",
+ "RECENTLY": "Vor kurzem",
+ "TOPOLOGY": "Topologie",
+ "PLEASEWAIT": "Warten Sie mal",
+ "LOADING": "Wird geladen",
+ "RESOURCEORCHESTRATOR": "Ressource Orchestrator",
+ "VIEW": "Aussicht",
+ "DROP": "Fallen",
+ "HERE": "Here",
+ "MAPVIEW": "Kartenansicht",
+ "LISTVIEW": "Listenansicht",
+ "OK": "Okay",
+ "DELETEDSUCCESSFULLY": "Erfolgreich gelöscht",
+ "SESSIONEXPIRY": "Sitzung abgelaufen, bitte erneut anmelden",
+ "DELETECONFIRMPOPUPMESSAGE": "Möchten Sie wirklich löschen?",
+ "DELETELOADERMESSAGE": "Bitte warten Sie, während der Löschvorgang ausgeführt wird",
+ "VALUE": "Wert",
+ "PERFORMACTION": "Aktion ausführen",
+ "EXECUTE": "Execute",
+ "EXECNSPRIMITIVE": "Exec NS Primitive",
+ "PRIMITIVETYPE": "Primitiver Typ",
+ "VNFPRIMITIVE": "VNF Level Primitive",
+ "NSPRIMITIVE": "NS Level Primitive",
+ "DESCRIPTOR": "Deskriptor",
+ "ERROR": "Etwas ist schief gelaufen. Bitte versuche es erneut",
+ "SHOWGRAPH": "Grafik anzeigen",
+ "UPDATESHOWGRAPH": "Grafik aktualisieren und anzeigen",
+ "CREATEPACKAGE": "Neues Paket erstellen",
+ "GZFILETYPEERRROR": "Laden Sie nur eine tar.gz-Datei hoch und die Größe sollte 15 MB nicht überschreiten",
+ "YAMLFILETYPEERRROR": "Laden Sie nur YAML-Dateien hoch und die Größe sollte 15 MB nicht überschreiten",
+ "JSONFILETYPEERRROR": "Laden Sie nur JSON-Dateien hoch und die Größe sollte 15 MB nicht überschreiten",
+ "PUBFILETYPEERRROR": "Laden Sie nur PUB-Dateien hoch und die Größe sollte 15 MB nicht überschreiten",
+ "PACKAGE": "Paket",
+ "URL": "URL",
+ "DEPLOYED": "Bereitgestellt",
+ "ROLES": "Rollen",
+ "INSTANCEDETAILS": "Instanzdetails",
+ "IPADDRESS": "IP Adresse",
+ "MGMT": "Mgmt",
+ "NETNAME": "Netzname",
+ "USER": "Benutzerin",
+ "PORT": "Hafen",
+ "USERNAME": "Nutzername",
+ "PASSWORD": "Passwort",
+ "NODATAERROR": "Beim Abrufen der Informationen ist ein Fehler aufgetreten",
+ "FREEZE": "Bevriezen",
+ "UNFREEZE": "Auftauen",
+ "CLONE": "Klon",
+ "CLONECONFIRMPOPUPMESSAGE": "Möchten Sie wirklich klonen",
+ "CLONESUCCESSFULLY": "Paket erfolgreich geklont",
+ "DROPFILES": "Ziehen Sie die Dateien einfach hierher oder klicken Sie hier, um sie hochzuladen",
+ "DROPFILESVALIDATION": "Bitte wählen Sie eine zu verarbeitende Datei aus",
+ "METRICS": "Metriken",
+ "NOOFHOURS": "Anzahl der Stunden",
+ "MANDATORYCHECK": "Verplichte velden zijn gemarkeerd met een sterretje (*)",
+ "K8VERSION": "K8-versie",
+ "ENTER": "Eingeben",
+ "SWITCHPROJECT": "Projekt wechseln",
+ "CURRENTPROJECT": "Derzeitiges Projekt",
+ "SUBMIT": "Submit",
+ "REFRESH": "Aktualisierung",
+ "OPEN": "Öffnen",
+ "UPLOADCONFIG": "Upload Config",
+ "FILEUPLOADLABEL": "Oder aus Datei laden",
+ "CONFIG": "Konfig",
+ "YAMLCONFIG": "Yaml Konfig",
+ "CHOOSEFILE": "Datei wählen",
+ "INVALIDCONFIG": "Ungültige Konfiguration",
+ "PAGE": {
+ "DASHBOARD": {
+ "DASHBOARD": "Instrumententafel",
+ "RECENTUSERLOG": "Letztes Benutzerprotokoll",
+ "LOGS": "Protokolle",
+ "FAILEDINSTANCES": "Fehlgeschlagene Instanzen",
+ "NOINSTANCES": "Keine Instanzen verfügbar",
+ "UPTIME": "Betriebszeit",
+ "RUNNINGINSTANCES": "Laufende Instanzen",
+ "NETSLICETEMPLATE": "NetSlice Vorlage",
+ "NETSLICEINSTANCE": "NetSlice Instanzen",
+ "USERS": "Benutzer",
+ "PROJECTS": "Projekte",
+ "USERSETTINGS": "Benutzereinstellungen",
+ "LOGOUT": "Ausloggen"
+ },
+ "LOGIN": {
+ "USERNAME": "Nutzername",
+ "PASSWORD": "Passwort",
+ "SIGNUP": "Anmelden",
+ "ACCOUNTCREATEMESSAGE": "Sie haben noch keinen Account?",
+ "LOGIN": "Anmeldung",
+ "PASSWORDVALIDMESSAGE": "Passwort wird benötigt",
+ "USERNAMEVALIDMESSAGE": "Ein Benutzername wird benötigt",
+ "SIGNINMSG": "Melden Sie sich an, um Ihre Sitzung zu starten",
+ "PASSWORDMINLENGTHVALIDMESSAGE": "Das Passwort muss aus 8 Zeichen bestehen und mindestens ein Groß-, Klein-, Ziffern- und Sonderzeichen enthalten",
+ "USERNAMEMINLENGTHVALIDMESSAGE": "Der Benutzername muss aus mindestens 5 Zeichen bestehen"
+ },
+ "INSTANCEINSTANTIATE": {
+ "NEWINSTANCE": "Neue Instanz",
+ "NSNAME": "Ns Name",
+ "DESCRIPTION": "Beschrijving",
+ "NSID": "Nsd Id",
+ "SSHKEY": "SSH-Schlüssel",
+ "VIMACCOUNT": "VIM-Konto",
+ "SSHKEYMSG": "Fügen Sie hier Ihren Schlüssel ein"
+ },
+ "NSMETRIC": {
+ "INSTANCESMETRIC": "Instanzmetrik",
+ "METRICERROR": "Daten in Metriken nicht verfügbar"
+ },
+ "USERSETTINGS": {
+ "LANGUAGE": "Sprache"
+ },
+ "VIM": {
+ "CREATEDSUCCESSFULLY": "VIM erfolgreich erstellt",
+ "LOACTIONINFO": "Geben Sie den Standortnamen ein und klicken Sie auf die Eingabetaste, um den Standort aus der Liste auszuwählen"
+ },
+ "VIMDETAILS": {
+ "NEWVIM": "Nieuwe VIM",
+ "VIMACCOUNTDETAILS": "VIM-Kontodetails",
+ "NAME": "Name",
+ "VIMUSERNAME": "VIM-Benutzername",
+ "VIMURL": "VIM-URL",
+ "VIMTYPE": "Art",
+ "TENANTNAME": "Name des Mieters",
+ "DESCRIPTION": "Beschreibung",
+ "SCHEMATYPE": "Schematyp",
+ "SCHEMAVERSION": "Schema-Version",
+ "CONFIGPARAMETERS": "KONFIG-PARAMETER",
+ "SDNCONTROLLER": "SDN-Controller",
+ "SDNPORTMAPPING": "SDN-Port-Zuordnung",
+ "VIMNETWORKNAME": "VIM-Netzwerkname",
+ "SECURITYGROUPS": "Sicherheitsgruppen",
+ "AVAILABILITYZONE": "Verfügbarkeitszone",
+ "REGIONALNAME": "Name der Region",
+ "INSECURE": "Unsicher",
+ "USEEXISTINGFLAVOURS": "Verwenden Sie vorhandene Aromen",
+ "USEINTERNALENDPOINT": "Verwenden Sie den internen Endpunkt",
+ "APIVERSION": "API-Version",
+ "PROJECTDOMAINID": "Projektdomänen-ID",
+ "PROJECTDOMAINNAME": "Projektdomänenname",
+ "USERDOMAINID": "Benutzer-Domain-ID",
+ "USERDOMAINUSER": "Benutzer-Domainname",
+ "KEYPAIR": "Schlüsselpaar",
+ "DATAPLANEPHYSICALNET": "Dataplane physikalisches Netz",
+ "USEFLOATINGIP": "Verwenden Sie Floating IP",
+ "DATAPLANENETVLANRANGE": "Dataplane Net VLAN-Bereich",
+ "MICROVERSION": "Mikroversion",
+ "BACKTOVIMACCOUNTS": "Zurück zu VimAccounts",
+ "VIMPASSWORD": "VIM-Passwort",
+ "ADDITIONALCONFIG": "Zusätzliche Konfiguration",
+ "ADDITIONALCONFIGPLACEHOLDER": "{'key1':[...],'key2':{},'key3':''}",
+ "NEWVIMACCOUNT": "Neues VIM-Konto",
+ "ORGNAME": "Orgname",
+ "VCENTERIP": "Vcenter ip",
+ "VCENTERPORT": "Vcenter-Anschluss",
+ "ADMINUSERNAME": "Admin-Benutzername",
+ "VCENTERUSER": "Vcenter-Benutzer",
+ "ADMINPASSWORD": "Administrator-Passwort",
+ "VCENTERPASSWORD": "Vcenter Passwort",
+ "NSXMANAGER": "Nsx Manager",
+ "VROPSSITE": "Vrops Seite",
+ "NSXUSER": "Nsx Benutzer",
+ "VROPSUSER": "Vrops Benutzer",
+ "NSXPASSWORD": "Nsx Passwort",
+ "VROPSPASSWORD": "Vrops Passwort",
+ "VPCCIDRBLOCK": "VPC-CIDR-Block",
+ "FLAVORIINFO": "Geschmacksinfo",
+ "VIM_TYPE": "VIM-Typ",
+ "VIMLOCATION": "VIM-Speicherort",
+ "SUBSCRIPTIONID": "Abonnement-ID",
+ "RESOURCEGROUP": "Ressourcengruppe",
+ "VNETNAME": "VNet Name",
+ "FLAVORSPATTERN": "Geschmacksmuster"
+ },
+ "WIMACCOUNTS": {
+ "CREATEDSUCCESSFULLY": "WIM erfolgreich erstellt",
+ "WIMDETAILS": "WIM-Details",
+ "NEWWIM": "Neuer WIM",
+ "SCHEMAVERSION": "Schema-Version",
+ "RO": "RO",
+ "ROACCOUNT": "RO-Konto",
+ "USERNAME": "WIM-Benutzername",
+ "PASSWORD": "WIM-Passwort"
+ },
+ "NSINSTANCE": {
+ "NEWNSINSTANCE": "Nieuwe NS",
+ "CREATEDSUCCESSFULLY": "NS-Instanz erfolgreich erstellt"
+ },
+ "VNFINSTANCE": {
+ "ADDVNFINSTANCE": "VNF-Instanz hinzufügen"
+ },
+ "PDUINSTANCE": {
+ "NEWPDUINSTANCE": "Nieuwe PDU",
+ "PDUTYPE": "PDU-Typ",
+ "PARAMETERS": "PDU-Instanzparameter",
+ "ADDINSTANCEPARAMS": "Instanzparameter hinzufügen",
+ "CREATEDSUCCESSFULLY": "PDU-Instanzen erfolgreich erstellt"
+ },
+ "NETSLICEINSTANCE": {
+ "CREATENETSLICEINSTANCE": "Maak NSI"
+ },
+ "SDNCONTROLLER": {
+ "NEWSDNCONTROLLER": "Nieuwe SDN-controller",
+ "REGISTEREDSDNCONTROLLER": "Registrierte SDN Controller",
+ "RO": "RO",
+ "DPID": "DPID",
+ "CREATEDSUCCESSFULLY": "SDN erfolgreich registriert",
+ "DPIDPLACEHOLDER": "xx:xx:xx:xx:xx:xx:xx:xx",
+ "DETAILS": "SDN-Controller-Details"
+ },
+ "USERS": {
+ "CREATEUSER": "Gebruiker aanmaken",
+ "NEWUSER": "Neuer Benutzer",
+ "USERNAME": "Nutzername",
+ "PASSWORD": "Passwort",
+ "CONFPASSWORD": "Passwort bestätigen",
+ "EDITUSER": "Benutzer bearbeiten",
+ "NEWPASSWORD": "Neues Kennwort",
+ "DEFAULTPROJECT": "Standardprojekt",
+ "PASSWORDCONFLICT": "Passwort und Passwort bestätigen stimmen nicht überein",
+ "PASSWORDMATCH": "Passwort-Übereinstimmung",
+ "CREATEDSUCCESSFULLY": "Benutzer erfolgreich erstellt",
+ "EDITEDSUCCESSFULLY": "Benutzer erfolgreich bearbeiten",
+ "EDITCREDENTIALS": "Passwort ändern",
+ "EDITUSERNAME": "Benutzernamen ändern",
+ "PROJECTSROLES": "Projekte Rollen",
+ "EDITPROJECTROLEMAPPING": "Projektrollenzuordnung bearbeiten",
+ "ADDMAPPINGS": "Mappings hinzufügen",
+ "EDITPROJECTROLEERROR": "Bitte geben Sie mindestens eine Projektrollenzuordnung an, um fortzufahren"
+ },
+ "TOPOLOGY": {
+ "SELECTELEMENT": "Element auswählen",
+ "VL": "VL",
+ "VNF": "VNF",
+ "VNFD": "VNFD",
+ "CP": "CP",
+ "NSD": "NSD",
+ "NS": "NS",
+ "VIRTUALLINK": "Virtueller Link",
+ "CONNECTIONPOINT": "Verbindungspunkt",
+ "INTCONNECTIONPOINT": "Int Verbindungspunkt",
+ "LINK": "Verknüpfung",
+ "ADDINGCP": "Bitte wählen Sie einen Verbindungspunkt von {{vnfdname}}, um {{vlname}} zu verknüpfen?",
+ "INFO": "Info",
+ "HELP": "Hilfe",
+ "HELPINFO": {
+ "CREATEEDGE": "Kante erstellen",
+ "CREATEEDGEFIRSTSETENCE": "Wählen Sie den ersten Scheitelpunkt aus, indem Sie mit darauf klicken",
+ "CREATEEDGESECONDSETENCE": "auf einem anderen Scheitelpunkt (anders als der ausgewählte).",
+ "DELETEEDGEVERTEX": "Kante / Scheitelpunkt löschen",
+ "DELETEEDGEVERTEXSENTENCE": "Doppelklicken Sie auf Kante / Scheitelpunkt.",
+ "SPREADEDGE": "Kante spreizen",
+ "SPREADEDGESENTENCE": "Wählen Sie den Scheitelpunkt aus, indem Sie mit darauf klicken",
+ "EDGEINFO": "Kanteninformationen anzeigen",
+ "EDGEINFOSENTENCE": "Wählen Sie die Kante durch Klicken aus. Die Informationen werden auf der linken Seite angezeigt."
+ },
+ "VDU": "VDU",
+ "INTVL": "IntVL",
+ "INTCP": "IntCP",
+ "DATAEMPTY": "Bitte ändere etwas"
+ },
+ "PROJECT": {
+ "NEWPROJECT": "Nieuw project",
+ "CREATEDSUCCESSFULLY": "Projekt erfolgreich erstellt",
+ "UPDATEDSUCCESSFULLY": "Projekt erfolgreich aktualisiert"
+ },
+ "NSPACKAGE": {
+ "ADDNSPACKAGE": "Verfassen Sie eine neue NS",
+ "CREATEDSUCCESSFULLY": "NS-Paket erfolgreich erstellt",
+ "NSCOMPOSE": {
+ "UPDATEDSUCCESSFULLY": "Erfolgreich geupdated",
+ "CONFIRMCONNECTIONPOINT": "Bitte bestätigen Sie, um den Verbindungspunkt hinzuzufügen",
+ "CANNOTLINKVNF": "Sie können einen VNF nicht mit einem VNF verknüpfen",
+ "CANNOTLINKVL": "Sie können eine VL nicht mit einer VL verknüpfen",
+ "CANNOTLINKVLVNF": "Sie können eine VL nicht mit einer VNF verknüpfen",
+ "CANNOTLINKVNFCP": "Sie können einen VNF nicht mit einem CP verknüpfen",
+ "CANNOTLINKVLCP": "Sie können eine VL nicht mit einem CP verknüpfen",
+ "CANNOTLINKCP": "Sie können einen CP nicht mit einem CP verknüpfen",
+ "ADDNSD": "Virtueller Link wurde erfolgreich hinzugefügt",
+ "ADDVNFD": "VNFD wurde erfolgreich hinzugefügt",
+ "ADDNS": "Der Verbindungslink wurde erfolgreich hinzugefügt",
+ "DELETENSD": "Der virtuelle Link wurde erfolgreich gelöscht",
+ "DELETEVNFD": "VNF erfolgreich gelöscht",
+ "DELETENS": "Der Verbindungspunkt wurde erfolgreich gelöscht",
+ "DELETELINK": "Der Link wurde erfolgreich gelöscht",
+ "MGMTNETWORK": "Mgmt Network",
+ "VIMNETWORKNAME": "Vim Network Name",
+ "MEMBER-VNF-INDEX": "member-vnf-index",
+ "VNFD-ID-REF": "vnfd-id-ref",
+ "VLD-ID": "vld-id",
+ "VNFD-CP-REF": "vnfd-Verbindungspunkt-ref"
+ },
+ "EDITPACKAGES": {
+ "UPDATEDSUCCESSFULLY": "Erfolgreich geupdated"
+ }
+ },
+ "VNFPACKAGE": {
+ "ADDVNFPACKAGE": "Erstellen Sie eine neue VNF",
+ "CREATEDSUCCESSFULLY": "VNF-Paket erfolgreich erstellt",
+ "VNFCOMPOSE": {
+ "UPDATEDSUCCESSFULLY": "Erfolgreich geupdated",
+ "INVALIDSELECTION": "Ungültige Auswahl",
+ "YOUCANNOTDELETELINK": "Sie können den Link nicht löschen",
+ "CANNOTLINKVDUANDINTCP": "Sie können vdu nicht mit int_cp verknüpfen",
+ "CANNOTLINKINTCPANDVDU": "Sie können int_cp nicht mit vdu verknüpfen",
+ "CANNOTLINKCPANDVNFVL": "Sie können cp nicht mit vnf_vl verknüpfen",
+ "CANNOTLINKVNFVLANDCP": "Sie können vnf_vl nicht mit cp verknüpfen",
+ "CANNOTLINKINTCPANDCP": "Sie können intcp nicht mit cp verknüpfen",
+ "CANNOTLINKCPANDINTCP": "Sie können cp nicht mit int_cp verknüpfen",
+ "CANNOTLINKVDUANDVDU": "Sie können ein vdu nicht mit einem vdu verknüpfen"
+ }
+ },
+ "NETSLICE": {
+ "CREATEDSUCCESSFULLY": "Netslice erfolgreich erstellt",
+ "TEMPLATECREATEDSUCCESSFULLY": "Netslice-Vorlage erfolgreich erstellt",
+ "UPDATEDSUCCESSFULLY": "Vorlage erfolgreich aktualisiert"
+ },
+ "NETSLICETEMPLATE": {
+ "NETSLICETEMPLATEDETAILS": "Netzwerk-Slices-Vorlagendetails"
+ },
+ "NSTINSTANCEINSTANTIATE": {
+ "NEWINSTANCE": "Neue Instanz",
+ "NSNAME": "Ns Name",
+ "DESCRIPTION": "Beschrijving",
+ "NSTID": "Nst Id",
+ "SSHKEY": "SSH-Schlüssel",
+ "VIMACCOUNT": "VIM-Konto",
+ "SSHKEYMSG": "Fügen Sie Ihren Schlüssel hier ein ..."
+ },
+ "NSPRIMITIVE": {
+ "PRIMITIVE": "Primitive",
+ "PRIMITIVEPARAMETERS": "Primitive Parameter",
+ "ADDPRIMITIVEPARAMS": "Primitive Parameter hinzufügen",
+ "EXECUTEDSUCCESSFULLY": "NS Primitive Configuration ausgeführt"
+ },
+ "ROLES": {
+ "CREATEROLE": "Rolle erstellen",
+ "ROLE": "Rolle",
+ "PERMISSIONS": "Berechtigungen",
+ "YAMLPERMISSIONS": "YAML Berechtigungen",
+ "CREATEDSUCCESSFULLY": "Rolle erfolgreich erstellt",
+ "UPDATEDSUCCESSFULLY": "Rolle erfolgreich aktualisiert",
+ "ROLEJSONERROR": "Rollenberechtigungen sollten in einer Schlüsselwertweise bereitgestellt werden",
+ "ROLEKEYERROR": "Der Wert von '{{roleKey}}' in Rollenberechtigungen sollte boolesch sein",
+ "EDITROLE": "Rolle bearbeiten",
+ "PREVIEW": "Vorschau",
+ "TEXTVIEW": "Textvorschau"
+ },
+ "K8S": {
+ "MENUK8S": "K8s",
+ "MENUK8SCLUSTER": "K8s Clusters",
+ "MENUK8SREPO": "K8s Repos",
+ "REGISTERK8CLUSTER": "Geregistreerde K8s-clusters",
+ "ADDK8CLUSTER": "K8s-cluster toevoegen",
+ "K8SCLUSTERDETAILS": "K8s Clusterdetails",
+ "REGISTERK8REPO": "Geregistreerde K8s-repository",
+ "ADDK8REPO": "K8s Repository toevoegen",
+ "K8SREPODETAILS": "K8s Repository Details",
+ "CREATEDSUCCESSFULLY": "K8s met succes gemaakt",
+ "NEWK8SCLUSTER": "Nieuw K8s-cluster",
+ "NAME": "Naam",
+ "K8SVERSION": "K8s-versie",
+ "VIMACCOUNT": "Vim-account",
+ "DESCRIPTION": "Beschrijving",
+ "NETS": "Nets",
+ "NETSPLACEHOLDER": "example: {'net1': 'osm-ext'}",
+ "CREDENTIALS": "Inloggegevens",
+ "NEWK8SREPO": "Nieuwe K8s Repository",
+ "TYPE": "Type",
+ "URL": "URL"
+ }
+ },
+ "HTTPERROR": {
+ "401": "Zugriff verweigert",
+ "400": "Bitte überprüfen Sie die Anfrage und versuchen Sie es erneut",
+ "404": "Erwarteter Dienst nicht verfügbar. Bitte versuchen Sie es später erneut.",
+ "500": "Serverfehler, Bitte versuchen Sie es später noch einmal",
+ "502": "Slechte gateway, probeer het later opnieuw",
+ "503": "Dienst vorübergehend nicht verfügbar. Bitte versuchen Sie es später erneut.",
+ "504": "Gateway timeout fehler. Bitte versuchen Sie es später erneut",
+ "409": "Bitte versuchen Sie es später noch einmal."
+ },
+ "PAGENOTFOUND": {
+ "OOPS": "Hoppla!",
+ "NOTFOUND": "404 Nicht gefunden",
+ "CONTENT": "Die Seite kann nicht gefunden oder nicht autorisiert werden, ist möglicherweise nicht mehr relevant oder hat ihren Namen geändert",
+ "MEAN": "In der Zwischenzeit können Sie zu zurückkehren",
+ "HOME": "Zuhause"
+ },
+ "DOMVALIDATIONS": {
+ "INVALIDURL": "Geben Sie eine gültige URL ein",
+ "INVALIDIPADDRESS": "Geben Sie eine gültige IP-Adresse ein",
+ "INVALIDPORTADDRESS": "Geben Sie eine gültige PORT-Adresse ein",
+ "INVALIDDPID": "Geben Sie eine gültige DPID ein",
+ "INVALIDJSON": "Geben Sie ein gültiges JSON-Format ein",
+ "INVALIDYAML": "Geben Sie ein gültiges YAML-Format ein"
+ },
+ "GRAFANA": {
+ "METRICSERROR": "Keine gültigen Metriken"
+ }
+}
\ No newline at end of file
--- /dev/null
+{
+ "OSM": "OSM",
+ "APPVERSION": "App Version",
+ "OSMVERSION": "OSM Version",
+ "OSMSOURCEMANO": "Open Source MANO",
+ "ADMIN": "Admin",
+ "ENTRIES": "Entries",
+ "COMPOSE": "Compose a",
+ "CREATE": "Create",
+ "SELECT": "Select",
+ "CANCEL": "Cancel",
+ "SAVE": "Save",
+ "ACTION": "Action",
+ "COUNT": "Count",
+ "IMAGE": "Image",
+ "IPPROFILEREF": "IP Profile Ref",
+ "ADD": "Add",
+ "EDIT": "Edit",
+ "APPLY": "Apply",
+ "FORCE": "Force",
+ "DOWNLOAD": "Download",
+ "CONTENT": "Content",
+ "DELETE": "Delete",
+ "FORCEDELETE": "Force Delete",
+ "RENAME": "Rename",
+ "INFO": "Info",
+ "NSPACKAGES": "NS Packages",
+ "VNFPACKAGES": "VNF Packages",
+ "INSTANCES": "Instances",
+ "INSTANTIATE": "Instantiate",
+ "NSINSTANCES": "NS Instances",
+ "VNFINSTANCES": "VNF Instances",
+ "PDUINSTANCES": "PDU Instances",
+ "VIMACCOUNTS": "VIM Accounts",
+ "WIMACCOUNTS": "WIM Accounts",
+ "SDNCONTROLLER": "SDN Controller",
+ "NETSLICE": "Netslice",
+ "PROJECT": "Project",
+ "DOMAIN": "Domain",
+ "PACKAGES": "Packages",
+ "MODIFIED": "Modified",
+ "NODATAMSG": "No data available in table",
+ "SHORTNAME": "Short Name",
+ "IDENTIFIER": "Identifier",
+ "DESCRIPTION": "Description",
+ "VENDOR": "Vendor",
+ "VERSION": "Version",
+ "ACTIONS": "Actions",
+ "NAME": "Name",
+ "USAGESTATE": "UsageState",
+ "MODIFICATIONDATE": "Modification Date",
+ "CREATEDDATE": "Creation Date",
+ "OPERATIONALSTATUS": "Operational Status",
+ "OPERATIONALSTATE": "Operational State",
+ "CONFIGSTATUS": "Config Status",
+ "DETAILEDSTATUS": "Detailed Status",
+ "NSDNAME": "Nsd name",
+ "NSTNAME": "Nst name",
+ "TYPE": "Type",
+ "VNFD": "VNFD",
+ "VNF": "VNF",
+ "MEMBERINDEX": "Member Index",
+ "NS": "NS",
+ "CREATEDAT": "Created At",
+ "CREATED": "Created",
+ "ALL": "All",
+ "ID": "Id",
+ "OPERATIONSTATE": "Operation State",
+ "STARTTIME": "Start Time",
+ "STATUSENTEREDTIME": "Status Entered Time",
+ "HISTORYOFOPERATIONS": "History Of Operations",
+ "UPDATE": "Update",
+ "READONLYMODE": "Read only mode",
+ "CURRENTLY": "Currently",
+ "ON": "On",
+ "OFF": "Off",
+ "IN": "in",
+ "FILES": "Files",
+ "NEW": "New",
+ "RECENTLY": "Recently",
+ "TOPOLOGY": "Topology",
+ "PLEASEWAIT": "Please Wait",
+ "LOADING": "Loading",
+ "RESOURCEORCHESTRATOR": "Resource Orchestrator",
+ "VIEW": "View",
+ "DROP": "Drop",
+ "HERE": "Here",
+ "MAPVIEW": "Map View",
+ "LISTVIEW": "List View",
+ "OK": "Ok",
+ "DELETEDSUCCESSFULLY": "{{title}} deleted successfully",
+ "SESSIONEXPIRY": "Session expired, please login again",
+ "DELETECONFIRMPOPUPMESSAGE": "Are you sure want to delete",
+ "DELETELOADERMESSAGE": "Please wait while {{title}} deletion is in progress",
+ "VALUE": "Value",
+ "PERFORMACTION": "Perform Action",
+ "EXECUTE": "Execute",
+ "EXECNSPRIMITIVE": "Exec NS Primitive",
+ "PRIMITIVETYPE": "Primitive Type",
+ "VNFPRIMITIVE": "VNF Level Primitive",
+ "NSPRIMITIVE": "NS Level Primitive",
+ "DESCRIPTOR": "Descriptor",
+ "ERROR": "Something Went wrong please try again",
+ "SHOWGRAPH": "Show Graph",
+ "UPDATESHOWGRAPH": "Update and Show Graph",
+ "CREATEPACKAGE": "Create New Package",
+ "GZFILETYPEERRROR": "Upload only tar.gz file and size should not exceed 15 MB",
+ "YAMLFILETYPEERRROR": "Upload only YAML file and size should not exceed 15 MB",
+ "JSONFILETYPEERRROR": "Upload only JSON file and size should not exceed 15 MB",
+ "PUBFILETYPEERRROR": "Upload only PUB file and size should not exceed 15 MB",
+ "PACKAGE": "Package",
+ "URL": "URL",
+ "DEPLOYED": "Deployed",
+ "ROLES": "Roles",
+ "INSTANCEDETAILS": "Instance Details",
+ "IPADDRESS": "IP Address",
+ "MGMT": "Mgmt",
+ "NETNAME": "Net Name",
+ "USER": "User",
+ "PORT": "Port",
+ "USERNAME": "Username",
+ "PASSWORD": "Password",
+ "NODATAERROR": "An error occurred while retrieving the information",
+ "FREEZE": "Freeze",
+ "UNFREEZE": "Unfreeze",
+ "CLONE": "Clone",
+ "CLONECONFIRMPOPUPMESSAGE": "Are you sure want to clone",
+ "CLONESUCCESSFULLY": "Package cloned successfully",
+ "DROPFILES": "Just drag and drop files or click here to upload files",
+ "DROPFILESVALIDATION": "Please select one file to process",
+ "METRICS": "Metrics",
+ "NOOFHOURS": "No Of Hours",
+ "MANDATORYCHECK": "Mandatory fields are marked with an asterisk (*)",
+ "K8VERSION": "K8 Version",
+ "ENTER": "Enter",
+ "SWITCHPROJECT": "Switch Project",
+ "CURRENTPROJECT": "Current Project",
+ "SUBMIT": "Submit",
+ "REFRESH": "Refresh",
+ "OPEN": "Open",
+ "UPLOADCONFIG": "Upload Config",
+ "FILEUPLOADLABEL": "Or load from file",
+ "CONFIG": "Config",
+ "YAMLCONFIG": "Yaml Config",
+ "CHOOSEFILE": "Choose File",
+ "INVALIDCONFIG": "Invalid configuration",
+ "PAGE": {
+ "DASHBOARD": {
+ "DASHBOARD": "Dashboard",
+ "RECENTUSERLOG": "Recent User Log",
+ "LOGS": "Logs",
+ "FAILEDINSTANCES": "Failed Instances",
+ "NOINSTANCES": "No Instances Available",
+ "UPTIME": "Uptime",
+ "RUNNINGINSTANCES": "Running Instances",
+ "NETSLICETEMPLATE": "NetSlice Template",
+ "NETSLICEINSTANCE": "NetSlice Instances",
+ "USERS": "Users",
+ "PROJECTS": "Projects",
+ "USERSETTINGS": "User Settings",
+ "LOGOUT": "Logout"
+ },
+ "LOGIN": {
+ "USERNAME": "Username",
+ "PASSWORD": "Password",
+ "SIGNUP": "Sign Up",
+ "ACCOUNTCREATEMESSAGE": "Don't have an account?",
+ "LOGIN": "Log In",
+ "PASSWORDVALIDMESSAGE": "Password is required",
+ "USERNAMEVALIDMESSAGE": "Username is required",
+ "SIGNINMSG": "Sign in to start your session",
+ "PASSWORDMINLENGTHVALIDMESSAGE": "Password must be 8 characters and contains at least one upper case, lower case, numeric & special character",
+ "USERNAMEMINLENGTHVALIDMESSAGE": "Username must be at least 5 characters"
+ },
+ "INSTANCEINSTANTIATE": {
+ "NEWINSTANCE": "New Instance",
+ "NSNAME": "Ns Name",
+ "DESCRIPTION": "Description",
+ "NSID": "Nsd Id",
+ "SSHKEY": "SSH Key",
+ "VIMACCOUNT": "VIM Account",
+ "SSHKEYMSG": "Paste your key here"
+ },
+ "NSMETRIC": {
+ "INSTANCESMETRIC": "Instances Metric",
+ "METRICERROR": "Data not available in metrics"
+ },
+ "USERSETTINGS": {
+ "LANGUAGE": "Language"
+ },
+ "VIM": {
+ "CREATEDSUCCESSFULLY": "VIM Created Successfully",
+ "LOACTIONINFO": "Type the location name and click enter button to select the location from the list"
+ },
+ "VIMDETAILS": {
+ "NEWVIM": "New VIM",
+ "VIMACCOUNTDETAILS": "VIM Account details",
+ "NAME": "Name",
+ "VIMUSERNAME": "VIM Username",
+ "VIMURL": "VIM URL",
+ "VIMTYPE": "Type",
+ "TENANTNAME": "Tenant name",
+ "DESCRIPTION": "Description",
+ "SCHEMATYPE": "Schema Type",
+ "SCHEMAVERSION": "Schema Version",
+ "CONFIGPARAMETERS": "CONFIG PARAMETERS",
+ "SDNCONTROLLER": "SDN Controller",
+ "SDNPORTMAPPING": "SDN Port Mapping",
+ "VIMNETWORKNAME": "VIM Network Name",
+ "SECURITYGROUPS": "Security Groups",
+ "AVAILABILITYZONE": "Availability Zone",
+ "REGIONALNAME": "Region Name",
+ "INSECURE": "Insecure",
+ "USEEXISTINGFLAVOURS": "Use existing flavors",
+ "USEINTERNALENDPOINT": "Use internal endpoint",
+ "APIVERSION": "API version",
+ "PROJECTDOMAINID": "Project domain id",
+ "PROJECTDOMAINNAME": "Project domain name",
+ "USERDOMAINID": "User domain id",
+ "USERDOMAINUSER": "User domain name",
+ "KEYPAIR": "Keypair",
+ "DATAPLANEPHYSICALNET": "Dataplane physical net",
+ "USEFLOATINGIP": "Use floating ip",
+ "DATAPLANENETVLANRANGE": "Dataplane net vlan range",
+ "MICROVERSION": "Microversion",
+ "BACKTOVIMACCOUNTS": "Back to VimAccounts",
+ "VIMPASSWORD": "VIM Password",
+ "ADDITIONALCONFIG": "Additional configuration",
+ "ADDITIONALCONFIGPLACEHOLDER": "{'key1':[...],'key2':{},'key3':''}",
+ "NEWVIMACCOUNT": "New VIM Account",
+ "ORGNAME": "Orgname",
+ "VCENTERIP": "Vcenter ip",
+ "VCENTERPORT": "Vcenter port",
+ "ADMINUSERNAME": "Admin username",
+ "VCENTERUSER": "Vcenter user",
+ "ADMINPASSWORD": "Admin password",
+ "VCENTERPASSWORD": "Vcenter password",
+ "NSXMANAGER": "Nsx manager",
+ "VROPSSITE": "Vrops site",
+ "NSXUSER": "Nsx user",
+ "VROPSUSER": "Vrops user",
+ "NSXPASSWORD": "Nsx password",
+ "VROPSPASSWORD": "Vrops password",
+ "VPCCIDRBLOCK": "VPC cidr block",
+ "FLAVORIINFO": "Flavor info",
+ "VIM_TYPE": "VIM Type",
+ "VIMLOCATION": "VIM Location",
+ "SUBSCRIPTIONID": "Subscription ID",
+ "RESOURCEGROUP": "Resource Group",
+ "VNETNAME": "VNet Name",
+ "FLAVORSPATTERN": "Flavors Pattern"
+ },
+ "WIMACCOUNTS": {
+ "CREATEDSUCCESSFULLY": "WIM Created Successfully",
+ "WIMDETAILS": "WIM Details",
+ "NEWWIM": "New WIM",
+ "SCHEMAVERSION": "Schema Version",
+ "RO": "RO",
+ "ROACCOUNT": "RO Account",
+ "USERNAME": "WIM Username",
+ "PASSWORD": "WIM Password"
+ },
+ "NSINSTANCE": {
+ "NEWNSINSTANCE": "New NS",
+ "CREATEDSUCCESSFULLY": "NS Instance Created Successfully"
+ },
+ "VNFINSTANCE": {
+ "ADDVNFINSTANCE": "Add VNF Instance"
+ },
+ "PDUINSTANCE": {
+ "NEWPDUINSTANCE": "New PDU",
+ "PDUTYPE": "PDU Type",
+ "PARAMETERS": "PDU Instances Parameters",
+ "ADDINSTANCEPARAMS": "Add Params",
+ "CREATEDSUCCESSFULLY": "PDU Instances Created Successfully"
+ },
+ "NETSLICEINSTANCE": {
+ "CREATENETSLICEINSTANCE": "Create NSI"
+ },
+ "SDNCONTROLLER": {
+ "NEWSDNCONTROLLER": "New SDN Controller",
+ "REGISTEREDSDNCONTROLLER": "Registered SDN Controllers",
+ "RO": "RO",
+ "DPID": "DPID",
+ "CREATEDSUCCESSFULLY": "SDN Registered Successfully",
+ "DPIDPLACEHOLDER": "xx:xx:xx:xx:xx:xx:xx:xx",
+ "DETAILS": "SDN Controller Details"
+ },
+ "USERS": {
+ "CREATEUSER": "Create User",
+ "NEWUSER": "New User",
+ "USERNAME": "User Name",
+ "PASSWORD": "Password",
+ "CONFPASSWORD": "Confirm Password",
+ "EDITUSER": "Edit User",
+ "NEWPASSWORD": "New Password",
+ "DEFAULTPROJECT": "Default Project",
+ "PASSWORDCONFLICT": "Password and confirm password are not matched",
+ "PASSWORDMATCH": "Password Match",
+ "CREATEDSUCCESSFULLY": "User Created Successfully",
+ "EDITEDSUCCESSFULLY": "User Edit Successfully",
+ "EDITCREDENTIALS": "Change Password",
+ "EDITUSERNAME": "Change Username",
+ "PROJECTSROLES": "Projects Roles",
+ "EDITPROJECTROLEMAPPING": "Edit Project Role Mapping",
+ "ADDMAPPINGS": "Add Mappings",
+ "EDITPROJECTROLEERROR": "Please provide at least one project role mapping to continue"
+ },
+ "TOPOLOGY": {
+ "SELECTELEMENT": "Select Element",
+ "VL": "VL",
+ "VNF": "VNF",
+ "VNFD": "VNFD",
+ "CP": "CP",
+ "NSD": "NSD",
+ "NS": "NS",
+ "VIRTUALLINK": "Virtual Link",
+ "CONNECTIONPOINT": "Connection Point",
+ "INTCONNECTIONPOINT": "Int Connection Point",
+ "LINK": "Link",
+ "ADDINGCP": "Please select a connection point of {{vnfdname}} to link {{vlname}}?",
+ "INFO": "Info",
+ "HELP": "Help",
+ "HELPINFO": {
+ "CREATEEDGE": "Create edge",
+ "CREATEEDGEFIRSTSETENCE": "Select the first vertex by clicking on it using",
+ "CREATEEDGESECONDSETENCE": "on another vertex (different than the selected one).",
+ "DELETEEDGEVERTEX": "Delete edge/vertex",
+ "DELETEEDGEVERTEXSENTENCE": "Double clicking on edge/vertex.",
+ "SPREADEDGE": "Spread edge",
+ "SPREADEDGESENTENCE": "Select the vertex by clicking on it using",
+ "EDGEINFO": "Show edge information",
+ "EDGEINFOSENTENCE": "Select the edge by clicking. The information will be shown on the left side."
+ },
+ "VDU": "VDU",
+ "INTVL": "IntVL",
+ "INTCP": "IntCP",
+ "DATAEMPTY": "Please change something"
+ },
+ "PROJECT": {
+ "NEWPROJECT": "New Project",
+ "CREATEDSUCCESSFULLY": "Project Created Successfully",
+ "UPDATEDSUCCESSFULLY": "Project Updated Successfully"
+ },
+ "NSPACKAGE": {
+ "ADDNSPACKAGE": "Compose a new NS",
+ "CREATEDSUCCESSFULLY": "NS Package Created Successfully",
+ "NSCOMPOSE": {
+ "UPDATEDSUCCESSFULLY": "Descriptor Updated Successfully",
+ "CONFIRMCONNECTIONPOINT": "Please confirm to add connection point",
+ "CANNOTLINKVNF": "You can't link a vnf with a vnf",
+ "CANNOTLINKVL": "You can't link a VL with a VL",
+ "CANNOTLINKVLVNF": "You can't link a VL with a vnf",
+ "CANNOTLINKVNFCP": "You can't link a VNF with a CP",
+ "CANNOTLINKVLCP": "You can't link a VL with a CP",
+ "CANNOTLINKCP": "You can't link a CP with a CP",
+ "ADDNSD": "Virtual Link is added succesfully",
+ "ADDVNFD": "VNFD is added succesfully",
+ "ADDNS": "Connection Link is added succesfully",
+ "DELETENSD": "Successfully Deleted the Virtual Link",
+ "DELETEVNFD": "Successfully Deleted the VNF",
+ "DELETENS": "Successfully Deleted the Connection point",
+ "DELETELINK": "Successfully Deleted the Link",
+ "MGMTNETWORK": "Mgmt Network",
+ "VIMNETWORKNAME": "Vim Network Name",
+ "MEMBER-VNF-INDEX": "member-vnf-index",
+ "VNFD-ID-REF": "vnfd-id-ref",
+ "VLD-ID": "vld-id",
+ "VNFD-CP-REF": "vnfd-connection-point-ref"
+ },
+ "EDITPACKAGES": {
+ "UPDATEDSUCCESSFULLY": "Descriptor Updated Successfully"
+ }
+ },
+ "VNFPACKAGE": {
+ "ADDVNFPACKAGE": "Compose a new VNF",
+ "CREATEDSUCCESSFULLY": "VNF Package Created Successfully",
+ "VNFCOMPOSE": {
+ "UPDATEDSUCCESSFULLY": "Descriptor Updated Successfully",
+ "INVALIDSELECTION": "Invalid Selection",
+ "YOUCANNOTDELETELINK": "You cannot delete link",
+ "CANNOTLINKVDUANDINTCP": "You cant link vdu with int_cp",
+ "CANNOTLINKINTCPANDVDU": "You cant link int_cp with vdu",
+ "CANNOTLINKCPANDVNFVL": "You cant link cp with vnf_vl",
+ "CANNOTLINKVNFVLANDCP": "You cant link vnf_vl with cp",
+ "CANNOTLINKINTCPANDCP": "You cant link intcp with cp",
+ "CANNOTLINKCPANDINTCP": "You cant link cp with int_cp",
+ "CANNOTLINKVDUANDVDU": "You can't link a vdu with a vdu"
+ }
+ },
+ "NETSLICE": {
+ "CREATEDSUCCESSFULLY": "Netslice Created Successfully",
+ "TEMPLATECREATEDSUCCESSFULLY": "Netslice Template Created Successfully",
+ "UPDATEDSUCCESSFULLY": "Template Updated Successfully"
+ },
+ "NETSLICETEMPLATE": {
+ "NETSLICETEMPLATEDETAILS": "Network Slices Template Details"
+ },
+ "NSTINSTANCEINSTANTIATE": {
+ "NEWINSTANCE": "New Instance",
+ "NSNAME": "Ns Name",
+ "DESCRIPTION": "Description",
+ "NSTID": "Nst Id",
+ "SSHKEY": "SSH Key",
+ "VIMACCOUNT": "VIM Account",
+ "SSHKEYMSG": "Paste your key here ..."
+ },
+ "NSPRIMITIVE": {
+ "PRIMITIVE": "Primitive",
+ "PRIMITIVEPARAMETERS": "Primitive Parameters",
+ "ADDPRIMITIVEPARAMS": "Add Primitive Params",
+ "EXECUTEDSUCCESSFULLY": "Executed NS Primitive Configuration"
+ },
+ "ROLES": {
+ "CREATEROLE": "Create Role",
+ "ROLE": "Role",
+ "PERMISSIONS": "Permissions",
+ "YAMLPERMISSIONS": "YAML Permissions",
+ "CREATEDSUCCESSFULLY": "Role Created Successfully",
+ "UPDATEDSUCCESSFULLY": "Role Updated Successfully",
+ "ROLEJSONERROR": "Role permissions should be provided in a key-value fashion",
+ "ROLEKEYERROR": "Value of '{{roleKey}}' in a role permissions should be boolean",
+ "EDITROLE": "Edit Role",
+ "PREVIEW": "Preview",
+ "TEXTVIEW": "Text View"
+ },
+ "K8S": {
+ "MENUK8S": "K8s",
+ "MENUK8SCLUSTER": "K8s Clusters",
+ "MENUK8SREPO": "K8s Repos",
+ "REGISTERK8CLUSTER": "Registered K8s clusters",
+ "ADDK8CLUSTER": "Add K8s Cluster",
+ "K8SCLUSTERDETAILS": "K8s Cluster Details",
+ "REGISTERK8REPO": "Registered K8s repository",
+ "ADDK8REPO": "Add K8s Repository",
+ "K8SREPODETAILS": "K8s Repository Details",
+ "CREATEDSUCCESSFULLY": "K8s Created Successfully",
+ "NEWK8SCLUSTER": "New K8s Cluster",
+ "NAME": "Name",
+ "K8SVERSION": "K8s Version",
+ "VIMACCOUNT": "Vim Account",
+ "DESCRIPTION": "Description",
+ "NETS": "Nets",
+ "NETSPLACEHOLDER": "example: {'net1': 'osm-ext'}",
+ "CREDENTIALS": "Credentials",
+ "NEWK8SREPO": "New K8s Repository",
+ "TYPE": "Type",
+ "URL": "URL"
+ }
+ },
+ "HTTPERROR": {
+ "401": "Access denied, Lack of permissions",
+ "400": "Please check the request and try again",
+ "404": "Expected service not avilable, Please try again later",
+ "500": "Server error, Please try again later",
+ "502": "Bad Gateway, Please try again later",
+ "503": "Service temporarily unavailable, Please try again later",
+ "504": "Gateway timeout error, Please try again later",
+ "409": "Please try again later"
+ },
+ "PAGENOTFOUND": {
+ "OOPS": "Oops!",
+ "NOTFOUND": "404 Not Found",
+ "CONTENT": "The page cannot be found or unauthorized, it might be no longer relevant or had its name changed",
+ "MEAN": "Meanwhile, you may return to",
+ "HOME": "Home"
+ },
+ "DOMVALIDATIONS": {
+ "INVALIDURL": "Enter a valid URL",
+ "INVALIDIPADDRESS": "Enter a valid IP Address",
+ "INVALIDPORTADDRESS": "Enter a valid PORT Address",
+ "INVALIDDPID": "Enter a valid DPID",
+ "INVALIDJSON": "Enter a valid JSON Format",
+ "INVALIDYAML": "Enter a valid JSON Format"
+ },
+ "GRAFANA": {
+ "METRICSERROR": "Not a valid metrics"
+ }
+}
\ No newline at end of file
--- /dev/null
+{
+ "OSM": "OSM",
+ "APPVERSION": "Versión de la aplicación",
+ "OSMVERSION": "Versión OSM",
+ "OSMSOURCEMANO": "Fuente abierta MANO",
+ "ADMIN": "Admin",
+ "ENTRIES": "entradas",
+ "COMPOSE": "Componer un",
+ "CREATE": "Crear",
+ "SELECT": "Seleccionar",
+ "CANCEL": "Cancelar",
+ "SAVE": "Salvar",
+ "COUNT": "contar",
+ "IMAGE": "Imagen",
+ "IPPROFILEREF": "IP Profile Ref",
+ "ACTION": "Acción",
+ "ADD": "Añadir",
+ "EDIT": "Editar",
+ "APPLY": "Aplicar",
+ "FORCE": "Fuerza",
+ "DOWNLOAD": "Descargar",
+ "CONTENT": "contenido",
+ "DELETE": "Borrar",
+ "FORCEDELETE": "Eliminar forzado",
+ "RENAME": "Rebautizar",
+ "INFO": "Info",
+ "NSPACKAGES": "NS Paquetes",
+ "VNFPACKAGES": "VNF Paquetes",
+ "INSTANCES": "Instancias",
+ "INSTANTIATE": "Instanciar",
+ "NSINSTANCES": "Instancias de NS",
+ "VNFINSTANCES": "Instancias VNF",
+ "PDUINSTANCES": "Instancias PDU",
+ "VIMACCOUNTS": "Cuentas VIM",
+ "WIMACCOUNTS": "Cuentas WIM",
+ "SDNCONTROLLER": "Controlador SDN",
+ "NETSLICE": "Netslice",
+ "PROJECT": "Proyecto",
+ "DOMAIN": "Dominio",
+ "PACKAGES": "Paquetes",
+ "MODIFIED": "Modificado",
+ "NODATAMSG": "No hay datos disponibles en la tabla",
+ "SHORTNAME": "Nombre corto",
+ "IDENTIFIER": "Identificador",
+ "DESCRIPTION": "Descripción",
+ "VENDOR": "Vendedor",
+ "VERSION": "Versión",
+ "ACTIONS": "Comportamiento",
+ "NAME": "NOMBRE",
+ "USAGESTATE": "Estado de uso",
+ "MODIFICATIONDATE": "Fecha de modificación",
+ "CREATEDDATE": "Fecha de creación",
+ "OPERATIONALSTATUS": "Estado operativo",
+ "OPERATIONALSTATE": "Estado operacional",
+ "CONFIGSTATUS": "Estado de configuración",
+ "DETAILEDSTATUS": "Estado detallado",
+ "NSDNAME": "Nombre nsd",
+ "NSTNAME": "Nst name",
+ "TYPE": "Tipo",
+ "VNFD": "VNFD",
+ "VNF": "VNF",
+ "MEMBERINDEX": "Índice de miembros",
+ "NS": "NS",
+ "CREATEDAT": "Creado en",
+ "CREATED": "Creado",
+ "ALL": "Todas",
+ "ID": "Id",
+ "OPERATIONSTATE": "Estado de la operación",
+ "STARTTIME": "Hora de inicio",
+ "STATUSENTEREDTIME": "Tiempo ingresado estado",
+ "HISTORYOFOPERATIONS": "Historia de operaciones",
+ "UPDATE": "Actualizar",
+ "READONLYMODE": "Modo de solo lectura",
+ "CURRENTLY": "Actualmente",
+ "ON": "En",
+ "OFF": "APAGADA",
+ "IN": "en",
+ "FILES": "Archivos",
+ "NEW": "Nueva",
+ "RECENTLY": "Recientemente",
+ "TOPOLOGY": "Topología",
+ "PLEASEWAIT": "Por favor espera",
+ "LOADING": "Cargando",
+ "RESOURCEORCHESTRATOR": "Orquestador de recursos",
+ "VIEW": "Ver",
+ "DROP": "soltar",
+ "HERE": "aquí",
+ "MAPVIEW": "Vista del mapa",
+ "LISTVIEW": "Vista de la lista",
+ "OK": "Okay",
+ "DELETEDSUCCESSFULLY": "Eliminada Exitosamente",
+ "SESSIONEXPIRY": "Sesión expirada, por favor ingrese nuevamente",
+ "DELETECONFIRMPOPUPMESSAGE": "¿Seguro que quieres eliminar?",
+ "DELETELOADERMESSAGE": "Por favor espere mientras la eliminación está en progreso",
+ "VALUE": "Valor",
+ "PERFORMACTION": "Realizar una acción",
+ "EXECUTE": "Ejecutar",
+ "EXECNSPRIMITIVE": "Ejecutar NS Primitiva",
+ "PRIMITIVETYPE": "Tipo primitivo",
+ "VNFPRIMITIVE": "Nivel VNF Primitivo",
+ "NSPRIMITIVE": "NS Level Primitive",
+ "DESCRIPTOR": "Descriptora",
+ "ERROR": "Algo salió mal. Por favor, vuelva a intentarlo",
+ "SHOWGRAPH": "Mostrar gráfico",
+ "UPDATESHOWGRAPH": "Actualizar y mostrar gráfico",
+ "CREATEPACKAGE": "Crear nuevo paquete",
+ "GZFILETYPEERRROR": "Cargue solo el archivo tar.gz y el tamaño no debe exceder los 15 MB",
+ "YAMLFILETYPEERRROR": "Cargue solo el archivo YAML y el tamaño no debe exceder los 15 MB",
+ "JSONFILETYPEERRROR": "Cargue solo el archivo JSON y el tamaño no debe exceder los 15 MB",
+ "PUBFILETYPEERRROR": "Cargue solo el archivo PUB y el tamaño no debe exceder los 15 MB",
+ "PACKAGE": "Paquete",
+ "URL": "URL",
+ "DEPLOYED": "Desplegada",
+ "ROLES": "Roles",
+ "INSTANCEDETAILS": "Detalles de instancia",
+ "IPADDRESS": "Dirección IP",
+ "MGMT": "Mgmt",
+ "NETNAME": "Nombre neto",
+ "USER": "Usuaria",
+ "PORT": "Puerto",
+ "USERNAME": "Nombre de usuario",
+ "PASSWORD": "Contraseña",
+ "NODATAERROR": "Se produjo un error al recuperar la información",
+ "FREEZE": "Congelar",
+ "UNFREEZE": "Descongelar",
+ "CLONE": "Clon",
+ "CLONECONFIRMPOPUPMESSAGE": "Estás seguro de querer clonar",
+ "CLONESUCCESSFULLY": "Paquete clonado exitosamente",
+ "DROPFILES": "Simplemente arrastre y suelte archivos aquí o haga clic aquí para cargar archivos",
+ "DROPFILESVALIDATION": "Por favor seleccione un archivo para procesar",
+ "METRICS": "Métrica",
+ "NOOFHOURS": "No de horas",
+ "MANDATORYCHECK": "Los campos obligatorios están marcados con un asterisco (*)",
+ "K8VERSION": "Versión K8",
+ "ENTER": "Entrar",
+ "SWITCHPROJECT": "Cambiar proyecto",
+ "CURRENTPROJECT": "Proyecto actual",
+ "SUBMIT": "Entrar",
+ "REFRESH": "Actualizar",
+ "OPEN": "Abierta",
+ "UPLOADCONFIG": "Subir configuración",
+ "FILEUPLOADLABEL": "O cargar desde el archivo",
+ "CONFIG": "Config",
+ "YAMLCONFIG": "Yaml Config",
+ "CHOOSEFILE": "Elija el archivo",
+ "INVALIDCONFIG": "Configuración inválida",
+ "PAGE": {
+ "DASHBOARD": {
+ "DASHBOARD": "Tablero",
+ "RECENTUSERLOG": "Registro de usuario reciente",
+ "LOGS": "Troncos",
+ "FAILEDINSTANCES": "Instancias fallidas",
+ "NOINSTANCES": "Keine Instanzen verfügbar",
+ "UPTIME": "Tiempodeactividad",
+ "RUNNINGINSTANCES": "Corriendo Instancias",
+ "NETSLICETEMPLATE": "Plantilla NetSlice",
+ "NETSLICEINSTANCE": "NetSlice Instancias",
+ "USERS": "Usuarios",
+ "PROJECTS": "Proyectos",
+ "USERSETTINGS": "Usuarios Ajustes",
+ "LOGOUT": "Cerrar sesión"
+ },
+ "LOGIN": {
+ "USERNAME": "Nombre de usuario",
+ "PASSWORD": "Contraseña",
+ "SIGNUP": "Regístrate",
+ "ACCOUNTCREATEMESSAGE": "¿No tienes una cuenta?",
+ "LOGIN": "iniciar sesión",
+ "PASSWORDVALIDMESSAGE": "se requiere contraseña",
+ "USERNAMEVALIDMESSAGE": "Se requiere nombre de usuario",
+ "SIGNINMSG": "Inicia sesión para iniciar tu sesión.",
+ "PASSWORDMINLENGTHVALIDMESSAGE": "La contraseña debe tener 8 caracteres y contiene al menos un carácter en mayúscula, minúscula, numérico y especial",
+ "USERNAMEMINLENGTHVALIDMESSAGE": "El nombre de usuario debe tener al menos 5 caracteres"
+ },
+ "INSTANCEINSTANTIATE": {
+ "NEWINSTANCE": "Nueva instancia",
+ "NSNAME": "Nombre de Ns",
+ "DESCRIPTION": "Descripción",
+ "NSID": "Nsd Id",
+ "SSHKEY": "SSH Key",
+ "VIMACCOUNT": "Cuenta VIM",
+ "SSHKEYMSG": "Pega tu llave aquí"
+ },
+ "NSMETRIC": {
+ "INSTANCESMETRIC": "Instancia métrica",
+ "METRICERROR": "Datos no disponibles en métricas"
+ },
+ "USERSETTINGS": {
+ "LANGUAGE": "Idioma"
+ },
+ "VIM": {
+ "CREATEDSUCCESSFULLY": "VIM Creada Exitosamente",
+ "LOACTIONINFO": "Escriba el nombre de la ubicación y haga clic en el botón Intro para seleccionar la ubicación de la lista"
+ },
+ "VIMDETAILS": {
+ "NEWVIM": "Nuevo VIM",
+ "VIMACCOUNTDETAILS": "VIM Account detalles",
+ "NAME": "Nombre",
+ "VIMUSERNAME": "VIM Nombre de usuario",
+ "VIMURL": "VIM URL",
+ "VIMTYPE": "Tipo",
+ "TENANTNAME": "Tenant Nombre",
+ "DESCRIPTION": "Descripción",
+ "SCHEMATYPE": "Tipo de esquema",
+ "SCHEMAVERSION": "Versión de esquema",
+ "CONFIGPARAMETERS": "CONFIGURAR PARÁMETROS",
+ "SDNCONTROLLER": "SDN Controladora",
+ "SDNPORTMAPPING": "SDN La asignación de puertos",
+ "VIMNETWORKNAME": "VIM Nombre de red",
+ "SECURITYGROUPS": "Grupos de seguridad",
+ "AVAILABILITYZONE": "Zona de disponibilidad",
+ "REGIONALNAME": "Nombre de región",
+ "INSECURE": "Insegura",
+ "USEEXISTINGFLAVOURS": "Usa sabores existentes",
+ "USEINTERNALENDPOINT": "Usar punto final interno",
+ "APIVERSION": "Versión API ",
+ "PROJECTDOMAINID": "Proyecto dominio id",
+ "PROJECTDOMAINNAME": "Proyecto dominio name",
+ "USERDOMAINID": "Usuaria dominio id",
+ "USERDOMAINUSER": "Usuaria dominio nombre",
+ "KEYPAIR": "Par de claves",
+ "DATAPLANEPHYSICALNET": "Plano de datos physical net",
+ "USEFLOATINGIP": "Utilizar flotante ip",
+ "DATAPLANENETVLANRANGE": "Plano de datos net vlan range",
+ "MICROVERSION": "Microversión",
+ "BACKTOVIMACCOUNTS": "Atrás a VimAccounts",
+ "VIMPASSWORD": "VIM Contraseña",
+ "ADDITIONALCONFIG": "Adicional configuración",
+ "ADDITIONALCONFIGPLACEHOLDER": "{'key1': [...], 'key2': {}, 'key3': ''}",
+ "NEWVIMACCOUNT": "Nueva VIM Cuenta",
+ "ORGNAME": "Orgnombre",
+ "VCENTERIP": "Vcenter ip",
+ "VCENTERPORT": "Vcenter Puerto",
+ "ADMINUSERNAME": "Administración nombre de usuario",
+ "VCENTERUSER": "Vcenter usuaria",
+ "ADMINPASSWORD": "Administración contraseña",
+ "VCENTERPASSWORD": "Vcenter contraseña",
+ "NSXMANAGER": "Nsx gerente",
+ "VROPSSITE": "Vrops sitio",
+ "NSXUSER": "Nsx usuaria",
+ "VROPSUSER": "Vrops usuaria",
+ "NSXPASSWORD": "Nsx contraseña",
+ "VROPSPASSWORD": "Vrops contraseña",
+ "VPCCIDRBLOCK": "VPC cidr bloquear",
+ "FLAVORIINFO": "Flavor informacion",
+ "VIM_TYPE": "VIM Tipo",
+ "VIMLOCATION": "VIM Ubicación",
+ "SUBSCRIPTIONID": "ID de suscripción",
+ "RESOURCEGROUP": "Grupo de recursos",
+ "VNETNAME": "Nombre de red virtual",
+ "FLAVORSPATTERN": "Patrón de sabores"
+ },
+ "WIMACCOUNTS": {
+ "CREATEDSUCCESSFULLY": "WIM Creado Exitosamente",
+ "WIMDETAILS": "Detalles de WIM",
+ "NEWWIM": "Nuevo WIM",
+ "SCHEMAVERSION": "Versión de esquema",
+ "RO": "RO",
+ "ROACCOUNT": "Cuenta RO",
+ "USERNAME": "Nombre de usuario de WIM",
+ "PASSWORD": "Contraseña WIM"
+ },
+ "NSINSTANCE": {
+ "NEWNSINSTANCE": "Nueva NS",
+ "CREATEDSUCCESSFULLY": "NS Ejemplo Creado Exitosamente"
+ },
+ "VNFINSTANCE": {
+ "ADDVNFINSTANCE": "Agregar instancia VNF"
+ },
+ "PDUINSTANCE": {
+ "NEWPDUINSTANCE": "Nueva PDU",
+ "PDUTYPE": "Tipo de PDU",
+ "PARAMETERS": "Parámetros de instancias de PDU",
+ "ADDINSTANCEPARAMS": "Agregar parámetros",
+ "CREATEDSUCCESSFULLY": "Instancias de PDU creadas con éxito"
+ },
+ "NETSLICEINSTANCE": {
+ "CREATENETSLICEINSTANCE": "Crear NSI"
+ },
+ "SDNCONTROLLER": {
+ "NEWSDNCONTROLLER": "Nuevo controlador SDN",
+ "REGISTEREDSDNCONTROLLER": "Controladores SDN registrados",
+ "RO": "RO",
+ "DPID": "DPID",
+ "CREATEDSUCCESSFULLY": "SDN registrado con éxito",
+ "DPIDPLACEHOLDER": "xx:xx:xx:xx:xx:xx:xx:xx",
+ "DETAILS": "Detalles del controlador SDN"
+ },
+ "USERS": {
+ "CREATEUSER": "Crear usuario",
+ "NEWUSER": "Nuevo usuario",
+ "USERNAME": "Nombre de usuario",
+ "PASSWORD": "Contraseña",
+ "CONFPASSWORD": "confirmar Contraseña",
+ "EDITUSER": "editar usuario",
+ "NEWPASSWORD": "Nueva contraseña",
+ "DEFAULTPROJECT": "Proyecto predeterminado",
+ "PASSWORDCONFLICT": "La contraseña y la contraseña de confirmación no coinciden",
+ "PASSWORDMATCH": "Contraseña",
+ "CREATEDSUCCESSFULLY": "Usuario Creada Exitosamente",
+ "EDITEDSUCCESSFULLY": "Usuario editado correctamente",
+ "EDITCREDENTIALS": "Cambia la contraseña",
+ "EDITUSERNAME": "Cambie el nombre de usuario",
+ "PROJECTSROLES": "Roles de proyectos",
+ "EDITPROJECTROLEMAPPING": "Editar asignación de roles de proyecto",
+ "ADDMAPPINGS": "Agregar asignaciones",
+ "EDITPROJECTROLEERROR": "Proporcione al menos un mapeo de roles del proyecto para continuar"
+ },
+ "TOPOLOGY": {
+ "SELECTELEMENT": "Seleccionar elemento",
+ "VL": "VL",
+ "VNF": "VNF",
+ "VNFD": "VNFD",
+ "CP": "CP",
+ "NSD": "NSD",
+ "NS": "NS",
+ "VIRTUALLINK": "Enlace virtual",
+ "CONNECTIONPOINT": "Punto de conexión",
+ "INTCONNECTIONPOINT": "Int Punto de conexión",
+ "LINK": "Enlazar",
+ "ADDINGCP": "Seleccione un punto de conexión de {{vnfdname}} para vincular {{vlname}}?",
+ "INFO": "Informacion",
+ "HELP": "Ayuda",
+ "HELPINFO": {
+ "CREATEEDGE": "Crear borde",
+ "CREATEEDGEFIRSTSETENCE": "Seleccione el primer vértice haciendo clic en él usando",
+ "CREATEEDGESECONDSETENCE": "en otro vértice (diferente al seleccionado).",
+ "DELETEEDGEVERTEX": "Eliminar borde/vértice",
+ "DELETEEDGEVERTEXSENTENCE": "Doble clic en borde / vértice.",
+ "SPREADEDGE": "Borde extendido",
+ "SPREADEDGESENTENCE": "Seleccione el vértice haciendo clic en él usando",
+ "EDGEINFO": "Mostrar información de borde",
+ "EDGEINFOSENTENCE": "Seleccione el borde haciendo clic. La información se mostrará en el lado izquierdo."
+ },
+ "VDU": "VDU",
+ "INTVL": "IntVL",
+ "INTCP": "IntCP",
+ "DATAEMPTY": "Por favor cambia algo"
+ },
+ "PROJECT": {
+ "NEWPROJECT": "Nuevo proyecto",
+ "CREATEDSUCCESSFULLY": "Proyecto Creada Exitosamente",
+ "UPDATEDSUCCESSFULLY": "Proyecto Actualizada Exitosamente"
+ },
+ "NSPACKAGE": {
+ "ADDNSPACKAGE": "Componer un nuevo NS",
+ "CREATEDSUCCESSFULLY": "NS Paquetes Creada Exitosamente",
+ "NSCOMPOSE": {
+ "UPDATEDSUCCESSFULLY": "Actualizada Exitosamente",
+ "CONFIRMCONNECTIONPOINT": "Confirme para agregar un punto de conexión",
+ "CANNOTLINKVNF": "No puedes vincular un vnf con un vnf",
+ "CANNOTLINKVL": "No puedes vincular un VL con un VL",
+ "CANNOTLINKVLVNF": "No puedes vincular un VL con un vnf",
+ "CANNOTLINKVNFCP": "No puedes vincular un VNF con un CP",
+ "CANNOTLINKVLCP": "No puedes vincular un VL con un CP",
+ "CANNOTLINKCP": "No puedes vincular un CP con un CP",
+ "ADDNSD": "Enlace virtual se agrega con éxito",
+ "ADDVNFD": "VNFD se agrega con éxito",
+ "ADDNS": "El enlace de conexión se agregó con éxito",
+ "DELETENSD": "Se eliminó con éxito el enlace virtual",
+ "DELETEVNFD": "Eliminado con éxito el VNF",
+ "DELETENS": "Se eliminó correctamente el punto de conexión",
+ "DELETELINK": "Se eliminó el enlace correctamente",
+ "MGMTNETWORK": "Mgmt Network",
+ "VIMNETWORKNAME": "Vim Network Name",
+ "MEMBER-VNF-INDEX": "member-vnf-index",
+ "VNFD-ID-REF": "vnfd-id-ref",
+ "VLD-ID": "vld-id",
+ "VNFD-CP-REF": "vnfd-punto de conexión-ref"
+ },
+ "EDITPACKAGES": {
+ "UPDATEDSUCCESSFULLY": "Descriptor actualizado exitosamente"
+ }
+ },
+ "VNFPACKAGE": {
+ "ADDVNFPACKAGE": "Componer un nuevo VNF",
+ "CREATEDSUCCESSFULLY": "VNF Paquetes Creada Exitosamente",
+ "VNFCOMPOSE": {
+ "UPDATEDSUCCESSFULLY": "Actualizada Exitosamente",
+ "INVALIDSELECTION": "Selección invalida",
+ "YOUCANNOTDELETELINK": "No puedes eliminar el enlace",
+ "CANNOTLINKVDUANDINTCP": "No puedes vincular vdu con int_cp",
+ "CANNOTLINKINTCPANDVDU": "No puedes vincular int_cp con vdu",
+ "CANNOTLINKCPANDVNFVL": "No puedes vincular cp con vnf_vl",
+ "CANNOTLINKVNFVLANDCP": "No puedes vincular vnf_vl con cp",
+ "CANNOTLINKINTCPANDCP": "No puedes vincular intcp con cp",
+ "CANNOTLINKCPANDINTCP": "No puedes vincular cp con int_cp",
+ "CANNOTLINKVDUANDVDU": "No puedes vincular un vdu con un vdu"
+ }
+ },
+ "NETSLICE": {
+ "CREATEDSUCCESSFULLY": "Netslice Creada Exitosamente",
+ "TEMPLATECREATEDSUCCESSFULLY": "Netslice Modelo Created Successfully",
+ "UPDATEDSUCCESSFULLY": "Plantilla actualizada con éxito"
+ },
+ "NETSLICETEMPLATE": {
+ "NETSLICETEMPLATEDETAILS": "Red Rebanadas Modelo Detalles"
+ },
+ "NSTINSTANCEINSTANTIATE": {
+ "NEWINSTANCE": "Nueva instancia",
+ "NSNAME": "Nombre de Ns",
+ "DESCRIPTION": "Descripción",
+ "NSTID": "Nsd Id",
+ "SSHKEY": "SSH Key",
+ "VIMACCOUNT": "Cuenta VIM",
+ "SSHKEYMSG": "Pega tu llave aquí ..."
+ },
+ "NSPRIMITIVE": {
+ "PRIMITIVE": "Primitiva",
+ "PRIMITIVEPARAMETERS": "Primitiva Parámetros",
+ "ADDPRIMITIVEPARAMS": "Añadir Parámetros primitivos",
+ "EXECUTEDSUCCESSFULLY": "Ejecutada NS Configuración primitiva"
+ },
+ "ROLES": {
+ "CREATEROLE": "Crear rol",
+ "ROLE": "Papel",
+ "PERMISSIONS": "Permisos",
+ "YAMLPERMISSIONS": "YAML Permisos",
+ "CREATEDSUCCESSFULLY": "Rol creado con éxito",
+ "UPDATEDSUCCESSFULLY": "Rol actualizado exitosamente",
+ "ROLEJSONERROR": "Los permisos de rol deben proporcionarse de manera clave-valor",
+ "ROLEKEYERROR": "El valor de '{{roleKey}}' en los permisos de un rol debe ser booleano",
+ "EDITROLE": "Editar rol",
+ "PREVIEW": "Avance",
+ "TEXTVIEW": "Vista de texto"
+ },
+ "K8S": {
+ "MENUK8S": "K8s",
+ "MENUK8SCLUSTER": "Clusters K8s",
+ "MENUK8SREPO": "K8s Repos",
+ "REGISTERK8CLUSTER": "Grupos de K8 registrados",
+ "ADDK8CLUSTER": "Agregar clúster K8s",
+ "K8SCLUSTERDETAILS": "Detalles del clúster K8s",
+ "REGISTERK8REPO": "Repositorio K8 registrado",
+ "ADDK8REPO": "Agregar repositorio K8s",
+ "K8SREPODETAILS": "Detalles del repositorio de K8s",
+ "CREATEDSUCCESSFULLY": "K8 creados con éxito",
+ "NEWK8SCLUSTER": "Nuevo clúster K8s",
+ "NAME": "Nombre",
+ "K8SVERSION": "Versión K8s",
+ "VIMACCOUNT": "Cuenta Vim",
+ "DESCRIPTION": "Descripción",
+ "NETS": "Nets",
+ "NETSPLACEHOLDER": "example: {'net1': 'osm-ext'}",
+ "CREDENTIALS": "Cartas credenciales",
+ "NEWK8SREPO": "Nuevo repositorio K8s",
+ "TYPE": "Tipo",
+ "URL": "URL"
+ }
+ },
+ "HTTPERROR": {
+ "401": "Acceso denegado",
+ "400": "Por favor revise la solicitud e intente nuevamente",
+ "404": "El servicio esperado no está disponible. Vuelve a intentarlo más tarde.",
+ "500": "Error del servidor. Vuelve a intentarlo más tarde",
+ "502": "Bad Gateway, por favor intente nuevamente más tarde",
+ "503": "El servicio no está disponible temporalmente. Vuelve a intentarlo más tarde",
+ "504": "Error de tiempo de espera de la puerta de enlace. Vuelva a intentarlo más tarde",
+ "409": "Por favor, inténtelo de nuevo más tarde"
+ },
+ "PAGENOTFOUND": {
+ "OOPS": "¡Uy!",
+ "NOTFOUND": "404 No encontrado",
+ "CONTENT": "La página no se puede encontrar o no está autorizada, puede que ya no sea relevante o se haya cambiado su nombre.",
+ "MEAN": "Mientras tanto, puede volver a",
+ "HOME": "Hogar"
+ },
+ "DOMVALIDATIONS": {
+ "INVALIDURL": "Ingrese una URL válida",
+ "INVALIDIPADDRESS": "Ingrese una dirección IP válida",
+ "INVALIDPORTADDRESS": "Ingrese una dirección de puerto válida",
+ "INVALIDDPID": "Ingrese un DPID válido",
+ "INVALIDJSON": "Ingrese un formato JSON válido",
+ "INVALIDYAML": "Ingrese un formato YAML válido"
+ },
+ "GRAFANA": {
+ "METRICSERROR": "No es una métrica válida"
+ }
+}
\ No newline at end of file
--- /dev/null
+{
+ "OSM": "OSM",
+ "APPVERSION": "Versão da aplicação",
+ "OSMVERSION": "Versão OSM",
+ "OSMSOURCEMANO": "Código aberto MANO",
+ "ADMIN": "Admin",
+ "ENTRIES": "Entradas",
+ "COMPOSE": "Componha um",
+ "CREATE": "Crio",
+ "SELECT": "Selecione",
+ "CANCEL": "Cancelar",
+ "SAVE": "Salve",
+ "COUNT": "contagem",
+ "IMAGE": "Imagem",
+ "IPPROFILEREF": "Ref do perfil IP",
+ "ACTION": "Açao",
+ "ADD": "Adicionar",
+ "EDIT": "Editar",
+ "APPLY": "Aplique",
+ "FORCE": "Força",
+ "DOWNLOAD": "Baixar",
+ "CONTENT": "Conteúdo",
+ "DELETE": "Excluir",
+ "FORCEDELETE": "Forçar exclusão",
+ "RENAME": "Renomear",
+ "INFO": "Info",
+ "NSPACKAGES": "Pacotes NS",
+ "VNFPACKAGES": "Pacotes VNF",
+ "INSTANCES": "Instâncias",
+ "INSTANTIATE": "Instanciar",
+ "NSINSTANCES": "Instâncias NS",
+ "VNFINSTANCES": "Instâncias VNF",
+ "PDUINSTANCES": "Instâncias da PDU",
+ "VIMACCOUNTS": "Contas VIM",
+ "WIMACCOUNTS": "Contas WIM",
+ "SDNCONTROLLER": "Controlador SDN",
+ "NETSLICE": "Netslice",
+ "PROJECT": "Projeto",
+ "DOMAIN": "Domínio",
+ "MODIFIED": "Modificada",
+ "PACKAGES": "Pacotes",
+ "NODATAMSG": "Sem dados disponíveis na tabela",
+ "SHORTNAME": "Nome curto",
+ "IDENTIFIER": "Identificador",
+ "DESCRIPTION": "Descrição",
+ "VENDOR": "Fornecedor",
+ "VERSION": "Versão",
+ "ACTIONS": "Ações",
+ "NAME": "Nome",
+ "USAGESTATE": "UsageState",
+ "MODIFICATIONDATE": "Modificação de data",
+ "CREATEDDATE": "Data de criação",
+ "OPERATIONALSTATUS": "Estado operacional",
+ "OPERATIONALSTATE": "Estado operacional",
+ "CONFIGSTATUS": "Status da configuração",
+ "DETAILEDSTATUS": "Status detalhado",
+ "NSDNAME": "Nome nsd",
+ "NSTNAME": "Nst name",
+ "TYPE": "Tipo",
+ "VNFD": "VNFD",
+ "VNF": "VNF",
+ "MEMBERINDEX": "Índice de membros",
+ "NS": "NS",
+ "CREATEDAT": "Criado em",
+ "CREATED": "Criada",
+ "ALL": "Todos",
+ "ID": "Identidade",
+ "OPERATIONSTATE": "Estado da operação",
+ "STARTTIME": "Hora de início",
+ "STATUSENTEREDTIME": "Horário de entrada do status",
+ "HISTORYOFOPERATIONS": "História das Operações",
+ "UPDATE": "Atualizar",
+ "READONLYMODE": "Modo somente leitura",
+ "CURRENTLY": "Atualmente",
+ "ON": "Em",
+ "OFF": "Fora",
+ "IN": "em",
+ "FILES": "arquivos",
+ "NEW": "Nova",
+ "RECENTLY": "Recentemente",
+ "TOPOLOGY": "Topologia",
+ "PLEASEWAIT": "Por favor, espere",
+ "LOADING": "Carregando",
+ "RESOURCEORCHESTRATOR": "Orquestrador de Recursos",
+ "VIEW": "Visão",
+ "DROP": "Solta",
+ "HERE": "Aqui",
+ "MAPVIEW": "Visão do mapa",
+ "LISTVIEW": "Exibição de lista",
+ "OK": "Está bem",
+ "DELETEDSUCCESSFULLY": "Apagado com sucesso",
+ "SESSIONEXPIRY": "Sessão expirada, faça o login novamente",
+ "DELETECONFIRMPOPUPMESSAGE": "Tem certeza de que deseja excluir",
+ "DELETELOADERMESSAGE": "Aguarde enquanto a exclusão está em andamento",
+ "VALUE": "Valor",
+ "PERFORMACTION": "Executar a ação",
+ "EXECUTE": "Executar",
+ "EXECNSPRIMITIVE": "Exec NS Primitive",
+ "PRIMITIVETYPE": "Tipo primitivo",
+ "VNFPRIMITIVE": "Primitivo de nível VNF",
+ "NSPRIMITIVE": "NS Level Primitive",
+ "DESCRIPTOR": "Descritora",
+ "ERROR": "Alguma coisa deu errado. Por favor tente outra vez",
+ "SHOWGRAPH": "Mostrar gráfico",
+ "UPDATESHOWGRAPH": "Atualizar e mostrar gráfico",
+ "CREATEPACKAGE": "Criar novo pacote",
+ "GZFILETYPEERRROR": "Carregue apenas o arquivo tar.gz e o tamanho não deve exceder 15 MB",
+ "YAMLFILETYPEERRROR": "Carregar apenas arquivo YAML e o tamanho não deve exceder 15 MB",
+ "JSONFILETYPEERRROR": "Carregar apenas arquivo JSON e o tamanho não deve exceder 15 MB",
+ "PUBFILETYPEERRROR": "Carregar apenas arquivo PUB e o tamanho não deve exceder 15 MB",
+ "PACKAGE": "Pacote",
+ "URL": "URL",
+ "DEPLOYED": "Deployed",
+ "ROLES": "Funções",
+ "INSTANCEDETAILS": "Detalhes da Instância",
+ "IPADDRESS": "Endereço de IP",
+ "MGMT": "Mgmt",
+ "NETNAME": "Nome líquido",
+ "USER": "Do utilizador",
+ "PORT": "Porta",
+ "USERNAME": "Nome de usuário",
+ "PASSWORD": "Senha",
+ "NODATAERROR": "Ocorreu um erro ao recuperar as informações",
+ "FREEZE": "Congelar",
+ "UNFREEZE": "Descongelar",
+ "CLONE": "Clone",
+ "CLONECONFIRMPOPUPMESSAGE": "Tem certeza de que deseja clonar",
+ "CLONESUCCESSFULLY": "Pacote clonado com sucesso",
+ "DROPFILES": "Basta arrastar e soltar arquivos aqui ou clique aqui para fazer upload de arquivos",
+ "DROPFILESVALIDATION": "Selecione um arquivo para processar",
+ "METRICS": "Métricas",
+ "NOOFHOURS": "Não de horas",
+ "MANDATORYCHECK": "Os campos obrigatórios estão marcados com um asterisco (*)",
+ "K8VERSION": "Versão K8",
+ "ENTER": "Entrar",
+ "SWITCHPROJECT": "Switch Project",
+ "CURRENTPROJECT": "Projeto atual",
+ "SUBMIT": "Enviar",
+ "REFRESH": "Atualizar",
+ "OPEN": "Aberto",
+ "UPLOADCONFIG": "Upload Config",
+ "FILEUPLOADLABEL": "Ou carregue do arquivo",
+ "CONFIG": "Config",
+ "YAMLCONFIG": "Yaml Config",
+ "CHOOSEFILE": "Escolher arquivo",
+ "INVALIDCONFIG": "Configuração inválida",
+ "PAGE": {
+ "DASHBOARD": {
+ "DASHBOARD": "painel de controle",
+ "RECENTUSERLOG": "Registro recente do usuário",
+ "LOGS": "Logs",
+ "FAILEDINSTANCES": "Instâncias com falha",
+ "NOINSTANCES": "Keine Instanzen verfügbar",
+ "UPTIME": "Tempo de atividade",
+ "RUNNINGINSTANCES": "Instâncias em execução",
+ "NETSLICETEMPLATE": "Modelo de fatia líquida",
+ "NETSLICEINSTANCE": "Instâncias de fatia líquida",
+ "USERS": "Comercial",
+ "PROJECTS": "Projetos",
+ "USERSETTINGS": "Configurações do usuário",
+ "LOGOUT": "Sair"
+ },
+ "LOGIN": {
+ "USERNAME": "Nome de usuário",
+ "PASSWORD": "Senha",
+ "SIGNUP": "Inscrever-se",
+ "ACCOUNTCREATEMESSAGE": "Não possui uma conta?",
+ "LOGIN": "entrar",
+ "PASSWORDVALIDMESSAGE": "Senha requerida",
+ "USERNAMEVALIDMESSAGE": "Nome de usuário é requerido",
+ "SIGNINMSG": "Faça login para iniciar sua sessão",
+ "PASSWORDMINLENGTHVALIDMESSAGE": "A senha deve ter 8 caracteres e conter pelo menos um caractere maiúsculo, minúsculo, numérico e especial",
+ "USERNAMEMINLENGTHVALIDMESSAGE": "O nome de usuário deve ter pelo menos 5 caracteres"
+ },
+ "INSTANCEINSTANTIATE": {
+ "NEWINSTANCE": "Nova Instância",
+ "NSNAME": "Ns Name",
+ "DESCRIPTION": "Descrição",
+ "NSID": "ID Nsd",
+ "SSHKEY": "Chave SSH",
+ "VIMACCOUNT": "Conta VIM",
+ "SSHKEYMSG": "Cole sua chave aqui"
+ },
+ "NSMETRIC": {
+ "INSTANCESMETRIC": "Métrica de Instâncias",
+ "METRICERROR": "Dados não disponíveis em métricas"
+ },
+ "USERSETTINGS": {
+ "LANGUAGE": "Língua"
+ },
+ "VIM": {
+ "CREATEDSUCCESSFULLY": "VIM criado com sucesso",
+ "LOACTIONINFO": "Digite o nome do local e clique no botão Enter para selecionar o local na lista"
+ },
+ "VIMDETAILS": {
+ "NEWVIM": "Novo VIM",
+ "VIMACCOUNTDETAILS": "Detalhes da conta VIM",
+ "NAME": "Nome",
+ "VIMUSERNAME": "Nome de usuário do VIM",
+ "VIMURL": "URL do VIM",
+ "VIMTYPE": "Tipo",
+ "TENANTNAME": "Nome do inquilino",
+ "DESCRIPTION": "Descrição",
+ "SCHEMATYPE": "Tipo de esquema",
+ "SCHEMAVERSION": "Versão do esquema",
+ "CONFIGPARAMETERS": "PARÂMETROS CONFIG",
+ "SDNCONTROLLER": "Controlador SDN",
+ "SDNPORTMAPPING": "Mapeamento de porta SDN",
+ "VIMNETWORKNAME": "Nome da rede VIM",
+ "SECURITYGROUPS": "Grupos de Segurança",
+ "AVAILABILITYZONE": "Zona de disponibilidade",
+ "REGIONALNAME": "Nome da região",
+ "INSECURE": "Insegura",
+ "USEEXISTINGFLAVOURS": "Use sabores existentes",
+ "USEINTERNALENDPOINT": "Usar terminal interno",
+ "APIVERSION": "Versão da API",
+ "PROJECTDOMAINID": "ID do domínio do projeto",
+ "PROJECTDOMAINNAME": "Nome de domínio do projeto",
+ "USERDOMAINID": "ID do domínio do usuário",
+ "USERDOMAINUSER": "Nome de domínio do usuário",
+ "KEYPAIR": "Par de chaves",
+ "DATAPLANEPHYSICALNET": "Rede física do plano de dados",
+ "USEFLOATINGIP": "Use ip flutuante",
+ "DATAPLANENETVLANRANGE": "Dataplane net vlan range",
+ "MICROVERSION": "Microversão",
+ "BACKTOVIMACCOUNTS": "Voltar para VimAccounts",
+ "VIMPASSWORD": "Senha do VIM",
+ "ADDITIONALCONFIG": "Configuração adicional",
+ "ADDITIONALCONFIGPLACEHOLDER": "{'key1':[...],'key2':{},'key3':''}",
+ "NEWVIMACCOUNT": "Nova conta VIM",
+ "ORGNAME": "Orgnome",
+ "VCENTERIP": "Vcenter ip",
+ "VCENTERPORT": "Porta Vcenter",
+ "ADMINUSERNAME": "Nome de usuário do administrador",
+ "VCENTERUSER": "Usuário do Vcenter",
+ "ADMINPASSWORD": "senha do administrador",
+ "VCENTERPASSWORD": "Senha do Vcenter",
+ "NSXMANAGER": "Gerente Nsx",
+ "VROPSSITE": "Site Vrops",
+ "NSXUSER": "Usuário Nsx",
+ "VROPSUSER": "Usuário Vrops",
+ "NSXPASSWORD": "Senha Nsx",
+ "VROPSPASSWORD": "Senha Vrops",
+ "VPCCIDRBLOCK": "Bloco cidr VPC",
+ "FLAVORIINFO": "Informação do sabor",
+ "VIM_TYPE": "Tipo VIM",
+ "VIMLOCATION": "Localização do VIM",
+ "SUBSCRIPTIONID": "ID de Inscrição",
+ "RESOURCEGROUP": "Grupo de Recursos",
+ "VNETNAME": "Nome da VNet",
+ "FLAVORSPATTERN": "Padrão de sabores"
+ },
+ "WIMACCOUNTS": {
+ "CREATEDSUCCESSFULLY": "WIM criado com sucesso",
+ "WIMDETAILS": "Detalhes do WIM",
+ "NEWWIM": "Novo WIM",
+ "SCHEMAVERSION": "Versão do esquema",
+ "RO": "RO",
+ "ROACCOUNT": "Conta RO",
+ "USERNAME": "Nome de usuário WIM",
+ "PASSWORD": "Senha WIM"
+ },
+ "NSINSTANCE": {
+ "NEWNSINSTANCE": "Nova NS",
+ "CREATEDSUCCESSFULLY": "Instância NS criada com êxito"
+ },
+ "VNFINSTANCE": {
+ "ADDVNFINSTANCE": "Adicionar instância VNF"
+ },
+ "PDUINSTANCE": {
+ "NEWPDUINSTANCE": "Nova PDU",
+ "PDUTYPE": "Tipo de PDU",
+ "PARAMETERS": "Parâmetros de instâncias da PDU",
+ "ADDINSTANCEPARAMS": "Adicionar parâmetros",
+ "CREATEDSUCCESSFULLY": "Instâncias da PDU criadas com êxito"
+ },
+ "NETSLICEINSTANCE": {
+ "CREATENETSLICEINSTANCE": "Criar NSI"
+ },
+ "SDNCONTROLLER": {
+ "NEWSDNCONTROLLER": "Novo controlador SDN",
+ "REGISTEREDSDNCONTROLLER": "Controladores SDN registrados",
+ "RO": "RO",
+ "DPID": "DPID",
+ "CREATEDSUCCESSFULLY": "SDN Registrado com Sucesso",
+ "DPIDPLACEHOLDER": "xx:xx:xx:xx:xx:xx:xx:xx",
+ "DETAILS": "Detalhes do Controlador SDN"
+ },
+ "USERS": {
+ "CREATEUSER": "Criar usuário",
+ "NEWUSER": "Novo usuário",
+ "USERNAME": "Nome de Usuário",
+ "PASSWORD": "Senha",
+ "CONFPASSWORD": "Confirme a Senha",
+ "EDITUSER": "Editar usuário",
+ "NEWPASSWORD": "Nova senha",
+ "DEFAULTPROJECT": "Projeto Padrão",
+ "PASSWORDCONFLICT": "Senha e confirmação de senha não correspondem",
+ "PASSWORDMATCH": "Correspondência de senha",
+ "CREATEDSUCCESSFULLY": "Usuário criado com sucesso",
+ "EDITEDSUCCESSFULLY": "Edição do Usuário com Sucesso",
+ "EDITCREDENTIALS": "Mudar senha",
+ "EDITUSERNAME": "Mudar nome de usuário",
+ "PROJECTSROLES": "Funções dos Projetos",
+ "EDITPROJECTROLEMAPPING": "Editar mapeamento de função do projeto",
+ "ADDMAPPINGS": "Adicionar mapeamentos",
+ "EDITPROJECTROLEERROR": "Forneça pelo menos um mapeamento de função do projeto para continuar"
+ },
+ "TOPOLOGY": {
+ "SELECTELEMENT": "Selecionar elemento",
+ "VL": "VL",
+ "VNF": "VNF",
+ "VNFD": "VNFD",
+ "CP": "CP",
+ "NSD": "NSD",
+ "NS": "NS",
+ "VIRTUALLINK": "Link virtual",
+ "CONNECTIONPOINT": "Ponto de conexão",
+ "INTCONNECTIONPOINT": "Ponto de conexão int",
+ "LINK": "Ligação",
+ "ADDINGCP": "Por favor, selecione um ponto de conexão {{vnfdname}} para vincular {{vlname}}?",
+ "INFO": "Info",
+ "HELP": "Socorro",
+ "HELPINFO": {
+ "CREATEEDGE": "Criar aresta",
+ "CREATEEDGEFIRSTSETENCE": "Selecione o primeiro vértice clicando nele usando",
+ "CREATEEDGESECONDSETENCE": "em outro vértice (diferente do selecionado).",
+ "DELETEEDGEVERTEX": "Excluir aresta / vértice",
+ "DELETEEDGEVERTEXSENTENCE": "Clicar duas vezes na aresta / vértice.",
+ "SPREADEDGE": "Espalhe a borda",
+ "SPREADEDGESENTENCE": "Selecione o vértice clicando nele usando",
+ "EDGEINFO": "Mostrar informações da aresta",
+ "EDGEINFOSENTENCE": "Selecione a aresta clicando. A informação será mostrada no lado esquerdo."
+ },
+ "VDU": "VDU",
+ "INTVL": "IntVL",
+ "INTCP": "IntCP",
+ "DATAEMPTY": "Por favor mude algo"
+ },
+ "PROJECT": {
+ "NEWPROJECT": "Novo projeto",
+ "CREATEDSUCCESSFULLY": "Projeto criado com sucesso",
+ "UPDATEDSUCCESSFULLY": "Projeto atualizado com sucesso"
+ },
+ "NSPACKAGE": {
+ "ADDNSPACKAGE": "Componha um novo NS",
+ "CREATEDSUCCESSFULLY": "Pacote NS criado com sucesso",
+ "NSCOMPOSE": {
+ "UPDATEDSUCCESSFULLY": "Atualizado com sucesso",
+ "CONFIRMCONNECTIONPOINT": "Confirme para adicionar o ponto de conexão",
+ "CANNOTLINKVNF": "Você não pode vincular um vnf a um vnf",
+ "CANNOTLINKVL": "Você não pode vincular uma VL a uma VL",
+ "CANNOTLINKVLVNF": "Você não pode vincular um VL a um vnf",
+ "CANNOTLINKVNFCP": "Você não pode vincular um VNF a um CP",
+ "CANNOTLINKVLCP": "Você não pode vincular uma VL a um CP",
+ "CANNOTLINKCP": "Você não pode vincular um CP a um CP",
+ "ADDNSD": "Link virtual adicionado com sucesso",
+ "ADDVNFD": "VNFD é adicionado com sucesso",
+ "ADDNS": "Link de conexão adicionado com sucesso",
+ "DELETENSD": "O link virtual foi excluído com sucesso",
+ "DELETEVNFD": "O VNF foi excluído com sucesso",
+ "DELETENS": "Excluído com êxito o ponto de conexão",
+ "DELETELINK": "O link foi excluído com sucesso",
+ "MGMTNETWORK": "Mgmt Network",
+ "VIMNETWORKNAME": "Vim Network Name",
+ "MEMBER-VNF-INDEX": "member-vnf-index",
+ "VNFD-ID-REF": "vnfd-id-ref",
+ "VLD-ID": "vld-id",
+ "VNFD-CP-REF": "vnfd-ponto de conexão-ref"
+ },
+ "EDITPACKAGES": {
+ "UPDATEDSUCCESSFULLY": "Atualizado com sucesso"
+ }
+ },
+ "VNFPACKAGE": {
+ "ADDVNFPACKAGE": "Componha um novo VNF",
+ "CREATEDSUCCESSFULLY": "Pacote VNF criado com sucesso",
+ "VNFCOMPOSE": {
+ "UPDATEDSUCCESSFULLY": "Atualizado com sucesso",
+ "INVALIDSELECTION": "Seleção inválida",
+ "YOUCANNOTDELETELINK": "Você não pode excluir o link",
+ "CANNOTLINKVDUANDINTCP": "Você não pode vincular o vdu ao int_cp",
+ "CANNOTLINKINTCPANDVDU": "Você não pode vincular int_cp ao vdu",
+ "CANNOTLINKCPANDVNFVL": "Você não pode vincular o cp ao vnf_vl",
+ "CANNOTLINKVNFVLANDCP": "Você não pode vincular vnf_vl ao cp",
+ "CANNOTLINKINTCPANDCP": "Você não pode vincular o intcp ao cp",
+ "CANNOTLINKCPANDINTCP": "Você não pode vincular o cp ao int_cp",
+ "CANNOTLINKVDUANDVDU": "Você não pode vincular um vdu a um vdu"
+ }
+ },
+ "NETSLICE": {
+ "CREATEDSUCCESSFULLY": "Netslice criado com sucesso",
+ "TEMPLATECREATEDSUCCESSFULLY": "Modelo Netslice criado com sucesso",
+ "UPDATEDSUCCESSFULLY": "Modelo atualizado com sucesso"
+ },
+ "NETSLICETEMPLATE": {
+ "NETSLICETEMPLATEDETAILS": "Detalhes do modelo de fatias de rede"
+ },
+ "NSTINSTANCEINSTANTIATE": {
+ "NEWINSTANCE": "Nova Instância",
+ "NSNAME": "Ns Name",
+ "DESCRIPTION": "Descrição",
+ "NSTID": "Nst Id",
+ "SSHKEY": "Chave SSH",
+ "VIMACCOUNT": "Conta VIM",
+ "SSHKEYMSG": "Cole sua chave aqui ..."
+ },
+ "NSPRIMITIVE": {
+ "PRIMITIVE": "Primitiva",
+ "PRIMITIVEPARAMETERS": "Parâmetros primitivos",
+ "ADDPRIMITIVEPARAMS": "Adicionar Parâmetros Primitivos",
+ "EXECUTEDSUCCESSFULLY": "Configuração primitiva do NS executada"
+ },
+ "ROLES": {
+ "CREATEROLE": "Criar função",
+ "ROLE": "Função",
+ "PERMISSIONS": "Permissões",
+ "YAMLPERMISSIONS": "YAML Permissões",
+ "CREATEDSUCCESSFULLY": "Função criada com sucesso",
+ "UPDATEDSUCCESSFULLY": "Função atualizada com sucesso",
+ "ROLEJSONERROR": "As permissões de função devem ser fornecidas de maneira com valor-chave",
+ "ROLEKEYERROR": "O valor de '{{roleKey}}' nas permissões de uma função deve ser booleano",
+ "EDITROLE": "Editar função",
+ "PREVIEW": "Pré-visualização",
+ "TEXTVIEW": "Visualização de texto"
+ },
+ "K8S": {
+ "MENUK8S": "K8s",
+ "MENUK8SCLUSTER": "Clusters do K8s",
+ "MENUK8SREPO": "Repos do K8s",
+ "REGISTERK8CLUSTER": "Clusters K8s registrados",
+ "ADDK8CLUSTER": "Adicionar cluster do K8s",
+ "K8SCLUSTERDETAILS": "Detalhes do cluster K8s",
+ "REGISTERK8REPO": "Repositório registrado do K8s",
+ "ADDK8REPO": "Adicionar repositório K8s",
+ "K8SREPODETAILS": "Detalhes do Repositório do K8s",
+ "CREATEDSUCCESSFULLY": "K8s criado com sucesso",
+ "NEWK8SCLUSTER": "Novo Cluster K8s",
+ "NAME": "Nome",
+ "K8SVERSION": "Versão do K8s",
+ "VIMACCOUNT": "Conta Vim",
+ "DESCRIPTION": "Descrição",
+ "NETS": "Nets",
+ "NETSPLACEHOLDER": "example: {'net1': 'osm-ext'}",
+ "CREDENTIALS": "Credenciais",
+ "NEWK8SREPO": "Novo Repositório do K8s",
+ "TYPE": "Tipo",
+ "URL": "URL"
+ }
+ },
+ "HTTPERROR": {
+ "401": "Acesso negado",
+ "400": "Verifique a solicitação e tente novamente",
+ "404": "Serviço esperado não disponível, tente novamente mais tarde",
+ "500": "Erro no servidor, tente novamente mais tarde",
+ "502": "Gateway incorreto. Tente novamente mais tarde",
+ "503": "Serviço temporariamente indisponível. Tente novamente mais tarde",
+ "504": "Erro de tempo limite do gateway. Tente novamente mais tarde",
+ "409": "Por favor, tente novamente mais tarde"
+ },
+ "PAGENOTFOUND": {
+ "OOPS": "Opa!",
+ "NOTFOUND": "404 não encontrado",
+ "CONTENT": "A página não pode ser encontrada ou não autorizada, pode não ser mais relevante ou seu nome foi alterado",
+ "MEAN": "Enquanto isso, você pode voltar para",
+ "HOME": "Casa"
+ },
+ "DOMVALIDATIONS": {
+ "INVALIDURL": "Digite um URL válido",
+ "INVALIDIPADDRESS": "Digite um endereço IP válido",
+ "INVALIDPORTADDRESS": "Digite um endereço PORT válido",
+ "INVALIDDPID": "Digite um DPID válido",
+ "INVALIDJSON": "Digite um formato JSON válido",
+ "INVALIDYAML": "Digite um formato YAML válido"
+ },
+ "GRAFANA": {
+ "METRICSERROR": "Métricas não válidas"
+ }
+}
\ No newline at end of file
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+
+<svg version="1.1" id="IconsRepoEditor" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="64px" height="64px" viewBox="-106.14 -106.14 654.53 654.53" style="enable-background:new 0 0 442.246 442.246;" xml:space="preserve" fill="#ffffff" stroke="#ffffff" stroke-width="0">
+
+<g id="IconsRepo_bgCarrier">
+
+<rect x="-106.14" y="-106.14" width="654.53" height="654.53" rx="327.265" fill="#c6b63f" stroke-width="0"/>
+
+</g> <path d="M409.657,32.474c-43.146-43.146-113.832-43.146-156.978,0l-84.763,84.762c29.07-8.262,60.589-6.12,88.129,6.732 l44.063-44.064c17.136-17.136,44.982-17.136,62.118,0c17.136,17.136,17.136,44.982,0,62.118l-55.386,55.386l-36.414,36.414 c-17.136,17.136-44.982,17.136-62.119,0l-47.43,47.43c11.016,11.017,23.868,19.278,37.332,24.48 c36.415,14.382,78.643,8.874,110.467-16.219c3.06-2.447,6.426-5.201,9.18-8.262l57.222-57.222l34.578-34.578 C453.109,146.306,453.109,75.926,409.657,32.474z"/> <path d="M184.135,320.114l-42.228,42.228c-17.136,17.137-44.982,17.137-62.118,0c-17.136-17.136-17.136-44.981,0-62.118 l91.8-91.799c17.136-17.136,44.982-17.136,62.119,0l47.43-47.43c-11.016-11.016-23.868-19.278-37.332-24.48 c-38.25-15.3-83.232-8.262-115.362,20.502c-1.53,1.224-3.06,2.754-4.284,3.978l-91.8,91.799 c-43.146,43.146-43.146,113.832,0,156.979c43.146,43.146,113.832,43.146,156.978,0l82.927-83.845 C230.035,335.719,220.243,334.496,184.135,320.114z"/> </svg>
\ No newline at end of file
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+
+<svg version="1.1" id="IconsRepoEditor" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="64px" height="64px" viewBox="-154.79 -154.79 751.83 751.83" style="enable-background:new 0 0 442.246 442.246;" xml:space="preserve" fill="#ffffff" stroke="#ffffff" stroke-width="0" transform="rotate(0)">
+
+<g id="IconsRepo_bgCarrier">
+
+<rect x="-154.79" y="-154.79" width="751.83" height="751.83" rx="375.915" fill="#3c8dbc" stroke-width="0"/>
+
+</g> <path d="M409.657,32.474c-43.146-43.146-113.832-43.146-156.978,0l-84.763,84.762c29.07-8.262,60.589-6.12,88.129,6.732 l44.063-44.064c17.136-17.136,44.982-17.136,62.118,0c17.136,17.136,17.136,44.982,0,62.118l-55.386,55.386l-36.414,36.414 c-17.136,17.136-44.982,17.136-62.119,0l-47.43,47.43c11.016,11.017,23.868,19.278,37.332,24.48 c36.415,14.382,78.643,8.874,110.467-16.219c3.06-2.447,6.426-5.201,9.18-8.262l57.222-57.222l34.578-34.578 C453.109,146.306,453.109,75.926,409.657,32.474z"/> <path d="M184.135,320.114l-42.228,42.228c-17.136,17.137-44.982,17.137-62.118,0c-17.136-17.136-17.136-44.981,0-62.118 l91.8-91.799c17.136-17.136,44.982-17.136,62.119,0l47.43-47.43c-11.016-11.016-23.868-19.278-37.332-24.48 c-38.25-15.3-83.232-8.262-115.362,20.502c-1.53,1.224-3.06,2.754-4.284,3.978l-91.8,91.799 c-43.146,43.146-43.146,113.832,0,156.979c43.146,43.146,113.832,43.146,156.978,0l82.927-83.845 C230.035,335.719,220.243,334.496,184.135,320.114z"/> </svg>
\ No newline at end of file
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+
+<svg version="1.1" id="IconsRepoEditor" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="-72.81 -72.81 448.99 448.99" style="enable-background:new 0 0 303.374 303.374;" xml:space="preserve" width="64px" height="64px" fill="#ffffff" stroke="#ffffff" stroke-width="0">
+
+<g id="IconsRepo_bgCarrier">
+
+<rect x="-72.81" y="-72.81" width="448.99" height="448.99" rx="224.495" fill="#605ca8" stroke-width="0"/>
+
+</g> <path d="M268.291,177.313c-4.144,0-8.12,0.727-11.814,2.052l-17.319-27.524c10.331-10.171,16.751-24.302,16.751-39.91 c0-30.899-25.138-56.037-56.037-56.037s-56.037,25.138-56.037,56.037c0,12.226,3.947,23.54,10.617,32.762l-33.742,33.954 c-4.438-2.404-9.515-3.771-14.907-3.771c-5.323,0-10.339,1.336-14.736,3.684l-19.721-20.688c5.93-7.037,9.514-16.113,9.514-26.014 c0-22.293-18.137-40.43-40.43-40.43S0,109.565,0,131.858s18.136,40.43,40.429,40.43c5.854,0,11.416-1.261,16.444-3.509 l21.387,22.436c-2.456,4.474-3.856,9.606-3.856,15.06c0,17.313,14.085,31.398,31.398,31.398s31.398-14.085,31.398-31.398 c0-5.388-1.365-10.462-3.766-14.897l33.756-33.969c9.207,6.635,20.491,10.559,32.68,10.559c8.815,0,17.157-2.052,24.584-5.694 l17.197,27.329c-5.258,6.136-8.446,14.097-8.446,22.793c0,19.345,15.739,35.084,35.084,35.084s35.083-15.739,35.083-35.084 S287.636,177.313,268.291,177.313z M161.834,111.931c0-20.974,17.063-38.037,38.037-38.037s38.037,17.063,38.037,38.037 s-17.063,38.037-38.037,38.037S161.834,132.904,161.834,111.931z M105.802,219.673c-7.388,0-13.398-6.011-13.398-13.398 s6.011-13.398,13.398-13.398s13.398,6.011,13.398,13.398S113.19,219.673,105.802,219.673z M18,131.858 c0-12.368,10.062-22.43,22.429-22.43s22.43,10.062,22.43,22.43s-10.062,22.43-22.43,22.43S18,144.226,18,131.858z M268.291,229.48 c-9.42,0-17.084-7.664-17.084-17.084s7.664-17.084,17.084-17.084s17.083,7.664,17.083,17.084S277.71,229.48,268.291,229.48z"/> </svg>
\ No newline at end of file
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+
+<svg version="1.1" id="IconsRepoEditor" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="-153.6 -153.6 819.20 819.20" style="enable-background:new 0 0 512 512;" xml:space="preserve" width="64px" height="64px" fill="#ffffff" stroke="#ffffff" stroke-width="0">
+
+<g id="IconsRepo_bgCarrier">
+
+<rect x="-153.6" y="-153.6" width="819.20" height="819.20" rx="409.6" fill="#f8a800" stroke-width="0"/>
+
+</g> <path d="M362.665,170.667V192c0,11.776,9.557,21.333,21.333,21.333s21.333-9.557,21.333-21.333v-21.333 c0-11.776-9.557-21.333-21.333-21.333S362.665,158.891,362.665,170.667z"/> <path d="M341.331,128h21.333c11.776,0,21.333-9.557,21.333-21.333s-9.557-21.333-21.333-21.333h-21.333 c-11.776,0-21.333,9.557-21.333,21.333S329.555,128,341.331,128z"/> <path d="M149.331,341.333V320c0-11.776-9.557-21.333-21.333-21.333s-21.333,9.557-21.333,21.333v21.333 c0,11.776,9.557,21.333,21.333,21.333S149.331,353.109,149.331,341.333z"/> <path d="M170.665,384h-21.333c-11.776,0-21.333,9.557-21.333,21.333s9.557,21.333,21.333,21.333h21.333 c11.776,0,21.333-9.557,21.333-21.333S182.441,384,170.665,384z"/> <path d="M469.397,298.667h-64.066v-21.333c0-11.776-9.557-21.333-21.333-21.333s-21.333,9.557-21.333,21.333v21.333h-64.062 c-23.488,0-42.603,19.115-42.603,42.603V384h-0.002c-11.776,0-21.333,9.557-21.333,21.333s9.557,21.333,21.333,21.333H256v42.731 C256,492.885,275.115,512,298.603,512h170.795C492.885,512,512,492.885,512,469.397V341.269 C512,317.781,492.885,298.667,469.397,298.667z M298.603,320v21.333h-0.021L298.603,320z M298.667,469.397l-0.011-63.895 c0-0.057,0.009-0.112,0.009-0.169c0-0.057-0.008-0.112-0.009-0.17l-0.011-63.83l170.688-0.064l0.064,128.064L298.667,469.397z"/> <path d="M256,170.731V128c11.775-0.001,21.331-9.558,21.331-21.333S267.775,85.335,256,85.333V42.603 C256,19.115,236.885,0,213.397,0H42.603C19.115,0,0,19.115,0,42.603v128.128c0,23.488,19.115,42.603,42.603,42.603h64.062v21.333 c0,11.776,9.557,21.333,21.333,21.333s21.333-9.557,21.333-21.333v-21.333h64.066C236.885,213.333,256,194.219,256,170.731z M42.603,42.667h-0.021l0.021-21.333V42.667z M42.667,170.731L42.645,42.667l170.688-0.064l0.032,63.395 c-0.007,0.224-0.034,0.443-0.034,0.669c0,0.23,0.027,0.454,0.034,0.682l0.032,63.318L42.667,170.731z"/> </svg>
\ No newline at end of file
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="18px" height="13px" viewBox="0 0 18 13" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+ <g id="Ecommerce" transform="translate(-844.000000, -3389.000000)" fill="#FFFFFF">
+ <g id="Product-Card-#1" transform="translate(150.000000, 2942.000000)">
+ <g id="Color" transform="translate(683.000000, 399.000000)">
+ <path d="M28.8443688,48.9224987 L28.095269,48.1585481 C27.8879809,47.9471506 27.5523969,47.9471506 27.3451088,48.1585481 L17.6752,58.0207009 C17.4673818,58.2320984 17.1317978,58.2320984 16.9255701,58.0207009 L12.6546937,53.6656962 C12.4474056,53.4542987 12.1118216,53.4542987 11.9055938,53.6656962 L11.1554337,54.4301874 C10.9481456,54.6415849 10.9481456,54.9838218 11.1554337,55.1946786 L16.5369712,60.6834443 C16.950487,61.105158 17.6211249,61.1056986 18.0351709,60.6839849 L28.8438387,49.6875305 C29.0516569,49.4766737 29.052187,49.1338962 28.8443688,48.9224987" id="Icon"></path>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
\ No newline at end of file
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+
+<svg version="1.1" id="IconsRepoEditor" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="64px" height="64px" viewBox="-45.25 -45.25 279.05 279.05" style="enable-background:new 0 0 188.547 188.547;" xml:space="preserve" fill="#ffffff" stroke="#ffffff" stroke-width="0">
+
+<g id="IconsRepo_bgCarrier">
+
+<rect x="-45.25" y="-45.25" width="279.05" height="279.05" rx="139.525" fill="#cf1c24" stroke-width="0"/>
+
+</g> <path d="M94.589,145.478v13.019h46.765l6.235,6.235v6.235H29.118v-6.235l6.235-6.235h46.765v-13.025H15.281 C6.884,145.471,0,138.584,0,130.188V32.861c0-8.397,6.877-15.281,15.281-15.281h146.143c8.415,0,15.284,6.875,15.284,15.281V64.05 c-1.925-2.125-3.964-4.125-6.235-5.849v-25.34c0-4.987-4.056-9.045-9.049-9.045H15.281c-4.993,0-9.045,4.058-9.045,9.045v78.626 c0,4.993,4.052,9.049,9.045,9.049h90.184c8.476,12.124,22.426,19.57,37.405,19.57c2.49,0,4.957-0.268,7.398-0.676l3.508,6.053 H94.589V145.478z M176.951,74.77c10.863,18.816,4.396,42.977-14.432,53.822c-18.815,10.863-42.965,4.415-53.828-14.425 c-10.859-18.804-4.396-42.953,14.42-53.813C141.919,49.491,166.082,55.951,176.951,74.77z M171.3,78.043 c-9.073-15.707-29.222-21.099-44.926-12.054c-15.704,9.073-21.111,29.216-12.026,44.92c9.066,15.704,29.21,21.136,44.907,12.062 C174.965,113.887,180.355,93.744,171.3,78.043z M172.42,126.162l-16.94,9.792l13.056,22.566l16.94-9.792L172.42,126.162z M187.229,151.834l-16.952,9.779c2.716,4.689,8.695,6.284,13.378,3.593S189.939,156.523,187.229,151.834z M108.058,45.64H26v6.235 h82.058V45.64z M86.795,60.366H26v6.235h60.794V60.366z M86.795,75.099H26v6.235h60.794V75.099z M26,96.063h60.794v-6.235H26 V96.063z"/> </svg>
\ No newline at end of file
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+
+<svg version="1.1" id="IconsRepoEditor" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="-68.96 -68.96 482.71 482.71" style="enable-background:new 0 0 344.789 344.789;" xml:space="preserve" width="64px" height="64px" fill="#ffffff" stroke="#ffffff" stroke-width="0">
+
+<g id="IconsRepo_bgCarrier">
+
+<rect x="-68.96" y="-68.96" width="482.71" height="482.71" rx="241.355" fill="#e4397c" stroke-width="0"/>
+
+</g> <path d="M259.395,64.283h-40c-4.142,0-7.5,3.357-7.5,7.5v38c0,4.143,3.358,7.5,7.5,7.5h8.5v32.745l-44,20.653V55.303h17.777 c2.82,0,5.402-1.582,6.683-4.095c1.28-2.513,1.043-5.531-0.615-7.813L178.462,3.092C177.051,1.149,174.795,0,172.395,0 c-2.401,0-4.657,1.149-6.068,3.092l-29.277,40.303c-1.658,2.282-1.895,5.301-0.615,7.813c1.281,2.513,3.862,4.095,6.683,4.095 h17.777v138.674l-44-20.653v-38.569c9.435-4.363,16-13.912,16-24.971c0-15.163-12.336-27.5-27.5-27.5 c-15.164,0-27.5,12.337-27.5,27.5c0,11.059,6.565,20.607,16,24.971v45.875c0,4.459,2.577,8.516,6.614,10.41l60.386,28.345v45.032 c-17.032,4.986-29.512,20.738-29.512,39.361c0,22.614,18.398,41.012,41.012,41.012c22.615,0,41.014-18.397,41.014-41.012 c0-18.623-12.48-34.376-29.514-39.361v-68.327l60.386-28.345c4.037-1.895,6.614-5.951,6.614-10.41v-40.051h8.5 c4.142,0,7.5-3.357,7.5-7.5v-38C266.895,67.641,263.537,64.283,259.395,64.283z"/> </svg>
\ No newline at end of file
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+
+<svg version="1.1" id="IconsRepoEditor" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="-76.05 -76.05 468.99 468.99" style="enable-background:new 0 0 316.89 316.89;" xml:space="preserve" width="64px" height="64px" fill="#FFFFFF" stroke="#FFFFFF" stroke-width="0">
+
+<g id="IconsRepo_bgCarrier">
+
+<rect x="-76.05" y="-76.05" width="468.99" height="468.99" rx="234.495" fill="#605ca8" stroke-width="0"/>
+
+</g> <path d="M182.47,212.195c0-0.754,0.036-1.5,0.057-2.25H38.5c-21.229,0-38.5,17.271-38.5,38.5s17.271,38.5,38.5,38.5h199.493 C205.905,277.24,182.47,247.408,182.47,212.195z M81.5,258.445h-35c-5.514,0-10-4.486-10-10c0-5.514,4.486-10,10-10h35 c5.514,0,10,4.486,10,10C91.5,253.959,87.014,258.445,81.5,258.445z"/> <path d="M38.5,196.945h145.476c7.114-35.78,38.743-62.837,76.581-62.837c9.54,0,18.682,1.727,27.139,4.872 c-6.697-11.378-19.066-19.035-33.196-19.035h-216c-21.229,0-38.5,17.271-38.5,38.5S17.271,196.945,38.5,196.945z M46.5,148.445h35 c5.514,0,10,4.486,10,10c0,5.514-4.486,10-10,10h-35c-5.514,0-10-4.486-10-10C36.5,152.931,40.986,148.445,46.5,148.445z"/> <path d="M38.5,106.945h216c21.228,0,38.5-17.271,38.5-38.5s-17.272-38.5-38.5-38.5h-216c-21.229,0-38.5,17.271-38.5,38.5 S17.271,106.945,38.5,106.945z M237.5,55.695c7.03,0,12.75,5.72,12.75,12.75s-5.72,12.75-12.75,12.75 c-7.03,0-12.75-5.72-12.75-12.75S230.47,55.695,237.5,55.695z M46.5,58.445h35c5.514,0,10,4.486,10,10s-4.486,10-10,10h-35 c-5.514,0-10-4.486-10-10S40.986,58.445,46.5,58.445z"/> <path d="M260.557,155.862c-31.112,0-56.333,25.221-56.333,56.333s25.221,56.333,56.333,56.333s56.332-25.221,56.332-56.333 S291.669,155.862,260.557,155.862z M290.653,200.261l-35.654,35.653c-0.754,0.755-1.759,1.172-2.828,1.172 c-1.069,0-2.074-0.416-2.829-1.172l-17.88-17.88c-0.756-0.755-1.172-1.76-1.172-2.828c0-1.068,0.416-2.073,1.172-2.829l3.535-3.535 c0.754-0.755,1.759-1.172,2.828-1.172c1.068,0,2.073,0.416,2.828,1.171l11.518,11.517l29.291-29.289 c0.754-0.755,1.759-1.172,2.828-1.172c1.069,0,2.074,0.417,2.829,1.172l3.535,3.535c0.755,0.754,1.172,1.759,1.172,2.828 C291.825,198.501,291.409,199.506,290.653,200.261z"/> </svg>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+var Tar =
+/******/ (function(modules) { // webpackBootstrap
+/******/ // The module cache
+/******/ var installedModules = {};
+/******/
+/******/ // The require function
+/******/ function __webpack_require__(moduleId) {
+/******/
+/******/ // Check if module is in cache
+/******/ if(installedModules[moduleId]) {
+/******/ return installedModules[moduleId].exports;
+/******/ }
+/******/ // Create a new module (and put it into the cache)
+/******/ var module = installedModules[moduleId] = {
+/******/ i: moduleId,
+/******/ l: false,
+/******/ exports: {}
+/******/ };
+/******/
+/******/ // Execute the module function
+/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ // Flag the module as loaded
+/******/ module.l = true;
+/******/
+/******/ // Return the exports of the module
+/******/ return module.exports;
+/******/ }
+/******/
+/******/
+/******/ // expose the modules object (__webpack_modules__)
+/******/ __webpack_require__.m = modules;
+/******/
+/******/ // expose the module cache
+/******/ __webpack_require__.c = installedModules;
+/******/
+/******/ // identity function for calling harmony imports with the correct context
+/******/ __webpack_require__.i = function(value) { return value; };
+/******/
+/******/ // define getter function for harmony exports
+/******/ __webpack_require__.d = function(exports, name, getter) {
+/******/ if(!__webpack_require__.o(exports, name)) {
+/******/ Object.defineProperty(exports, name, {
+/******/ configurable: false,
+/******/ enumerable: true,
+/******/ get: getter
+/******/ });
+/******/ }
+/******/ };
+/******/
+/******/ // getDefaultExport function for compatibility with non-harmony modules
+/******/ __webpack_require__.n = function(module) {
+/******/ var getter = module && module.__esModule ?
+/******/ function getDefault() { return module['default']; } :
+/******/ function getModuleExports() { return module; };
+/******/ __webpack_require__.d(getter, 'a', getter);
+/******/ return getter;
+/******/ };
+/******/
+/******/ // Object.prototype.hasOwnProperty.call
+/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ // __webpack_public_path__
+/******/ __webpack_require__.p = "";
+/******/
+/******/ // Load entry module and return exports
+/******/ return __webpack_require__(__webpack_require__.s = 2);
+/******/ })
+/************************************************************************/
+/******/ ([
+/* 0 */
+/***/ (function(module, exports) {
+
+/*
+ * tar-js
+ * MIT (c) 2011 T. Jameson Little
+ */
+
+(function () {
+ "use strict";
+
+ var lookup = [
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
+ 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+ 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
+ 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
+ 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+ 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+ 'w', 'x', 'y', 'z', '0', '1', '2', '3',
+ '4', '5', '6', '7', '8', '9', '+', '/'
+ ];
+ function clean(length) {
+ var i, buffer = new Uint8Array(length);
+ for (i = 0; i < length; i += 1) {
+ buffer[i] = 0;
+ }
+ return buffer;
+ }
+
+ function extend(orig, length, addLength, multipleOf) {
+ var newSize = length + addLength,
+ buffer = clean((parseInt(newSize / multipleOf) + 1) * multipleOf);
+
+ buffer.set(orig);
+
+ return buffer;
+ }
+
+ function pad(num, bytes, base) {
+ num = num.toString(base || 8);
+ return "000000000000".substr(num.length + 12 - bytes) + num;
+ }
+
+ function stringToUint8 (input, out, offset) {
+ var i, length;
+
+ out = out || clean(input.length);
+
+ offset = offset || 0;
+ for (i = 0, length = input.length; i < length; i += 1) {
+ out[offset] = input.charCodeAt(i);
+ offset += 1;
+ }
+
+ return out;
+ }
+
+ function uint8ToBase64(uint8) {
+ var i,
+ extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes
+ output = "",
+ temp, length;
+
+ function tripletToBase64 (num) {
+ return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F];
+ };
+
+ // go through the array every three bytes, we'll deal with trailing stuff later
+ for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {
+ temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]);
+ output += tripletToBase64(temp);
+ }
+
+ // this prevents an ERR_INVALID_URL in Chrome (Firefox okay)
+ switch (output.length % 4) {
+ case 1:
+ output += '=';
+ break;
+ case 2:
+ output += '==';
+ break;
+ default:
+ break;
+ }
+
+ return output;
+ }
+
+ module.exports.clean = clean;
+ module.exports.pad = pad;
+ module.exports.extend = extend;
+ module.exports.stringToUint8 = stringToUint8;
+ module.exports.uint8ToBase64 = uint8ToBase64;
+}());
+
+
+/***/ }),
+/* 1 */
+/***/ (function(module, exports, __webpack_require__) {
+
+/*
+ * tar-js
+ * MIT (c) 2011 T. Jameson Little
+ */
+
+(function () {
+ "use strict";
+
+/*
+struct posix_header { // byte offset
+ char name[100]; // 0
+ char mode[8]; // 100
+ char uid[8]; // 108
+ char gid[8]; // 116
+ char size[12]; // 124
+ char mtime[12]; // 136
+ char chksum[8]; // 148
+ char typeflag; // 156
+ char linkname[100]; // 157
+ char magic[6]; // 257
+ char version[2]; // 263
+ char uname[32]; // 265
+ char gname[32]; // 297
+ char devmajor[8]; // 329
+ char devminor[8]; // 337
+ char prefix[155]; // 345
+ // 500
+};
+*/
+
+ var utils = __webpack_require__(0),
+ headerFormat;
+
+ headerFormat = [
+ {
+ 'field': 'fileName',
+ 'length': 100
+ },
+ {
+ 'field': 'fileMode',
+ 'length': 8
+ },
+ {
+ 'field': 'uid',
+ 'length': 8
+ },
+ {
+ 'field': 'gid',
+ 'length': 8
+ },
+ {
+ 'field': 'fileSize',
+ 'length': 12
+ },
+ {
+ 'field': 'mtime',
+ 'length': 12
+ },
+ {
+ 'field': 'checksum',
+ 'length': 8
+ },
+ {
+ 'field': 'type',
+ 'length': 1
+ },
+ {
+ 'field': 'linkName',
+ 'length': 100
+ },
+ {
+ 'field': 'ustar',
+ 'length': 8
+ },
+ {
+ 'field': 'owner',
+ 'length': 32
+ },
+ {
+ 'field': 'group',
+ 'length': 32
+ },
+ {
+ 'field': 'majorNumber',
+ 'length': 8
+ },
+ {
+ 'field': 'minorNumber',
+ 'length': 8
+ },
+ {
+ 'field': 'filenamePrefix',
+ 'length': 155
+ },
+ {
+ 'field': 'padding',
+ 'length': 12
+ }
+ ];
+
+ function formatHeader(data, cb) {
+ var buffer = utils.clean(512),
+ offset = 0;
+
+ headerFormat.forEach(function (value) {
+ var str = data[value.field] || "",
+ i, length;
+
+ for (i = 0, length = str.length; i < length; i += 1) {
+ buffer[offset] = str.charCodeAt(i);
+ offset += 1;
+ }
+
+ offset += value.length - i; // space it out with nulls
+ });
+
+ if (typeof cb === 'function') {
+ return cb(buffer, offset);
+ }
+ return buffer;
+ }
+
+ module.exports.structure = headerFormat;
+ module.exports.format = formatHeader;
+}());
+
+
+/***/ }),
+/* 2 */
+/***/ (function(module, exports, __webpack_require__) {
+
+/*
+ * tar-js
+ * MIT (c) 2011 T. Jameson Little
+ */
+
+(function () {
+ "use strict";
+
+ var header = __webpack_require__(1),
+ utils = __webpack_require__(0),
+ recordSize = 512,
+ blockSize;
+
+ function Tar(recordsPerBlock) {
+ this.written = 0;
+ blockSize = (recordsPerBlock || 20) * recordSize;
+ this.out = utils.clean(blockSize);
+ }
+
+ Tar.prototype.append = function (filepath, input, opts, callback) {
+ var data,
+ checksum,
+ mode,
+ mtime,
+ uid,
+ gid,
+ headerArr;
+
+ if (typeof input === 'string') {
+ input = utils.stringToUint8(input);
+ } else if (input.constructor !== Uint8Array.prototype.constructor) {
+ throw 'Invalid input type. You gave me: ' + input.constructor.toString().match(/function\s*([$A-Za-z_][0-9A-Za-z_]*)\s*\(/)[1];
+ }
+
+ if (typeof opts === 'function') {
+ callback = opts;
+ opts = {};
+ }
+
+ opts = opts || {};
+
+ mode = opts.mode || parseInt('777', 8) & 0xfff;
+ mtime = opts.mtime || Math.floor(+new Date() / 1000);
+ uid = opts.uid || 0;
+ gid = opts.gid || 0;
+
+ data = {
+ fileName: filepath,
+ fileMode: utils.pad(mode, 7),
+ uid: utils.pad(uid, 7),
+ gid: utils.pad(gid, 7),
+ fileSize: utils.pad(input.length, 11),
+ mtime: utils.pad(mtime, 11),
+ checksum: ' ',
+ type: opts.type || '0',
+ ustar: 'ustar ',
+ owner: opts.owner || '',
+ group: opts.group || ''
+ };
+
+ // calculate the checksum
+ checksum = 0;
+ Object.keys(data).forEach(function (key) {
+ var i, value = data[key], length;
+
+ for (i = 0, length = value.length; i < length; i += 1) {
+ checksum += value.charCodeAt(i);
+ }
+ });
+
+ data.checksum = utils.pad(checksum, 6) + "\u0000 ";
+
+ headerArr = header.format(data);
+
+ var i, offset, length;
+
+ this.out.set(headerArr, this.written);
+
+ this.written += headerArr.length;
+
+ // If there is not enough space in this.out, we need to expand it to
+ // fit the new input.
+ if (this.written + input.length > this.out.length) {
+ this.out = utils.extend(this.out, this.written, input.length, blockSize);
+ }
+
+ this.out.set(input, this.written);
+
+ // to the nearest multiple of recordSize
+ this.written += input.length + (recordSize - (input.length % recordSize || recordSize));
+
+ // make sure there's at least 2 empty records worth of extra space
+ if (this.out.length - this.written < recordSize * 2) {
+ this.out = utils.extend(this.out, this.written, recordSize * 2, blockSize);
+ }
+
+ if (typeof callback === 'function') {
+ callback(this.out);
+ }
+
+ return this.out;
+ };
+
+ Tar.prototype.clear = function () {
+ this.written = 0;
+ this.out = utils.clean(blockSize);
+ };
+
+ module.exports = Tar;
+}());
+
+
+/***/ })
+/******/ ]);
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/** Styles for the application **/
+@import "../../assets/scss/mixins/mixin";
+@import "../../assets/scss/variable";
+$customnavbar-padding-x: ($spacer / 0.5) !default;
+* {
+ outline: 0;
+}
+button[type=submit]:focus, .sidebar-body button[type=button]:focus {
+ @include box-shadow(0, 0, 0, 0.2rem, lighten($primary, 50%) !important);
+}
+.btn-danger:focus{
+ @include box-shadow(0, 0, 0, 0.2rem, lighten($danger, 30%) !important);
+}
+body,
+.list-overflow,
+.scroll-box,
+.smarttable-style,
+.modal-body-custom-height,
+.layout-wrapper, .CodeMirror-vscrollbar, .ng-sidebar, .runninginstances .popover-body {
+ &::-webkit-scrollbar {
+ @include wh-value(10px, null);
+ }
+ &::-webkit-scrollbar-thumb {
+ background-clip: content-box;
+ @include border(all, 3, solid, transparent);
+ @include roundedCorners(7);
+ @include box-shadow(0, 0, 0, 10px, rgba($black, 0.8), inset);
+ }
+ &::-webkit-scrollbar-button {
+ @include wh-value(0, 0);
+ @include flexbox(none, null, null, null, null, null);
+ }
+ &::-webkit-scrollbar-corner {
+ @include background(null, transparent, null, null, null);
+ }
+}
+body {
+ @include font-family("Roboto");
+ @include background(null, $theme-bg-color, null, null, null);
+ overflow-x: hidden;
+ .osm-logo {
+ @include wh-value(100px, auto);
+ }
+ .bg-light {
+ @include background(null, $theme-bg-color !important, null, null, null);
+ }
+ a {
+ color: $primary;
+ &:hover,
+ &:focus {
+ text-decoration: none;
+ }
+ }
+ .badge {
+ @include line-height(normal);
+ &.badge-pill {
+ @include padding-percentage-value(0.2em, 0.6em, 0.2em, 0.6em);
+ }
+ }
+ button {
+ outline: none;
+ @include box-shadow(0, 0, 0, 0, transparent);
+ &:hover,
+ &:focus,
+ &:active {
+ outline: none;
+ @include box-shadow(0, 0, 0, 0, transparent !important);
+ }
+ &.btn-primary,
+ &.btn-default,
+ &.btn-warning,
+ &.btn-outline-primary:hover,
+ &.btn-outline-warning:hover {
+ color: $white;
+ &:hover,
+ &:focus,
+ &:not(:disabled):not(.disabled):active {
+ color: $white;
+ @include background(null, $primary, null, null, null);
+ border-color: $primary;
+ }
+ &:disabled {
+ cursor: not-allowed;
+ }
+ }
+ }
+ .row {
+ margin-left: 0;
+ margin-right: 0;
+ }
+ .navbar {
+ @include padding-percentage-value(
+ $navbar-padding-y,
+ $customnavbar-padding-x,
+ $navbar-padding-y,
+ $customnavbar-padding-x
+ );
+ }
+ .form-control {
+ @include roundedCorners(4);
+ @include font(null, 12px, null);
+ &::placeholder {
+ color: $gray-400;
+ }
+ }
+ .modal-dialog {
+ max-width: 600px;
+ }
+ .header-style {
+ @include font(null, 1.2rem, 700);
+ color: $primary;
+ @include line-height(1.25);
+ }
+ .cursor-default {
+ cursor: default;
+ }
+ .cursor-pointer {
+ cursor: pointer;
+ }
+ .mr-top-5 {
+ @include margin-value-percentage(5px, auto, auto, auto);
+ }
+ .padLeft0 {
+ padding-left: 0px;
+ }
+ .padRight0 {
+ padding-right: 0px;
+ }
+ .mandatory-label {
+ @include font(null, 10px, null);
+ }
+ .dropzone {
+ min-height: 50px;
+ @include flexbox(table, null, null, null, null, null);
+ @include wh-value(100%, 50px);
+ @include border(all, 1, dashed, $secondary);
+ cursor: pointer;
+ .text-wrapper {
+ @include padding-value(5, 5, 5, 5);
+ @include flexbox(table-cell, null, null, null, null, null);
+ vertical-align: middle;
+ }
+ .file-drop-title {
+ @include font(null, 16px, null);
+ }
+ }
+ .close {
+ opacity: 1 !important;
+ }
+ .roles-section {
+ .card {
+ .bg-secondary {
+ @include background(null, $gray-400 !important, null, null, null);
+ }
+ }
+ }
+ .card {
+ margin-bottom: 1rem;
+ }
+ .custom-card {
+ @include border(top, 3, solid, $primary);
+ @include roundedCorners(3);
+ .custom-card-body {
+ @include padding-value(15, 15, 15, 15);
+ }
+ }
+ table-cell-default-editor select-editor select {
+ @include wh-value(null, calc(2rem + 8px) !important);
+ @include padding-value(0, 10, 0, 10);
+ }
+ .CodeMirror {
+ min-height: 400px !important;
+ }
+ .table-layout-fixed {
+ table-layout: fixed;
+ word-wrap: break-word;
+ }
+ .border-radius-default {
+ @include roundedCorners(3);
+ }
+ /** Model Popup-Design **/
+ .modal-body-custom-height {
+ max-height: 65vh;
+ overflow-y: auto;
+ }
+ /** Hide input clear icon in IE */
+ input::-ms-clear {
+ @include flexbox(none, null, null, null, null, null);
+ }
+ /** Overwrite the tooltip z-index */
+ .tooltip {
+ z-index: 1010;
+ }
+ /** Popover Header **/
+ .popover-header {
+ color: $primary;
+ @include background(null, $theme-bg-color, null, null, null);
+ }
+ /** Vim Show running instance Details **/
+ .runninginstances{
+ width:200px;
+ .popover-body{
+ max-height: 200px;
+ overflow-y: scroll;
+ }
+ }
+ /****************************************************************************/
+ /************************** Smart table custom design ***********************/
+ /****************************************************************************/
+ ng2-smart-table {
+ @include font(null, 15px, null);
+ color: $gray-700;
+ .form-control {
+ @include wh-value(null, auto);
+ }
+ &.dataTables_empty td {
+ text-align: center;
+ }
+ ng2-smart-table-title {
+ * {
+ @include font(null, 12px, null);
+ }
+ a {
+ color: $gray-700 !important;
+ @include flexbox(block, null, null, null, null, null);
+ text-decoration: none;
+ &::after {
+ content: "\f0dc" !important;
+ @include font-family("Font Awesome 5 Free");
+ float: right;
+ color: $gray-500;
+ @include wh-value(0, 0);
+ }
+ &.asc::after {
+ content: "\f0de" !important;
+ @include font-family("Font Awesome 5 Free");
+ float: right;
+ color: $gray-500;
+ }
+ &.desc::after {
+ content: "\f0dd" !important;
+ @include font-family("Font Awesome 5 Free");
+ float: right;
+ color: $gray-500;
+ }
+ &:hover {
+ text-decoration: none !important;
+ }
+ &.sort.desc::after {
+ transform: none !important;
+ margin-bottom: 0;
+ }
+ &.sort.asc::after,
+ &.sort.desc::after {
+ content: "";
+ @include flexbox(inline-block, null, null, null, null, null);
+ @include wh-value(0, 0);
+ @include border(all, 0, solid, transparent !important);
+ margin-bottom: 0 !important;
+ }
+ }
+ span {
+ color: $gray-700;
+ }
+ }
+ ng2-smart-table-cell {
+ word-break: break-word;
+ table-cell-view-mode {
+ @include font(null, 12px, null);
+ .icon-label {
+ @include font(null, 20px, null);
+ @include flexbox(inline-block, null, null, null, null, null);
+ @include wh-value(100px, 0);
+ text-align: center;
+ cursor: default;
+ }
+ }
+ }
+ .ng2-smart-filter {
+ @include wh-value(null, calc(2rem + 2px) !important);
+ @include font(null, 12px, null);
+ margin-top: 6px;
+ }
+ table.list-data {
+ tr td,
+ tr th {
+ @include padding-value(2, 10, 2, 10);
+ vertical-align: middle !important;
+ }
+ tbody {
+ tr.selected {
+ background: none !important;
+ }
+ }
+ }
+ default-table-filter {
+ select-filter {
+ select.form-control {
+ @include flexbox(inline-block, null, null, null, null, null);
+ @include wh-value(null, calc(1.5rem + 2px) !important);
+ vertical-align: middle;
+ background: $white
+ url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E")
+ no-repeat right 0.75rem center;
+ background-size: 8px 10px;
+ @include border(all, 1, solid, $gray-200);
+ @include roundedCorners(2);
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+ &::-ms-expand {
+ visibility: hidden;
+ }
+ }
+ }
+ select-filter {
+ select {
+ @include roundedCorners(4);
+ }
+ }
+ input-filter {
+ input[type="text"] {
+ @include position_value(relative, null, null, null, null);
+ }
+ &:after {
+ @include position_value(relative, -26px, null, null, 100%);
+ content: "\f002";
+ @include font("Font Awesome 5 Free", 10px, null);
+ @include padding-value(0, 0, 0, 2);
+ color: $gray-500;
+ }
+ }
+ }
+ ng2-smart-table-pager {
+ @include flexbox(null, null, row-reverse, null, null, null);
+ @include padding-value(5, 20, 5, 20);
+ .ng2-smart-pagination {
+ .ng2-smart-page-item {
+ @include font(null, 10px, null);
+ a {
+ &:hover {
+ text-decoration: none;
+ }
+ }
+ .ng2-smart-page-link {
+ @include font(null, 12px !important, null);
+ &.page-link {
+ text-align: center;
+ vertical-align: middle;
+ color: $primary;
+ @include border(all, 1, solid, $primary !important);
+ &:hover {
+ @include background(null, $primary !important, null, null, null);
+ color: $white;
+ }
+ }
+ }
+ span.ng2-smart-page-link.page-link {
+ color: $white;
+ @include background(null, $primary !important, null, null, null);
+ @include border(all, 1, solid, $primary !important);
+ }
+ }
+ }
+ }
+ }
+ /****************************************************************************/
+ /*********************** Button styles under list class *********************/
+ /****************************************************************************/
+ .list {
+ &.action {
+ button.btn.btn-primary {
+ @include padding-value(2, 8, 2, 8);
+ }
+ }
+ button:focus {
+ outline: 0;
+ @include box-shadow(0, 0, 0, 0, transparent);
+ }
+ button.btn.btn-primary {
+ color: $primary;
+ @include background(null, $white, null, null, null);
+ &:not(.active:hover) {
+ @include background(null, $white, null, null, null);
+ }
+ &:active {
+ color: $primary;
+ @include background(null, $white, null, null, null);
+ }
+ &.action-button {
+ color: $white;
+ @include background(null, $primary !important, null, null, null);
+ &:hover {
+ @include background(null, $primary, null, null, null);
+ }
+ }
+ }
+ .dropdown-menu {
+ @include border(all, 1, solid, $primary);
+ @include padding-value(0, 0, 0, 0);
+ button.btn.btn-primary {
+ @include background(null, transparent, null, null, null);
+ @include padding-value(8, 8, 8, 8);
+ @include roundedCorners(0);
+ &:hover {
+ @include background(null, $primary, null, null, null);
+ color: $white;
+ }
+ &:not(:last-child) {
+ @include border(bottom, 1, solid, $primary);
+ }
+ }
+ }
+ }
+ /****************************************************************************/
+ /*********************** Custom tabel design in topology ********************/
+ /****************************************************************************/
+ .custom-table {
+ td:first-child {
+ @include font(null, null, bold);
+ text-align: right;
+ }
+ th,
+ td {
+ @include padding-value(5, 7, 5, 7);
+ @include font(null, 10px, null);
+ @include line-height(15px);
+ }
+ }
+ /****************************************************************************/
+ /************************** Ng select custom design *************************/
+ /****************************************************************************/
+ .ng-select {
+ &.is-invalid .ng-select-container {
+ @include border(all, 1, solid, $red);
+ }
+ .ng-select-container {
+ @include border(all, 1, solid, $gray-200);
+ .ng-value-container .ng-placeholder {
+ color: $gray-80;
+ }
+ }
+ }
+ /****************************************************************************/
+ /******************** Custom nav section for default status *****************/
+ /****************************************************************************/
+ .list-utilites-actions {
+ @include flexbox(flex, null, row, null, center, null);
+ nav.custom-items-config {
+ @include position_value(relative, null, null, null, null);
+ @include roundedCorners(3);
+ span {
+ @include font(null, 13px, 600);
+ @include flexbox(inline-block, null, null, null, null, null);
+ @include position_value(relative, null, null, null, null);
+ text-decoration: none;
+ text-align: center;
+ @include margin-value(0, 0, 0, 10);
+ &:first-child {
+ @include margin-value(0, 0, 0, 0);
+ }
+ i {
+ @include font(null, 14px, null);
+ @include margin-value(0, 5, 0, 0);
+ }
+ }
+ }
+ }
+ /****************************************************************************/
+ /************************* File upload custom design ************************/
+ /****************************************************************************/
+ .custom-file-label {
+ color: $primary;
+ @include roundedCorners(4);
+ @include border(all, 1, solid, $primary);
+ overflow: hidden;
+ @include margin-value(0, 0, 0, 0);
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ padding-right: 80px;
+ &::after {
+ color: $white;
+ @include background(null, $primary, null, null, null);
+ }
+ }
+ /****************************************************************************/
+ /************************* Notifier Container Design ************************/
+ /****************************************************************************/
+ .notifier__container {
+ ul {
+ @include margin-value(0, 0, 0, 0);
+ }
+ }
+ /***************************************************************************/
+ /************************* Topology Common Design **************************/
+ /****************************************************************************/
+ .ns-composer-form,
+ .vnf-composer-form,
+ .ns-instance-form {
+ @include font(null, 12px, null);
+ .ns-svg,
+ .vnf-svg {
+ @include wh-value(30px, 25px);
+ }
+ .svg-container {
+ min-height: 60vh;
+ }
+ .form-control {
+ @include font(null, 10px, null);
+ }
+ .scroll-box {
+ max-height: 285px;
+ overflow-y: scroll;
+ }
+ .border-all {
+ @include border(all, 1, solid, $primary);
+ }
+ .list-group {
+ &.inside-svg {
+ .list-group-item {
+ @include padding-value(3.2, 8, 3.2, 8);
+ }
+ }
+ &.dragable {
+ .list-group-item {
+ cursor: move;
+ @include padding-value(4.8, 4.8, 4.8, 4.8);
+ @include margin-value(0, 0, 5, 0);
+ @include background(null, $gray-200, null, null, null);
+ @include flexbox(flex, null, null, null, center, null);
+ border: none;
+ .span-overflow-text {
+ @include wh-value(90%, null);
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ @include line-height(25px);
+ }
+ }
+ }
+ }
+ .drag-icon {
+ color: $gray-600;
+ @include font(null, 15px, null);
+ }
+ .ctrl {
+ cursor: move;
+ }
+ svg {
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ -o-user-select: none;
+ user-select: none;
+ image.node:hover,
+ circle.node:hover {
+ opacity: 0.7 !important;
+ }
+ image.active,
+ circle.active {
+ opacity: 0.7 !important;
+ }
+ path.link {
+ stroke: $dark-gray;
+ stroke-width: 2px;
+ fill: none;
+ &:hover {
+ stroke-width: 4px;
+ }
+ .dragline {
+ pointer-events: none;
+ }
+ }
+ .node_text {
+ text-anchor: middle;
+ pointer-events: none;
+ }
+ :not(.ctrl) {
+ cursor: pointer;
+ }
+ }
+ fieldset {
+ @include border(all, 1, solid, $primary);
+ legend {
+ @include padding-value(0, 5, 0, 5);
+ @include font(null, 15px, null);
+ color: $primary;
+ &.vl-legend,
+ &.element-legend {
+ @include wh-value(55%, null);
+ }
+ &.vnfd-legend {
+ @include wh-value(25%, null);
+ }
+ }
+ }
+ .btn-icon {
+ @include wh-value(36px, 36px);
+ text-align: center;
+ @include margin-value(0, 10, 10, 0);
+ }
+ .topology-btn {
+ color: $primary;
+ border-color: $primary;
+ &:hover,
+ &.pinned {
+ color: $white !important;
+ @include background(null, $primary !important, null, null, null);
+ }
+ }
+ .badgegroup {
+ @include flexbox(flex, flex-end, row, center, center, null);
+ }
+ }
+ .ns-topology-sidebar-container,
+ .vnf-topology-sidebar-container,
+ .ns-instance-topology-sidebar-container {
+ @include position_value(absolute !important, 0px, null, null, 0px);
+ .ng-sidebar {
+ @include wh-value(27%, null);
+ @include background(null, $white, null, null, null);
+ @include border(all, 1, solid, $gray-300);
+ .sidebar-header {
+ @include background(null, $modalheader-gray, null, null, null);
+ @include padding-value(5, 10, 5, 10);
+ @include border(bottom, 1, solid, $gray-300);
+ @include flexbox(flex, space-between, null, center, center, null);
+ .topology_title {
+ color: $primary;
+ }
+ }
+ .sidebar-body {
+ @include padding-value(10, 5, 10, 5);
+ }
+ }
+ .ng-sidebar__content {
+ button {
+ @include position_value(absolute, 45%, null, null, 0px);
+ @include background(null, $primary, null, null, null);
+ }
+ .detail-sidebar {
+ @include flexbox(inline-block, null, null, null, null, null);
+ @include position_value(relative, null, null, null, null);
+ animation: push 0.5s infinite linear;
+ }
+ }
+ @keyframes push {
+ 0% {
+ right: 0;
+ }
+ 50% {
+ right: -0.2em;
+ }
+ 70% {
+ right: -0.3em;
+ }
+ 100% {
+ right: 0;
+ }
+ }
+ }
+}
+/****************************************************************************/
+/************************** MEDIA QUERIES ***********************************/
+/****************************************************************************/
+@media (max-width: map-get($grid-breakpoints, md)) {
+ .smarttable-style {
+ overflow-x: auto;
+ white-space: nowrap;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @ file contains @mixin functions for animation property
+ * example for animation: @include animation(rotate 1s linear);
+ * example for keyframes: @include keyframes(rotate) {
+ 0% { @include rotate(0); }
+ 100% { @include rotate(359); }
+ }
+ */
+
+// @mixin for animation properties
+@mixin animation ($animation) {
+ -webkit-animation: #{$animation};
+ -moz-animation: #{$animation};
+ -ms-animation: #{$animation};
+ -o-animation: #{$animation};
+ animation: #{$animation};
+}
+
+// @mixin for keyframes properties
+@mixin keyframes ($animation) {
+ @-webkit-keyframes #{$animation} {
+ @content;
+ }
+ @-moz-keyframes #{$animation} {
+ @content;
+ }
+ @-o-keyframes #{$animation} {
+ @content;
+ }
+ @keyframes #{$animation} {
+ @content;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @ file contains @mixin functions for background property
+ * example: @include background(url, orange, 20px, repeat, center);
+ */
+
+// @mixin for background properties
+@mixin background($url, $color, $size, $repeat, $position) {
+ background-image: $url;
+ background-color: $color;
+ background-size : $size;
+ background-repeat: $repeat;
+ background-position: $position;
+}
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @ file contains @mixin functions for border
+ * example: @include border(top, 1, solid, #000);
+ */
+
+// @mixin for border size and color
+@mixin border($side, $size, $type, $color){
+ @if ($side == top) {
+ border-top: $size+px $type $color;
+ } @else if ($side == right) {
+ border-right: $size+px $type $color;
+ } @else if ($side == left) {
+ border-left: $size+px $type $color;
+ } @else if ($side == bottom ) {
+ border-bottom: $size+px $type $color;
+ } @else if($side == all ){
+ border: $size+px $type $color;
+ }@else {
+ @if ($size == thin){
+ border: $size $type $color;
+ }
+ @else {
+ border: $size+px $type $color;
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @ file contains @mixin functions for box-shadow
+ * example: @include box-shadow(1px, 2px, 2px, 2px, #000);
+ */
+
+// @mixin for box shadow
+@mixin box-shadow($hoff: false, $voff: false, $blur: false, $spread: false, $color: false, $inset: false) {
+ @if $inset {
+ -webkit-box-shadow:inset $hoff $voff $blur $spread $color;
+ -moz-box-shadow:inset $hoff $voff $blur $spread $color;
+ box-shadow:inset $hoff $voff $blur $spread $color;
+ } @else {
+ -webkit-box-shadow: $hoff $voff $blur $spread $color;
+ -moz-box-shadow: $hoff $voff $blur $spread $color;
+ box-shadow: $hoff $voff $blur $spread $color;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @ file contains custom @mixin functions
+ */
+
+// @mixin for container width and height
+@mixin wh-value($width, $height) {
+ width: $width;
+ height: $height;
+}
+
+// @mixin for padding values
+@mixin padding-value($top, $right, $bottom, $left) {
+ padding: $top+px $right+px $bottom+px $left+px;
+}
+
+// @mixin for any padding values
+@mixin padding-percentage-value($top: null, $right: null, $bottom: null, $left: null) {
+ padding: $top $right $bottom $left;
+}
+
+// @mixin for margin values
+@mixin margin-value($top, $right, $bottom, $left) {
+ margin: $top+px $right+px $bottom+px $left+px;
+}
+
+// @mixin for margin values in percentage
+@mixin margin-value-percentage($top: null, $right: null, $bottom: null, $left: null) {
+ margin: $top $right $bottom $left;
+}
+
+// @mixin for center-align element/container
+@mixin align-center($topbottom, $width) {
+ margin: $topbottom auto;
+ width: $width;
+}
+
+// @mixin for center-align with top and bottom margin element/container
+@mixin tband-align-center($topbottom, $width, $bottommargin) {
+ margin: $topbottom auto $bottommargin;
+ width: $width;
+}
+
+// @mixin for transform style
+@mixin transform($x, $y, $z)
+{
+ transform: translate3d($x+px, $y+px, $z+px);
+ -webkit-transform: translate3d($x+px, $y+px, $z+px);
+}
+
+// @mixin for font-family setting
+@mixin font-family($font){
+ font-family: $font;
+}
+
+// @mixin for font-style setting
+@mixin font-style($font-style){
+ font-style: $font-style;
+}
+
+// Mixin for font & its attributes
+@mixin font($family, $size, $weight) {
+ font-family: $family;
+ font-size: $size;
+ font-weight: $weight;
+}
+
+// @mixin for line-height setting
+@mixin line-height($line-height){
+ line-height: $line-height;
+}
+
+// @mixin for letter-spacing setting
+@mixin letter-spacing($letter-spacing){
+ letter-spacing: $letter-spacing;
+}
+
+// @mixin to manipulate placeholder attribute in input element
+@mixin placeholder {
+ ::-webkit-input-placeholder {@content}
+ :-moz-placeholder {@content}
+ ::-moz-placeholder {@content}
+ :-ms-input-placeholder {@content}
+}
+
+// mixins for user-select
+@mixin user-select($select) {
+ @each $pre in -webkit-, -moz-, -ms-, -o- {
+ #{$pre + user-select}: #{$select};
+ }
+ #{user-select}: #{$select};
+ }
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @ file contains @mixin function for flex properties
+ * example: @include flexbox(flex, flex-start, row-reverse, center, center, flex-end);
+ * 1. display: flex | inline-flex
+ * 2. justify-content : flex-start | flex-end | center | space-between | space-around
+ * 3. flex-direction: row | row-reverse | column | column-reverse
+ * 4. align-content: flex-start | flex-end | center | space-between | space-around | stretch
+ * 5. align-items: flex-start | flex-end | center | baseline | stretch
+ * 6. align-self: auto | flex-start | flex-end | center | baseline | stretch
+ */
+
+@mixin flexbox($display: null, $justify: null, $direction: null, $aligncontent: null, $alignitems: null, $alignself: null) {
+display: $display;
+justify-content: $justify;
+flex-direction: $direction;
+align-content: $aligncontent;
+align-items: $alignitems;
+align-self: $alignself;
+}
+
+/** To set flexible length for items
+ * flex-grow: how much an item will grow relative to the rest of the flexible items
+ flex-shrink: how much an item will shrink relative to the rest of the flexible items
+ flex-basis: The length of the item. Legal values: "auto", "inherit", or a number followed by "%", "px", "em"
+ */
+@mixin flex($flex-grow: null, $flex-shrink: null, $flex-basis: null){
+ flex-grow: $flex-grow;
+ flex-shrink: $flex-shrink;
+ flex-basis: $flex-basis;
+}
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @ file contains @mixin functions for font-weight
+ * example: @include fontWeight(600); (OR) @include fontWeight(semi-bold);
+ */
+
+// @mixin for font weight
+@mixin fontWeight($weight){
+ $weights: (
+ thin: 100,
+ extra-light: 200,
+ light: 300,
+ regular: 400,
+ medium: 500,
+ semi-bold: 600,
+ bold: 700,
+ extra-bold: 800,
+ ultra-bold: 900
+ );
+
+ $output: $weight;
+ @if map-has-key($weights, $weight) {
+ $output: map-get($weights, $weight);
+ }
+
+ font-weight: $output;
+ }
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @ file contains @mixin functions for offset position
+ * @param {String} $position - Either `relative`, `absolute` or `fixed`
+ * @param {Length} $top [null] - Top offset
+ * @param {Length} $right [null] - Right offset
+ * @param {Length} $bottom [null] - Bottom offset
+ * @param {Length} $left [null] - Left offset
+ */
+
+@mixin position_value($position, $top: null, $right: null, $bottom: null, $left: null) {
+ position: $position;
+ top: $top;
+ right: $right;
+ bottom: $bottom;
+ left: $left;
+}
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @ file contains @mixin functions for font
+ * example: @include rem("font-size", 14);
+ */
+
+@mixin rem($property, $values...) {
+ $n: length($values);
+ $i: 1;
+ $pxlist: ();
+ $remlist: ();
+ @while $i <=$n {
+ $itemVal: (nth($values, $i));
+ @if $itemVal !="auto" {
+ $pxlist: append($pxlist, $itemVal + px);
+ $remlist: append($remlist, ($itemVal / 16) + rem);
+ }
+ @else {
+ $pxlist: append($pxlist, auto);
+ $remlist: append($remlist, auto);
+ }
+ $i: $i+1;
+ }
+ #{$property}: $pxlist;
+ #{$property}: $remlist;
+}
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @ file contains @mixin functions for border radius
+ * example: @include roundedCorners(10);
+ */
+
+// Rounded Corner has equal radius
+@mixin roundedCorners($size) {
+ border-radius: $size + px;
+}
+
+// Rounded Corner for percentage values
+@mixin roundedCornersPercentage($size) {
+ border-radius: $size;
+}
+
+// Rounded Corner for Top left/right
+@mixin roundedTop($size) {
+ border-radius: $size + px $size + px 0 0;
+}
+
+// Rounded Corner for Top Left alone
+@mixin roundedTopLeft($size) {
+ border-radius: $size + px 0 0 0;
+}
+
+// Rounded Corner for Top Right alone
+@mixin roundedTopRight($size) {
+ border-radius: 0 $size + px 0 0;
+}
+
+// Rounded Corner for Bottom left/right
+@mixin roundedBottom($size) {
+ border-radius: 0 0 $size + px $size + px;
+}
+
+// Rounded Corner for Bottom Left alone
+@mixin roundedBottomLeft($size) {
+ border-radius: 0 0 0 $size + px;
+}
+
+// Rounded Corner for Bottom Right alone
+@mixin roundedBottomRight($size) {
+ border-radius: 0 0 $size + px 0;
+}
+
+// Rounded Corner for Left Top/Bottom
+@mixin roundedLeft($size) {
+ border-radius: $size + px 0 0 $size + px;
+}
+
+// Rounded Corner for Right Top/Bottom
+@mixin roundedRight($size) {
+ border-radius: 0 $size + px $size + px 0;
+}
+
+// Shorthand for all four corners rounded equally
+@mixin circularCorners($size) {
+ border-radius: $size;
+}
+
+// Border bottom left radius
+@mixin roundedBottomLeftRadius($sive) {
+ border-bottom-left-radius: $sive + px;
+}
+
+// Border bottom right radius
+@mixin roundedBottomRightRadius($sive) {
+ border-bottom-right-radius: $sive + px;
+}
+
+// Border top left radius
+@mixin roundedTopLeftRadius($sive) {
+ border-top-left-radius: $sive + px;
+}
+
+// Border top right radius
+@mixin roundedTopRightRadius($sive) {
+ border-top-right-radius: $sive + px;
+}
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @ file contains @mixin functions for transform
+ */
+
+// @mixin for 3d transform
+@mixin transform_style($txsize, $tysize, $tzsize) {
+ transform: translate3d($txsize, $tysize, $tzsize);
+}
+
+// @mixin for rotate transform
+@mixin rotate($deg){
+ transform: rotate($deg+deg);
+ -webkit-transform: rotate($deg+deg);
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @ file contains @mixin functions for transition property
+ * example: @include transition(background, 1s, ease-in-out, 0);
+ */
+
+// @mixin for transition properties
+@mixin transition($property: null, $duration: null, $timing-function: null, $delay: null) {
+ transition-property: $property;
+ transition-duration: $duration;
+ transition-timing-function: $timing-function;
+ transition-delay: $delay;
+}
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/** All mixins are imported here */
+@import '_animation';
+@import '_background';
+@import '_border';
+@import '_box-shadow';
+@import '_custom';
+@import '_flex';
+@import '_font-weight';
+@import '_position';
+@import '_rem';
+@import '_rounded-corners';
+@import '_transform';
+@import '_transition';
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/*Roboto Fonts*/
+$roboto-font-path: "~roboto-fontface/fonts" !default;
+@import "~roboto-fontface/css/roboto/sass/roboto-fontface-regular";
+/*Custom mixin*/
+@import "mixins/mixin.scss";
+/*Theme setup color*/
+@import "variable";
+/*bootstrap styles*/
+@import "~bootstrap/scss/bootstrap";
+/*Custom theme styles*/
+@import "app.scss";
+/*Code Mirror styles*/
+@import "~codemirror/lib/codemirror";
+@import "~codemirror/addon/fold/foldgutter";
+@import "~codemirror/theme/neat";
+@import "~codemirror/theme/material";
+@import "~codemirror/addon/dialog/dialog";
+@import "~codemirror/addon/display/fullscreen";
+/*ng-select styles*/
+@import "~@ng-select/ng-select/themes/default.theme.css";
+/*Angular notifier styles*/
+@import "~angular-notifier/styles/core.scss";
+@import "~angular-notifier/styles/themes/theme-material.scss";
+@import "~angular-notifier/styles/themes/theme-material.scss";
+@import "~angular-notifier/styles/types/type-success.scss";
+@import "~angular-notifier/styles/types/type-error.scss";
+@import "~angular-notifier/styles/types/type-warning.scss";
+@import "~angular-notifier/styles/types/type-default.scss";
+@import "~angular-notifier/styles/types/type-info.scss";
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+// Custom Variables
+$themecolor: #2962ff;
+$theme-light: #fff;
+
+/*Topbar Colors*/
+
+$topbar: $theme-light;
+$topbar-height: 64px;
+$topbar-navlink-padding: 0px 15px;
+$topbar-navlink-font-size: 0.875rem;
+$topbar-navlink-height: 64px;
+$topbar-navbrand-padding: 0 10px 0 10px;
+/*Sidebar Colors*/
+
+$sidebar: $theme-light;
+$sidebar-text: #fff;
+$sidebar-icons: #fff;
+$sidebar-width-full: 100px;
+$sidebar-width-mini: 65px;
+/*Boxed layout width*/
+
+$boxed-width: 1200px;
+/*Shadow*/
+
+$shadow: 1px 0px 20px rgba(0, 0, 0, 0.08);
+/*transitions*/
+
+$transitions: 0.2s ease-in;
+/*Dark transparent bg*/
+
+$transparent-dark-bg: rgba(0, 0, 0, 0.05);
+$lft: left;
+$rgt: right;
+$card-alt: #e4e9ef;
+%square {
+ border-radius: 0px;
+}
+
+%rotate45 {
+ transform: rotate(45deg);
+ -ms-transform: rotate(45deg);
+ -webkit-transform: rotate(45deg);
+ -o-transform: rotate(45deg);
+ -moz-transform: rotate(45deg);
+}
+
+/*******************************/
+
+// Bootstrap overrides
+/*******************************/
+
+/**
+ * Table Of Content
+ *
+ * 1. Color system
+ * 2. Options
+ * 3. Body
+ * 4. Typography
+ * 5. Breadcrumbs
+ * 6. Cards
+ * 7. Dropdowns
+ * 8. Buttons
+ * 9. Typography
+ * 10. Progress bars
+ * 11. Tables
+ * 12. Forms
+ * 14. Component
+ */
+
+//
+// Color system
+//
+$primary: #054c8c;
+$secondary: #065fac;
+$theme-bg-color: #eef5f9;
+$breadcrumb-after-color: #002a6a;
+
+$white: #fff !default;
+$gray-100: #f6fafe !default;
+$gray-200: #e9ecef !default;
+$gray-300: #dee2e6 !default;
+$gray-400: #ced4da !default;
+$gray-500: #afb5c1 !default;
+$gray-600: #6c757d !default;
+$gray-700: #4f5467 !default;
+$gray-800: #343a40 !default;
+$gray-900: #212529 !default;
+$gray-80: #cccccc !default;
+$gray-97: #f7f7f7 !default;
+$medium-pink: #fb6ca4 !default;
+$black-coral: #5a5c69 !default;
+$cerise-pink: #e4397c !default;
+$pure-red: #ff0000 !default;
+$denim: #1467b3 !default;
+$black: #000 !default;
+$blue: #137eff !default;
+$dark-gray: #aaaaaa;
+$indigo: #6610f2 !default;
+$purple: #8b5edd !default;
+$pink: #e83e8c !default;
+$red: #dd4b39 !default;
+$orange: #fb8c00 !default;
+$yellow: #f39c12 !default;
+$green: #00a65a !default;
+$teal: #20c997 !default;
+$cyan: #4fc3f7 !default;
+$grayish-red: #c1bfbf !default;
+$white-smoke: #f1f1f1 !default;
+$text-muted: $gray-500 !default;
+$colors: (
+ blue: $blue,
+ indigo: $indigo,
+ purple: $purple,
+ pink: $pink,
+ red: $red,
+ orange: $orange,
+ yellow: $yellow,
+ green: $green,
+ teal: $teal,
+ cyan: $cyan,
+ white: $white,
+ gray: $gray-600,
+ gray-dark: $gray-800
+);
+$primary: $blue !default;
+$secondary: $gray-400 !default;
+$success: $green !default;
+$info: $blue !default;
+$warning: $yellow !default;
+$danger: $red !default;
+$light: $gray-100 !default;
+$dark: $gray-800 !default;
+$cyan: $cyan !default;
+$orange: $orange !default;
+$theme-colors: () !default;
+$theme-colors: map-merge(
+ (
+ "primary": $primary,
+ "secondary": $secondary,
+ "success": $success,
+ "info": $info,
+ "warning": $warning,
+ "danger": $danger,
+ "light": $light,
+ "dark": $dark,
+ "cyan": $cyan,
+ "orange": $orange,
+ "purple": $purple
+ ),
+ $theme-colors
+);
+$modalheader-gray: #f8f9fa;
+//
+// Quickly modify global styling by enabling or disabling optional features.
+$enable-caret: true !default;
+$enable-rounded: true !default;
+$enable-shadows: false !default;
+$enable-gradients: false !default;
+$enable-transitions: true !default;
+$enable-hover-media-query: false !default;
+$enable-grid-classes: true !default;
+$enable-print-styles: true !default;
+// Body
+//
+// Settings for the element.
+$main-body-bg: #fff !default;
+$body-bg: #f2f4f5;
+$body-color: #6a7a8c !default;
+$grid-gutter-width: 20px !default;
+// Typography
+//
+// Font, line-height, and color for body text, headings, and more.
+$font-size-base: 0.875rem;
+$font-family-open-sans: "Open Sans";
+$font-weight-light: 300 !default;
+$font-weight-normal: 400 !default;
+$font-weight-medium: 500 !default;
+$font-weight-bold: 700 !default;
+$h1-font-size: 36px !default;
+$h2-font-size: 30px !default;
+$h3-font-size: 24px !default;
+$h4-font-size: 18px !default;
+$h5-font-size: 16px !default;
+$h6-font-size: 14px !default;
+$headings-margin-bottom: (1rem / 2) !default;
+$headings-font-weight: 400 !default;
+$headings-color: inherit !default;
+// Breadcrumbs
+$breadcrumb-bg: $body-bg;
+$breadcrumb-margin-bottom: 1.5rem;
+// Cards
+$card-border-width: 0px !default;
+$card-border-color: transparent !default;
+$card-border-radius: 0px !default;
+// Dropdowns
+$dropdown-item-padding-x: 1rem !default;
+$dropdown-item-padding-y: 0.65rem !default;
+$dropdown-border-color: $gray-200;
+$dropdown-divider-bg: $gray-100;
+// Buttons
+$btn-secondary-border: $gray-300;
+// Progress bars
+$progress-bg: $gray-100;
+// Tables
+$table-bg-accent: $gray-100;
+$table-bg-hover: $gray-100;
+$table-hover-bg: $gray-100 !default;
+$table-cell-padding: 1rem !default;
+$table-bg-level: -10 !default;
+$table-bg-level2: 1 !default;
+$table-bg-level3: -5 !default;
+// Components
+$component-active-color: $white !default;
+$component-active-bg: $themecolor !default;
+$badge-pill-padding-x: 0.2em !default;
+$badge-pill-padding-y: 1em !default;
+// Forms
+$input-group-addon-bg: $gray-100;
+$input-border-color: $gray-200;
+$input-group-addon-border-color: $gray-200;
+$input-btn-focus-color: rgba(0, 0, 0, 0.25) !default;
+$input-focus-border-color: rgba(0, 0, 0, 0.25) !default;
+$custom-control-indicator-active-bg: rgba(0, 0, 0, 35%) !default;
+$input-btn-focus-box-shadow: transparent !default;
+$custom-select-focus-box-shadow: transparent !default;
+$custom-select-border-width: 1px !default;
+//
+// Define common padding and border radius sizes and more.
+$border-width: 1px !default;
+$border-color: rgba(0, 0, 0, 0.1) !default;
+$border-radius: 2px !default;
+$border-radius-lg: 2px !default;
+$border-radius-sm: 1px !default;
+// Progress bars
+$progress-height: 5px !default;
+//Tabs
+$nav-tabs-link-active-bg: $white !default;
+// Grid breakpoints
+//
+// Define the minimum dimensions at which your layout will change,
+// adapting to different screen sizes, for use in media queries.
+$grid-breakpoints: (
+ xs: 0,
+ sm: 576px,
+ md: 768px,
+ lg: 992px,
+ xl: 1600px
+) !default;
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+
+/**
+ * @file Directive for go to top button.
+ */
+import { Directive, HostListener } from '@angular/core';
+import { SharedService } from 'SharedService';
+
+/**
+ * Creating Directive for handling go to top button
+ * @Directive appGottoTop selector
+ */
+@Directive({
+ selector: '[appGottoTop]'
+})
+/** Exporting a class @exports GoToTopDirective */
+export class GoToTopDirective {
+ /** To set scroll top position @private */
+ private topPosToStartShowing: number = 100;
+
+ /** Contains all methods related to shared @private */
+ private sharedService: SharedService;
+
+ constructor(sharedService: SharedService) {
+ this.sharedService = sharedService;
+ }
+ /**
+ * to listen the scroll event in DOM @public
+ */
+ @HostListener('window:scroll') public enableGotoTop(): void {
+ const scrollPosition: number = Math.max(window.pageYOffset, document.documentElement.scrollTop, document.body.scrollTop);
+ if (scrollPosition >= this.topPosToStartShowing) {
+ this.sharedService.showGotoTop = true;
+ } else {
+ this.sharedService.showGotoTop = false;
+ }
+ }
+
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @file environment variables
+ * This file can be replaced during build by using the `fileReplacements` array.
+ * `npm run build` replaces `environment.ts` with `environment.prod.ts`.
+ * The list of file replacements can be found in `angular.json`.
+ */
+
+import { version } from 'PACKAGEJSON';
+
+/** OSM_Admin URL @constant */
+const OSM_ADMIN_ENDPOINT: string = 'osm/admin/v1/';
+/** OSM_NS LCM URL @constant */
+const OSM_NSLCM_ENDPOINT: string = 'osm/nslcm/v1/';
+/** OSM_NST URL @constant */
+const OSM_NST_ENDPOINT: string = 'osm/nst/v1/';
+/** OSM_NSI LCM URL @constant */
+const OSM_NSILCM_ENDPOINT: string = 'osm/nsilcm/v1/';
+/** OSM_VNFD PACKAGES URL @constant */
+const OSM_VNFDPACKAGE_ENDPOINT: string = 'osm/vnfpkgm/v1/';
+/** OSM_PDU URL @constant */
+const OSM_PDU_ENDPOINT: string = 'osm/pdu/v1/';
+/** OSM_NSD URL @constant */
+const OSM_NSD_ENDPOINT: string = 'osm/nsd/v1/';
+/** Assets root path @constant */
+const ASSETS_PATH: string = 'assets/';
+/** OSM Version @constant */
+const OSM_VERSION: string = 'osm/version';
+/** Grafana End-Point @constant */
+// tslint:disable-next-line: no-http-string
+const GRAFANA_ENDPOINT: string = 'http://' + window.location.hostname + ':3000';
+
+/** Exporting a const @exports environment */
+// tslint:disable-next-line: typedef
+export const environment = {
+ production: true,
+ packageSize: 15,
+ paginationNumber: 10, //Possible values are 10, 25, 50, 100
+ packageVersion: version,
+ // tslint:disable-next-line: no-http-string
+ MAPLATLONGAPI_URL: 'http://photon.komoot.de/api/?q={value}&limit=5',
+ GENERATETOKEN_URL: OSM_ADMIN_ENDPOINT + 'tokens',
+ PROJECTS_URL: OSM_ADMIN_ENDPOINT + 'projects',
+ USERS_URL: OSM_ADMIN_ENDPOINT + 'users',
+ ROLES_URL: OSM_ADMIN_ENDPOINT + 'roles',
+ VIMACCOUNTS_URL: OSM_ADMIN_ENDPOINT + 'vim_accounts',
+ WIMACCOUNTS_URL: OSM_ADMIN_ENDPOINT + 'wim_accounts',
+ SDNCONTROLLER_URL: OSM_ADMIN_ENDPOINT + 'sdns',
+ K8SCLUSTER_URL: OSM_ADMIN_ENDPOINT + 'k8sclusters',
+ K8REPOS_URL: OSM_ADMIN_ENDPOINT + 'k8srepos',
+ NETWORKSLICETEMPLATE_URL: OSM_NST_ENDPOINT + 'netslice_templates',
+ NETWORKSLICETEMPLATECONTENT_URL: OSM_NST_ENDPOINT + 'netslice_templates_content',
+ NSDINSTANCES_URL: OSM_NSLCM_ENDPOINT + 'ns_instances',
+ VNFINSTANCES_URL: OSM_NSLCM_ENDPOINT + 'vnfrs',
+ NSINSTANCESCONTENT_URL: OSM_NSLCM_ENDPOINT + 'ns_instances_content',
+ NSHISTORYOPERATIONS_URL: OSM_NSLCM_ENDPOINT + 'ns_lcm_op_occs',
+ NETWORKSLICEINSTANCESCONTENT_URL: OSM_NSILCM_ENDPOINT + 'netslice_instances_content',
+ NSTHISTORYOPERATIONS_URL: OSM_NSILCM_ENDPOINT + '/nsi_lcm_op_occs',
+ NSDESCRIPTORSCONTENT_URL: OSM_NSD_ENDPOINT + 'ns_descriptors_content',
+ NSDESCRIPTORS_URL: OSM_NSD_ENDPOINT + 'ns_descriptors',
+ VNFPACKAGESCONTENT_URL: OSM_VNFDPACKAGE_ENDPOINT + 'vnf_packages_content',
+ VNFPACKAGES_URL: OSM_VNFDPACKAGE_ENDPOINT + 'vnf_packages',
+ PDUINSTANCE_URL: OSM_PDU_ENDPOINT + 'pdu_descriptors',
+ PERMISSIONS_CONFIG_FILE: ASSETS_PATH + 'config/rolePermissions.json',
+ GRAFANA_URL: GRAFANA_ENDPOINT + '/d',
+ DOMAIN_URL: OSM_ADMIN_ENDPOINT + 'domains',
+ OSM_VERSION_URL: OSM_VERSION
+};
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @file environment variables
+ * This file can be replaced during build by using the `fileReplacements` array.
+ * `npm run build` replaces `environment.ts` with `environment.prod.ts`.
+ * The list of file replacements can be found in `angular.json`.
+ */
+
+import { version } from 'PACKAGEJSON';
+
+/** OSM Admin URL @constant */
+const OSM_ADMIN_ENDPOINT: string = 'osm/admin/v1/';
+/** OSM NS LCM URL @constant */
+const OSM_NSLCM_ENDPOINT: string = 'osm/nslcm/v1/';
+/** OSM NST URL @constant */
+const OSM_NST_ENDPOINT: string = 'osm/nst/v1/';
+/** OSM NSI LCM URL @constant */
+const OSM_NSILCM_ENDPOINT: string = 'osm/nsilcm/v1/';
+/** OSM VNFD PACKAGES URL @constant */
+const OSM_VNFDPACKAGE_ENDPOINT: string = 'osm/vnfpkgm/v1/';
+/** OSM PDU URL @constant */
+const OSM_PDU_ENDPOINT: string = 'osm/pdu/v1/';
+/** OSM NSD URL @constant */
+const OSM_NSD_ENDPOINT: string = 'osm/nsd/v1/';
+/** Assets root path @constant */
+const ASSETS_PATH: string = 'assets/';
+/** OSM Version @constant */
+const OSM_VERSION: string = 'osm/version';
+/** Grafana End-Point @constant */
+// tslint:disable-next-line: no-http-string
+const GRAFANA_ENDPOINT: string = 'http://' + window.location.hostname + ':3000';
+
+/** Exporting a const @exports environment */
+// tslint:disable-next-line: typedef
+export const environment = {
+ production: false,
+ packageSize: 15,
+ paginationNumber: 10, //Possible values are 10, 25, 50, 100
+ packageVersion: version,
+ // tslint:disable-next-line: no-http-string
+ MAPLATLONGAPI_URL: 'http://photon.komoot.de/api/?q={value}&limit=5',
+ GENERATETOKEN_URL: OSM_ADMIN_ENDPOINT + 'tokens',
+ PROJECTS_URL: OSM_ADMIN_ENDPOINT + 'projects',
+ USERS_URL: OSM_ADMIN_ENDPOINT + 'users',
+ ROLES_URL: OSM_ADMIN_ENDPOINT + 'roles',
+ VIMACCOUNTS_URL: OSM_ADMIN_ENDPOINT + 'vim_accounts',
+ WIMACCOUNTS_URL: OSM_ADMIN_ENDPOINT + 'wim_accounts',
+ SDNCONTROLLER_URL: OSM_ADMIN_ENDPOINT + 'sdns',
+ K8SCLUSTER_URL: OSM_ADMIN_ENDPOINT + 'k8sclusters',
+ K8REPOS_URL: OSM_ADMIN_ENDPOINT + 'k8srepos',
+ NETWORKSLICETEMPLATE_URL: OSM_NST_ENDPOINT + 'netslice_templates',
+ NETWORKSLICETEMPLATECONTENT_URL: OSM_NST_ENDPOINT + 'netslice_templates_content',
+ NSDINSTANCES_URL: OSM_NSLCM_ENDPOINT + 'ns_instances',
+ VNFINSTANCES_URL: OSM_NSLCM_ENDPOINT + 'vnfrs',
+ NSINSTANCESCONTENT_URL: OSM_NSLCM_ENDPOINT + 'ns_instances_content',
+ NSHISTORYOPERATIONS_URL: OSM_NSLCM_ENDPOINT + 'ns_lcm_op_occs',
+ NETWORKSLICEINSTANCESCONTENT_URL: OSM_NSILCM_ENDPOINT + 'netslice_instances_content',
+ NSTHISTORYOPERATIONS_URL: OSM_NSILCM_ENDPOINT + 'nsi_lcm_op_occs',
+ NSDESCRIPTORSCONTENT_URL: OSM_NSD_ENDPOINT + 'ns_descriptors_content',
+ NSDESCRIPTORS_URL: OSM_NSD_ENDPOINT + 'ns_descriptors',
+ VNFPACKAGESCONTENT_URL: OSM_VNFDPACKAGE_ENDPOINT + 'vnf_packages_content',
+ VNFPACKAGES_URL: OSM_VNFDPACKAGE_ENDPOINT + 'vnf_packages',
+ PDUINSTANCE_URL: OSM_PDU_ENDPOINT + 'pdu_descriptors',
+ PERMISSIONS_CONFIG_FILE: ASSETS_PATH + 'config/rolePermissions.json',
+ GRAFANA_URL: GRAFANA_ENDPOINT + '/d',
+ DOMAIN_URL: OSM_ADMIN_ENDPOINT + 'domains',
+ OSM_VERSION_URL: OSM_VERSION
+};
--- /dev/null
+<!--
+Copyright 2020 TATA ELXSI
+
+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.
+
+Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+-->
+<!doctype html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <title>OSM</title>
+ <base href="/">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <!-- <meta http-equiv="Content-Security-Policy"
+ content="base-uri 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline' fonts.googleapis.com cdnjs.cloudflare.com;media-src 'self';form-action 'self';child-src 'none';"> -->
+ <link rel="icon" type="image/x-icon" href="favicon.ico">
+</head>
+
+<body>
+ <app-root></app-root>
+</body>
+
+</html>
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+// Karma configuration file, see link for more information
+// https://karma-runner.github.io/1.0/config/configuration-file.html
+
+module.exports = function (config) {
+ config.set({
+ basePath: '',
+ frameworks: ['jasmine', '@angular-devkit/build-angular'],
+ plugins: [
+ require('karma-jasmine'),
+ require('karma-chrome-launcher'),
+ require('karma-jasmine-html-reporter'),
+ require('karma-coverage-istanbul-reporter'),
+ require('@angular-devkit/build-angular/plugins/karma')
+ ],
+ client: {
+ clearContext: false // leave Jasmine Spec Runner output visible in browser
+ },
+ coverageIstanbulReporter: {
+ dir: require('path').join(__dirname, '../coverage/osm'),
+ reports: ['html', 'lcovonly', 'text-summary'],
+ fixWebpackSourcePaths: true
+ },
+ reporters: ['progress', 'kjhtml'],
+ port: 9876,
+ colors: true,
+ logLevel: config.LOG_INFO,
+ autoWatch: true,
+ browsers: ['Chrome'],
+ singleRun: false
+ });
+};
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @file Main for the application.
+ */
+import { enableProdMode } from '@angular/core';
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+
+import { AppModule } from './app/AppModule';
+import { environment } from './environments/environment';
+
+if (environment.production) {
+ enableProdMode();
+}
+
+platformBrowserDynamic().bootstrapModule(AppModule)
+ .catch((err: Error): void => { console.error(err); });
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+import { HttpHeaders } from '@angular/common/http';
+
+/**
+ * @file Model for Commonly used information.
+ */
+/**
+ * handle count @enum
+ */
+export enum CONSTANTNUMBER {
+ randomNumber = 4,
+ osmapviewlong = 77.673,
+ osmapviewlat = 19.166,
+ chennailong = 80.2809,
+ chennailat = 13.0781,
+ bangalorelong = 77.5868,
+ bangalorelat = 12.9718,
+ mumbailong = 72.8342,
+ mumbailat = 18.9394,
+ tirvandrumlong = 76.9544,
+ tirvandrumlat = 8.5009,
+ oneMB = 1048576,
+ paginationDefaultValue = 10,
+ splitLongitude = 1,
+ splitLatitude = 2
+}
+/**
+ * handle count @enum
+ */
+export enum CONFIGCONSTANT {
+ operationalStateFirstStep = 'init',
+ operationalStateSecondStep = 'running',
+ operationalStateThirdStep = 'failed',
+ configStateFirstStep = 'init',
+ configStateSecondStep = 'configured',
+ configStateThirdStep = 'failed',
+ historyStateFirstStep = 'PROCESSING',
+ historyStateSecondStep = 'COMPLETED',
+ historyStateThirdStep = 'FAILED',
+ wimOperationalStateFirstStep = 'PROCESSING',
+ wimOperationalStateStateSecondStep = 'ENABLED',
+ wimOperationalStateThirdStep = 'ERROR',
+ vimOperationalStateFirstStep = 'PROCESSING',
+ vimOperationalStateStateSecondStep = 'ENABLED',
+ vimOperationalStateThirdStep = 'ERROR',
+ sdnOperationalStateFirstStep = 'PROCESSING',
+ sdnOperationalStateStateSecondStep = 'ENABLED',
+ sdnOperationalStateThirdStep = 'ERROR',
+ k8OperationalStateFirstStep = 'PROCESSING',
+ k8OperationalStateStateSecondStep = 'ENABLED',
+ k8OperationalStateThirdStep = 'ERROR'
+}
+/** Interface for Post options */
+export interface POSTAPIRESOURCE {
+ apiURLHeader: APIURLHEADER;
+ payload?: object;
+}
+/** Interface for ApiURL Header */
+export interface APIURLHEADER {
+ url: string;
+ httpOptions?: APIHEADERS;
+}
+/** Interface for the Get Method with response type */
+export interface GETAPIURLHEADER {
+ headers: HttpHeaders;
+ responseType: string;
+}
+/** Interface for Httpoptions Header */
+interface APIHEADERS {
+ headers: HttpHeaders;
+}
+/** Interface for the Error */
+export interface ERRORDATA {
+ error: ERRORDETAILSDATA;
+}
+/** Interface for the Error Details */
+interface ERRORDETAILSDATA {
+ detail: string;
+ code?: string;
+ status?: number;
+ text?: Function;
+}
+/** Handle the URL params */
+export interface URLPARAMS {
+ page: string;
+ id: string;
+ titleName?: string;
+ forceDeleteType?: boolean;
+ name?: string;
+ memberIndex?: object;
+ nsConfig?: object;
+ projectID?: string;
+ username?: string;
+}
+/** Handle the Delete params */
+export interface DELETEPARAMS {
+ identifier: string;
+ name?: string;
+ shortName: string;
+ projectName?: string;
+ userName?: string;
+ username?: string;
+ page?: string;
+ id?: string;
+}
+
+/** Interface for the Delete Details */
+export interface MODALCLOSERESPONSEDATA {
+ message: string;
+}
+
+/** Interface for the modal closer */
+export interface MODALCLOSERESPONSEWITHCP {
+ message: string;
+ connection_point?: string;
+}
+
+/** Interface for local storage settings */
+export interface LOCALSTORAGE {
+ id_token?: string;
+ project_id?: string;
+ expires?: string;
+ username?: string;
+ project?: string;
+ project_name?: string;
+ id?: string;
+ admin?: boolean;
+ isAdmin?: string;
+ token_state?: string;
+}
+/** Interface for Tar settings */
+export interface TARSETTINGS {
+ name?: string;
+ 'type'?: string;
+ readAsString?: Function;
+ buffer: ArrayBuffer;
+}
+/** Interface for Package information */
+export interface PACKAGEINFO {
+ id?: string;
+ packageType?: string;
+ descriptor: string;
+}
+
+/** Interface For the Pagination pager in ng-smarttable */
+export interface PAGERSMARTTABLE {
+ display: boolean;
+ perPage: number;
+}
+/** Interface for breadcrumb item */
+export interface BREADCRUMBITEM {
+ title: string;
+ url: string;
+}
+/** Interface For the Pagination pager in ng-smarttable */
+export interface SMARTTABLECLASS {
+ // tslint:disable-next-line: no-reserved-keywords
+ class: string;
+}
+/** Constants of the VIM Types */
+export const VIM_TYPES: TYPESECTION[] = [
+ { value: 'openstack', title: 'Openstack' },
+ { value: 'aws', title: 'AWS' },
+ { value: 'vmware', title: 'VMware vCD' },
+ { value: 'openvim', title: 'OpenVIM' },
+ { value: 'opennebula', title: 'OpenNebula' },
+ { value: 'azure', title: 'Azure' }
+];
+/** Constants of the SDN Types */
+export const SDN_TYPES: TYPESECTION[] = [
+ { value: 'arista', title: 'Arista' },
+ { value: 'floodlightof', title: 'Floodlight openflow' },
+ { value: 'odlof', title: 'OpenDaylight openflow' },
+ { value: 'onosof', title: 'ONOS openflow' },
+ { value: 'onos_vpls', title: 'ONOS vpls' }
+];
+/** Constants of the WIM Types */
+export const WIM_TYPES: TYPESECTION[] = [
+ { value: 'arista', title: 'Arista' },
+ { value: 'dynpac', title: 'DynPac' },
+ { value: 'floodlightof', title: 'Floodlight openflow' },
+ { value: 'odlof', title: 'OpenDaylight openflow' },
+ { value: 'onosof', title: 'ONOS openflow' },
+ { value: 'onos_vpls', title: 'ONOS vpls' },
+ { value: 'tapi', title: 'TAPI' }
+];
+/** Interface for List, Add WIM & SDN Types */
+export interface TYPESECTION {
+ value: string;
+ title: string;
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @file Model for K8s related information.
+ */
+
+/** Interface for K8SCLUSTERDATA */
+export interface K8SCLUSTERDATA {
+ credentials: Credentials;
+ description: string;
+ k8s_version: number;
+ name: string;
+ namespace: string;
+ nets: Nets;
+ schema_version: string;
+ vim_account: string;
+ _admin: Admin;
+ _id: string;
+}
+/** Interface for K8SCLUSTERDATA */
+export interface K8SREPODATA {
+ description: string;
+ name: string;
+ schema_version: string;
+ 'type': string;
+ url: string;
+ vim_account: string;
+ _admin: Admin;
+ _id: string;
+}
+/** Interface for the Credentials */
+interface Credentials{
+ apiVersion: string;
+ clusters: Clusters[];
+ contexts: Contexts[];
+ 'current-context': string;
+ kind: string;
+ preferences: {};
+ users: Users[];
+}
+/** Interface for the Clusters */
+interface Clusters {
+ cluster: Cluster;
+ name: string;
+}
+/** Interface for the Cluster */
+interface Cluster {
+ 'certificate-authority-data': string;
+ server: string;
+}
+/** Interface for the Contexts */
+interface Contexts{
+ context: Context;
+ name: string;
+}
+/** Interface for the Contexts */
+interface Context {
+ cluster: string;
+ user: string;
+}
+/** Interface for the Users */
+interface Users{
+ name: string;
+ user: User;
+}
+/** Interface for the Users */
+interface User {
+ 'client-certificate-data': string;
+ 'client-key-data': string;
+}
+/** Interface for the K8SCLUSTERDATA nets */
+interface Nets{
+ net1: string;
+}
+/** Interface for the K8SCLUSTERDATA _admin */
+interface Admin{
+ created: string;
+ current_operation: number;
+ 'helm-chart': HelmChart;
+ 'juju-bundle': JujuBundle;
+ operationalState: string;
+ modified: string;
+}
+/** Interface for the K8SCLUSTERDATA _admin Helm chart */
+interface HelmChart {
+ created: boolean;
+ id: string;
+}
+/** Interface for the K8SCLUSTERDATA _admin Juju Bundle */
+interface JujuBundle {
+ error_msg: string;
+}
+/** Interface for the K8SCLUSTERDATA Return to Display */
+export interface K8SCLUSTERDATADISPLAY{
+ name: string;
+ identifier: string;
+ operationalState: string;
+ version: number;
+ created: string;
+ modified: string;
+ pageType: string;
+}
+/** Interface for the K8SCLUSTERDATA Return to Display */
+export interface K8SREPODATADISPLAY {
+ name: string;
+ identifier: string;
+ url: string;
+ 'type': string;
+ created: string;
+ modified: string;
+ pageType: string;
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @file Model for Commonly used information.
+ */
+/** Constants of the Menu child active class */
+const childActiveClass: string[] = ['active'];
+/** Constants of the Menu Items */
+export const MENU_ITEMS: MENUITEMS[] = [
+ {
+ liClass: 'round-edge-top-3',
+ anchorTagClass: 'link round-edge-top-3 individual',
+ clickFunction: 'nosubmenu',
+ routerLink: '/',
+ routerLinkActive: ['parentactive'],
+ routerLinkActiveOptions: true,
+ icon: 'fas fa-th-large',
+ menuName: 'PAGE.DASHBOARD.DASHBOARD',
+ isChildExists: false
+ },
+ {
+ liClass: 'header-menu',
+ anchorTagClass: 'heading text-uppercase',
+ menuName: 'PROJECT',
+ isChildExists: false
+ },
+ {
+ liClass: 'round-edge-top-3',
+ anchorTagClass: 'parentlink round-edge-top-3 mr-top-5',
+ clickFunction: 'packages',
+ routerLink: '/packages',
+ routerLinkActive: ['menu-open', 'parentactive'],
+ routerLinkActiveOptions: false,
+ icon: 'fas fa-box',
+ menuName: 'PACKAGES',
+ isChildExists: true,
+ ulClass: 'sidebar-submenu',
+ childItems: [
+ {
+ liClass: '',
+ anchorTagClass: 'link',
+ routerLink: '/packages/ns',
+ routerLinkActive: childActiveClass,
+ routerLinkActiveOptions: false,
+ icon: 'fas fa-box-open',
+ menuName: 'NSPACKAGES',
+ isChildExists: false
+ },
+ {
+ liClass: '',
+ anchorTagClass: 'link',
+ routerLink: '/packages/vnf',
+ routerLinkActive: childActiveClass,
+ routerLinkActiveOptions: false,
+ icon: 'fas fa-box-open',
+ menuName: 'VNFPACKAGES',
+ isChildExists: false
+ },
+ {
+ liClass: '',
+ anchorTagClass: 'link',
+ routerLink: '/packages/netslice',
+ routerLinkActive: childActiveClass,
+ routerLinkActiveOptions: false,
+ icon: 'fas fa-layer-group',
+ menuName: 'PAGE.DASHBOARD.NETSLICETEMPLATE',
+ isChildExists: false
+ }
+ ]
+ },
+ {
+ liClass: 'mt-1 round-edge-bottom-3 border-bottom-none',
+ anchorTagClass: 'parentlink round-edge-bottom-3 border-bottom-none',
+ clickFunction: 'instances',
+ routerLink: '/instances',
+ routerLinkActive: ['menu-open', 'parentactive'],
+ routerLinkActiveOptions: false,
+ icon: 'fa fa-paper-plane',
+ menuName: 'INSTANCES',
+ isChildExists: true,
+ ulClass: 'sidebar-submenu',
+ childItems: [
+ {
+ liClass: '',
+ anchorTagClass: 'link',
+ routerLink: '/instances/ns',
+ routerLinkActive: childActiveClass,
+ routerLinkActiveOptions: false,
+ icon: 'fas fa-sitemap',
+ menuName: 'NSINSTANCES',
+ isChildExists: false
+ },
+ {
+ liClass: '',
+ anchorTagClass: 'link',
+ routerLink: '/instances/vnf',
+ routerLinkActive: childActiveClass,
+ routerLinkActiveOptions: false,
+ icon: 'fas fa-hdd',
+ menuName: 'VNFINSTANCES',
+ isChildExists: false
+ },
+ {
+ liClass: '',
+ anchorTagClass: 'link',
+ routerLink: '/instances/pdu',
+ routerLinkActive: childActiveClass,
+ routerLinkActiveOptions: false,
+ icon: 'fas fa-hdd',
+ menuName: 'PDUINSTANCES',
+ isChildExists: false
+ },
+ {
+ liClass: '',
+ anchorTagClass: 'link',
+ routerLink: '/instances/netslice',
+ routerLinkActive: childActiveClass,
+ routerLinkActiveOptions: false,
+ icon: 'fas fa-layer-group',
+ menuName: 'PAGE.DASHBOARD.NETSLICEINSTANCE',
+ isChildExists: false
+ }
+ ]
+ },
+ {
+ liClass: 'round-edge-top-3 round-edge-bottom-3 mr-top-5',
+ anchorTagClass: 'link round-edge-top-3 round-edge-bottom-3 individual',
+ clickFunction: 'nosubmenu',
+ routerLink: '/sdn/details',
+ routerLinkActive: ['parentactive'],
+ routerLinkActiveOptions: true,
+ icon: 'fas fa-globe',
+ menuName: 'SDNCONTROLLER',
+ isChildExists: false
+ },
+ {
+ liClass: 'round-edge-top-3 round-edge-bottom-3 mr-top-5',
+ anchorTagClass: 'link round-edge-top-3 round-edge-bottom-3 individual',
+ clickFunction: 'nosubmenu',
+ routerLink: '/vim',
+ routerLinkActive: ['parentactive'],
+ routerLinkActiveOptions: false,
+ icon: 'fas fa-server',
+ menuName: 'VIMACCOUNTS',
+ isChildExists: false
+ },
+ {
+ liClass: 'round-edge-top-3 round-edge-bottom-3 mr-top-5',
+ anchorTagClass: 'parentlink round-edge-top-3 round-edge-bottom-3',
+ clickFunction: 'k8s',
+ routerLink: '/k8s',
+ routerLinkActive: ['menu-open', 'parentactive'],
+ routerLinkActiveOptions: false,
+ icon: 'fas fa-asterisk',
+ menuName: 'PAGE.K8S.MENUK8S',
+ isChildExists: true,
+ ulClass: 'sidebar-submenu',
+ childItems: [
+ {
+ liClass: '',
+ anchorTagClass: 'link',
+ routerLink: '/k8s/cluster',
+ routerLinkActive: childActiveClass,
+ routerLinkActiveOptions: false,
+ icon: 'fas fa-project-diagram',
+ menuName: 'PAGE.K8S.MENUK8SCLUSTER',
+ isChildExists: false
+ },
+ {
+ liClass: '',
+ anchorTagClass: 'link',
+ routerLink: '/k8s/repo',
+ routerLinkActive: childActiveClass,
+ routerLinkActiveOptions: false,
+ icon: 'fas fa-flag',
+ menuName: 'PAGE.K8S.MENUK8SREPO',
+ isChildExists: false
+ }
+ ]
+ },
+ {
+ liClass: 'round-edge-top-3 round-edge-bottom-3 mr-top-5',
+ anchorTagClass: 'link round-edge-top-3 round-edge-bottom-3 individual',
+ clickFunction: 'nosubmenu',
+ routerLink: '/wim/details',
+ routerLinkActive: ['parentactive'],
+ routerLinkActiveOptions: true,
+ icon: 'fas fa-sitemap',
+ menuName: 'WIMACCOUNTS',
+ isChildExists: false
+ },
+ {
+ liClass: 'header-menu',
+ anchorTagClass: 'heading text-uppercase',
+ menuName: 'ADMIN',
+ isChildExists: false
+ },
+ {
+ liClass: 'mt-1 round-edge-top-3',
+ anchorTagClass: 'link round-edge-top-3 individual',
+ clickFunction: 'nosubmenu',
+ routerLink: '/projects',
+ routerLinkActive: ['parentactive'],
+ routerLinkActiveOptions: true,
+ icon: 'fas fa-folder',
+ menuName: 'PAGE.DASHBOARD.PROJECTS',
+ isChildExists: false
+ },
+ {
+ liClass: 'mt-1 mb-1',
+ anchorTagClass: 'link individual',
+ clickFunction: 'nosubmenu',
+ routerLink: '/users/details',
+ routerLinkActive: ['parentactive'],
+ routerLinkActiveOptions: true,
+ icon: 'fas fa-users',
+ menuName: 'PAGE.DASHBOARD.USERS',
+ isChildExists: false
+ },
+ {
+ liClass: 'round-edge-bottom-3',
+ anchorTagClass: 'link round-edge-bottom-3 individual',
+ clickFunction: 'nosubmenu',
+ routerLink: '/roles',
+ routerLinkActive: ['parentactive'],
+ routerLinkActiveOptions: true,
+ icon: 'fas fa-user-tag',
+ menuName: 'ROLES',
+ isChildExists: false
+ }
+];
+
+/** Interface for Post options */
+export interface MENUITEMS {
+ ulClass?: string;
+ liClass: string;
+ anchorTagClass: string;
+ clickFunction?: string;
+ routerLink?: string;
+ routerLinkActive?: string[];
+ routerLinkActiveOptions?: boolean;
+ icon?: string;
+ menuName: string;
+ isChildExists: boolean;
+ childItems?: MENUITEMS[];
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @file Model for NSD related information.
+ */
+
+import { VNFDAdminDetails } from './VNFDModel';
+
+/** Interface for NSData */
+export interface NSData {
+ shortName: string;
+ identifier: string;
+ description: string;
+ vendor: string;
+ version: string;
+ page?: string;
+ name?: string;
+ projectName?: string;
+ userName?: string;
+ username?: string;
+}
+
+/** Interface for the nscompose descriptors content */
+export interface NSDDetails {
+ 'connection-point': CONNECTIONPOINT[];
+ 'constituent-vnfd': CONSTITUENTVNFD[];
+ description: string;
+ id: string;
+ logo: string;
+ name: string;
+ 'short-name': string;
+ vendor: string;
+ version: string;
+ vld: VLD[];
+ _admin: VNFDAdminDetails;
+ _id: string;
+ 'constituent-vnfr-ref': string[];
+}
+
+/** Interface for the connection-point */
+export interface CONNECTIONPOINT {
+ name: string;
+ 'vld-id-ref': string;
+}
+
+/** Interface for the constituent-vnfd */
+export interface CONSTITUENTVNFD {
+ 'member-vnf-index': number;
+ 'vnfd-id-ref': string;
+}
+
+/** Interface for the vld */
+export interface VLD {
+ id: string;
+ 'mgmt-network': boolean;
+ name: string;
+ 'short-name'?: string;
+ 'type': string;
+ 'vnfd-connection-point-ref'?: VNFDCONNECTIONPOINTREF[];
+ 'vim-network-name': string;
+}
+
+/** Interface for VNFDCONNECTIONPOINTREF */
+export interface VNFDCONNECTIONPOINTREF {
+ 'member-vnf-index-ref': number;
+ 'vnfd-connection-point-ref': string;
+ 'vnfd-id-ref': string;
+}
+/** Interface Nodes Creation */
+export interface COMPOSERNODES {
+ id: string;
+ reflexive: Boolean;
+ 'type': string;
+ name?: string;
+ nodeIndex?: number;
+ selectorId?: string;
+ x?: number;
+ y?: number;
+ fx?: number;
+ fy?: number;
+}
+
+/** Interface for the Tick */
+export interface Tick {
+ target: TickPath;
+ source: TickPath;
+ left: boolean;
+ right: boolean;
+}
+
+/** Interface for the Path */
+export interface TickPath {
+ x: number;
+ y: number;
+ id: string;
+ 'type'?: string;
+}
+
+/** Interface for the NSD */
+interface NSD {
+ 'constituent-vnfd': CONSTITUENTVNFD[];
+ description: string;
+ id: string;
+ name: string;
+ 'short-name': string;
+ vendor: string;
+ version: string;
+ vld: VLD[];
+ _admin: VNFDAdminDetails;
+ _id: string;
+}
+/** Interface for the GRAPHDETAILS */
+export interface GRAPHDETAILS {
+ width: number;
+ height: number;
+ nodeHeight: number;
+ nodeWidth: number;
+ textX: number;
+ textY: number;
+ radius: number;
+ distance: number;
+ strength: number;
+ forcex: number;
+ forcey: number;
+ sourcePaddingYes: number;
+ sourcePaddingNo: number;
+ targetPaddingYes: number;
+ targetPaddingNo: number;
+ alphaTarget: number;
+ imageX: number;
+ imageY: number;
+ shiftKeyCode: number;
+}
+
+/** Interface for the NS Create params */
+export interface NSCREATEPARAMS {
+ nsName: string;
+ nsDescription: string;
+ nsdId: string;
+ vimAccountId: string;
+ vld: string;
+ ssh_keys: string[];
+}
+
+/** Interface for the NSI Create params */
+export interface NSICREATEPARAMS {
+ nsName: string;
+ nsDescription: string;
+ nstId: string;
+ vimAccountId: string;
+ 'netslice-vld': string;
+ ssh_keys: string[];
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @file Model for NS Instance related information.
+ */
+
+import { CONSTITUENTVNFD, VLD, VNFDCONNECTIONPOINTREF } from 'NSDModel';
+import { VNFDAdminDetails } from 'VNFDModel';
+
+/** Interface for NSInstanceDetails */
+export interface NSInstanceDetails {
+ 'orchestration-progress': JSON;
+ 'constituent-vnfr-ref': string[];
+ 'operational-events': string[];
+ admin: Admin;
+ 'ssh-authorized-key': string;
+ _admin: _Admin;
+ 'admin-status': string;
+ 'operational-status': string;
+ 'datacenter': string;
+ nsd: NSD;
+ name: string;
+ 'name-ref': string;
+ 'short-name': string;
+ id: string;
+ 'nsd-name-ref': string;
+ description: string;
+ 'detailed-status': string;
+ 'config-status': string;
+ 'resource-orchestrator': string;
+ 'nsd-ref': string;
+ vld: VLD[];
+ instantiate_params: InstantiateParam;
+ additionalParamsForNs: AdditionalParamForN;
+ _id?: string;
+}
+
+/** Interface for Admin */
+interface Admin {
+ deployed: DeployedAdmin;
+}
+
+/** Interface for DeployedAdmin */
+interface DeployedAdmin {
+ RO: ROAdmin;
+}
+
+/** Interface for ROAdmin */
+interface ROAdmin {
+ 'nsr_status': string;
+}
+
+/** Interface for _Admin */
+// tslint:disable-next-line:class-name
+interface _Admin {
+ 'projects_write': string[];
+ deployed: DeployedAdmin;
+ nslcmop: string;
+ nsState: string;
+ modified: number;
+ projects_read: string[];
+ created: string;
+}
+
+/** Interface for Deployed_Admin */
+interface DeployedAdmin {
+ VCA: string[];
+ RO: ROAdmin;
+}
+
+/** Interface for RO_Admin */
+interface ROAdmin {
+ 'nsr_status': string;
+ 'nsr_id': string;
+ 'nsd_id': string;
+ vnfd: VNFD[];
+}
+
+/** Interface for VNFD */
+interface VNFD {
+ 'member-vnf-index': number;
+ id: string;
+}
+
+/** Interface for NSD */
+export interface NSD {
+ description: string;
+ vld: NSDVLD[];
+ _admin: VNFDAdminDetails;
+ name: string;
+ version: string;
+ _id: string;
+ 'short-name': string;
+ id: string;
+ 'constituent-vnfd': CONSTITUENTVNFD[];
+ vendor: string;
+ vdur: string[];
+ 'connection-point': CONNECTIONPOINT[];
+}
+
+/** Interface for _AdminDetails */
+// tslint:disable-next-line:class-name
+export interface _AdminDetails {
+ usageState: string;
+ projects_write: string[];
+ projects_read: string[];
+ operationalState: string;
+ modified: string;
+ storage: Storage;
+ onboardingState: string;
+ userDefinedData: JSON;
+ created: number;
+}
+
+/** Interface for Storage */
+interface Storage {
+ path: string;
+ 'pkg-dir': string;
+ zipfile: string;
+ folder: string;
+ descriptor: string;
+ fs: string;
+}
+
+/** Interface for NSDVLD */
+export interface NSDVLD {
+ 'vim-id': string;
+ 'status-detailed': string;
+ name: string;
+ status: string;
+ 'vim-network-name': string;
+ id: string;
+ 'type': string;
+ 'vnfd-connection-point-ref': VNFDCONNECTIONPOINTREF[];
+ 'short-name': string;
+}
+
+/** Interface for InstantiateParam */
+interface InstantiateParam {
+ nsdId: string;
+ nsName: string;
+ nsDescription: string;
+ vimAccountId: string;
+}
+
+/** Interface for AdditionalParamForN */
+interface AdditionalParamForN {
+ _id: string;
+ 'ns-instance-config-ref': string;
+ 'crete-time': string;
+}
+
+/** interface for the History nsdInstanceData */
+export interface NSDInstanceData {
+ id?: string;
+ lcmOperationType?: string;
+ operationState?: string;
+ startTime?: number;
+ statusEnteredTime?: number;
+ identifier: string;
+ name: string;
+ NsdName: string;
+ OperationalStatus: string;
+ ConfigStatus: string;
+ DetailedStatus: string;
+ state?: string;
+ memberIndex?: object;
+ nsConfig?: object;
+}
+
+/** Interface for the nsInfo */
+export interface NSINFO {
+ nsInstanceID: string;
+ nsName: string;
+ nsOperationalStatus: string;
+ nsConfigStatus: string;
+ nsDetailedStatus: string;
+ nsResourceOrchestrator: string;
+}
+
+/** Interface for the NSINSTANCENODES */
+export interface NSINSTANCENODES {
+ id?: string;
+ nodeTypeRef?: string;
+ name?: string;
+ 'type'?: string;
+ vnfdCP?: VNFDCONNECTIONPOINTREF[];
+ vimNetworkName?: string;
+ shortName?: string;
+ cp?: CONNECTIONPOINT[];
+ vdur?: string[];
+ vld?: NSDVLD[];
+ nsID?: string;
+ vnfdID?: string;
+ vimID?: string;
+ vndfrID?: string;
+ ipAddress?: string;
+ memberIndex?: string;
+ vnfdRef?: string;
+ vndfCPRef?: string;
+ selectorId?: string;
+}
+
+/** Interface for the connection-point */
+export interface CONNECTIONPOINT {
+ 'connection-point-id': string;
+ name: string;
+ id: string;
+}
+
+/** Interface for Exec NS Primitive */
+export interface NSPrimitive {
+ 'primitive': string;
+ 'primitive_params': NSPrimitiveParams[];
+ 'member_vnf_index': string;
+}
+
+/** Interface for Exec NS Primitive Params */
+export interface NSPrimitiveParams {
+ primitive_params_name: string;
+ primitive_params_value: string;
+}
+
+/** Interface Nodes Creation */
+export interface COMPOSERNODES {
+ id: string;
+ reflexive: Boolean;
+ nodeTypeRef: string;
+ name?: string;
+ nodeIndex?: number;
+ selectorId?: string;
+ x?: number;
+ y?: number;
+ fx?: number;
+ fy?: number;
+ shortName?: string;
+ vimNetworkName?: string;
+ 'type'?: string;
+ vnfdRef?: string;
+ memberIndex?: string;
+ vimID?: string;
+ vndfrID?: string;
+ ipAddress?: string;
+ nsID?: string;
+ vnfdID?: string;
+}
+
+/** Interface for the Virtual Link Info */
+export interface VLINFO {
+ id: string;
+ name: string;
+ 'type': string;
+ shortName: string;
+ vimNetworkName: string;
+}
+
+/** Interface for the VNFR Info */
+export interface VNFRINFO{
+ vimID: string;
+ _id: string;
+ ip: string;
+ nsrID: string;
+ id: string;
+ vnfdRef: string;
+ vnfdId: string;
+ memberIndex: string;
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @file Model for NS topology related information.
+ */
+
+/** Interface for the GRAPHDETAILS */
+export interface GRAPHDETAILS {
+ width: number;
+ height: number;
+ nodeHeight: number;
+ nodeWidth: number;
+ textX: number;
+ textY: number;
+ radius: number;
+ distance: number;
+ strength: number;
+ forcex: number;
+ forcey: number;
+ sourcePaddingYes: number;
+ sourcePaddingNo: number;
+ targetPaddingYes: number;
+ targetPaddingNo: number;
+ alphaTarget: number;
+ imageX: number;
+ imageY: number;
+ shiftKeyCode: number;
+}
+/** Interface for the Path */
+export interface TickPath {
+ x: number;
+ y: number;
+ id: string;
+ 'type'?: string;
+}
+/** Interface for the Tick */
+export interface Tick {
+ target: TickPath;
+ source: TickPath;
+ left: boolean;
+ right: boolean;
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @file Model for Network Slice Template related information.
+ */
+
+/** Interface for MetricModel */
+export interface NetworkSliceModel {
+ 'netslice-subnet': NetsliceSubnet[];
+ id: string;
+ 'SNSSAI-identifier': SNSSAIIdentifier;
+ 'quality-of-service': QualityOfService;
+ name: string;
+ _id: string;
+ _admin: ADMIN;
+ 'netslice-vld': NetsliceVld[];
+}
+
+/** Interface for NetsliceSubnet */
+interface NetsliceSubnet {
+ description : string;
+ id: string;
+ 'is-shared-nss': string;
+ 'nsd-ref': string;
+}
+
+/** Interface for SNSSAIIdentifier */
+interface SNSSAIIdentifier {
+ 'slice-service-type': string;
+}
+
+/** Interface for SNSSAIIdentifier */
+interface QualityOfService {
+ id: number;
+}
+
+/** Interface for Admin */
+interface ADMIN {
+ operationalState: string;
+ created: string;
+ projects_write: string[];
+ projects_read: string[];
+ usageState: string;
+ modified: string;
+ onboardingState: string;
+ userDefinedData: {};
+ storage : Storage;
+}
+
+/** Interface for Storage */
+interface Storage {
+ fs: string;
+ folder: string;
+ descriptor: string;
+ path: string;
+}
+
+/** Interface for NetsliceVld */
+interface NetsliceVld {
+ name: string;
+ id: string;
+ 'nss-connection-point-ref': NssConnectionPointRef[];
+ 'mgmt-network': boolean;
+ // tslint:disable-next-line:no-reserved-keywords
+ type: string;
+}
+
+/** Interface for NssConnectionPointRef */
+interface NssConnectionPointRef {
+ 'nss-ref': string;
+ 'nsd-connection-point-ref': string;
+}
+
+/** Interface for NetworkSliceData */
+export interface NetworkSliceData {
+ name: string;
+ identifier: string;
+ usageState: string;
+}
+
+/** Interface for Network Slice instance Data */
+export interface NSTInstanceDetails {
+ name: string;
+ id: string;
+ 'nst-ref': string;
+ 'operational-status': string;
+ 'config-status': string;
+ 'detailed-status': string;
+}
+/** interface for the Network Slice instance Data in datasource Table */
+export interface NSTInstanceData {
+ name: string;
+ identifier: string;
+ NstName: string;
+ OperationalStatus: string;
+ ConfigStatus: string;
+ DetailedStatus: string;
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @file Model for PDU Instance related information.
+ */
+
+/** Interface for PDUInstanceDetails */
+export interface PDUInstanceDetails {
+ description: string;
+ interfaces: PDUInterfaces[];
+ name: string;
+ 'type': string;
+ vim_accounts: string[];
+ _admin: ADMIN;
+ _id: string;
+ identifier?: string;
+}
+
+/** Interface for PDU interfaces */
+export interface PDUInterfaces {
+ 'ip-address': string;
+ mgmt: boolean;
+ name: string;
+ 'vim-network-name': string;
+}
+
+/** Interface for Admin */
+interface ADMIN {
+ created: string;
+ modified: string;
+ onboardingState: string;
+ operationalState: string;
+ projects_write: string[];
+ projects_read: string[];
+ usageState: string;
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @file Model for project related information.
+ */
+
+/** Interface for ProjectDetails */
+export interface ProjectDetails {
+ _admin?: Admin;
+ _id?: string;
+ name?: string;
+ id?: string;
+}
+
+/** Interface for Admin */
+interface Admin {
+ created: number;
+ modified: number;
+ projects_read?: string[];
+}
+/** Interface for ProjectDetails in smarttable */
+export interface ProjectData {
+ projectName: string;
+ modificationDate: string;
+ creationDate: string;
+ page?: string;
+ id?: string;
+ project?: string;
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @file Model for role related information.
+ */
+
+/** Interface for ProjectDetails */
+export interface RoleDetails {
+ _admin?: Admin;
+ _id?: string;
+ name?: string;
+ id?: string;
+ permissions?: {};
+}
+
+/** Interface for Admin */
+interface Admin {
+ created: number;
+ modified: number;
+}
+/** Interface for Role data in smarttable */
+export interface RoleData {
+ name: string;
+ identifier: string;
+ modified: string;
+ created: string;
+ permissions: {};
+}
+/** Interface for Role configuration from role config file */
+export interface RoleConfig {
+ rolePermissions: PermissionGroup[];
+}
+/** Interface for Role permission group */
+export interface PermissionGroup {
+ title: string;
+ permissions: Permission[];
+}
+/** Interface for Role permission group */
+export interface Permission {
+ operation: string;
+ value: string | boolean;
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @file Model For SDN Controller model Information.
+ */
+
+/** Interface for SDNControllerModel */
+export interface SDNControllerModel {
+ dpid: string;
+ ip: string;
+ name: string;
+ password: string;
+ port: string;
+ schema_version: string;
+ 'type': string;
+ user: string;
+ version: string;
+ _admin: ADMIN;
+ _id: string;
+}
+
+/** Interface for _ADMIN */
+interface ADMIN {
+ created: number;
+ current_operation: boolean;
+ deployed: Deployed;
+ 'detailed-status': string;
+ modified: number;
+ operationalState: string;
+ operations: Operation[];
+ projects_read: string[];
+ projects_write: string[];
+}
+
+/** Interface for Deployed */
+interface Deployed {
+ RO: string;
+}
+
+/** Interface for Operations */
+interface Operation {
+ 'detailed-status': string;
+ lcmOperationType: string;
+ operationParams: string;
+ operationState: string;
+ startTime: number;
+ statusEnteredTime: number;
+ worker: string;
+}
+
+/** Interface for SDNControllerList */
+export interface SDNControllerList {
+ name: string;
+ id?: string;
+ identifier: string;
+ 'type': string;
+ operationalState: string;
+ ip: string;
+ port: string;
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+
+/**
+ * @file Model for user related information.
+ */
+
+/** Interface for UserDetails */
+export interface UserDetails {
+ userDetail: UserDetail[];
+}
+
+/** Interface for UserDetail */
+export interface UserDetail {
+ username: string;
+ password?: string;
+ _id?: string;
+ projects: string[];
+ _admin?: Admin;
+ modified: string;
+ created: string;
+ identifier: string;
+ projectListName?: string;
+ project_role_mappings?: ProjectRoleMappings[];
+}
+
+/** Interface for user role mappings */
+export interface UserRoleMap {
+ project_role_mappings?: ProjectRoleMappings[];
+}
+
+/** Interface for Admin */
+interface Admin {
+ salt: string;
+ created: number;
+ modified: number;
+}
+/** Interface for UserDetail */
+export interface UserData {
+ username: string;
+ projects: string;
+ modified: string;
+ created: string;
+ identifier: string;
+}
+
+/** Interface for Project Roles Mappings */
+export interface ProjectRoleMappings {
+ project?: string;
+ project_name?: string;
+ role?: string;
+ role_name?: string;
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @file Model for VNFD related information.
+ */
+
+/** Interface for Project */
+export interface ProjectModel {
+ project_id: string;
+ project?: string;
+ project_name?: string;
+ expires: number;
+ _id: string;
+ id: string;
+ issued_at: number;
+ remote_port: number;
+ username: string;
+ remote_host: string;
+ admin: boolean;
+}
+
+/** Interface for ProjectDetails */
+export interface ProjectDetails {
+ _admin: AdminDetails;
+ name: string;
+ _id: string;
+}
+
+/** Interface for AdminDetails */
+interface AdminDetails {
+ modified: string;
+ created: string;
+}
+
+/** Interface for VNFD NODE Details */
+export interface VNFDNODE {
+ nodeTypeRef?: string;
+ 'connection-point'?: CONNECTIONPOINT[];
+ description?: string;
+ id: string;
+ 'internal-vld'?: InternalVLD[];
+ version?: string;
+ name?: string;
+ 'mgmt-interface'?: MGMT;
+ _id?: string;
+ vdu?: VDU[];
+ _admin?: VNFDAdminDetails;
+ 'short-name'?: string;
+ shortName?: string;
+ vendor?: string;
+ 'type'?: string;
+ 'cloud-init-file'?: string;
+ count?: number;
+ vduID?: string;
+ 'interface'?: VNFDInterface[];
+ 'vm-flavor'?: VMFlavor;
+ intVLID?: string;
+ 'internal-connection-point'?: VLDInternalConnectionPoint[];
+ 'monitoring-param'?: MonitoringParam[];
+ 'ip-profile-ref'?: string;
+ 'id-ref'?: string;
+ 'ip-address'?: string;
+ reflexive?: boolean;
+ image?: string;
+}
+
+/** Interface for VNFDDetails */
+export interface VNFDDetails {
+ 'connection-point': CONNECTIONPOINT[];
+ description: string;
+ id: string;
+ 'internal-vld': InternalVLD[];
+ version: string;
+ name: string;
+ 'mgmt-interface': MGMT;
+ _id: string;
+ vdu: VDU[];
+ _admin: VNFDAdminDetails;
+ 'short-name': string;
+ vendor: string;
+}
+
+/** Interface for MGMT */
+interface MGMT {
+ cp: string;
+}
+
+/** Interface for VDU */
+export interface VDU {
+ nodeTypeRef?: string;
+ 'cloud-init-file'?: string;
+ count?: number;
+ description?: string;
+ id?: string;
+ image?: string;
+ 'interface'?: VNFDInterface[];
+ 'internal-connection-point'?: VDUInternalConnectionPoint[];
+ name?: string;
+ 'vm-flavor'?: VMFlavor;
+ vduInterface?: string;
+ 'monitoring-param'?: MonitoringParam[];
+}
+
+/** Interface for VMFlavor */
+interface VMFlavor {
+ 'storage-gb'?: string;
+ 'memory-mb'?: string;
+ 'vcpu-count'?: string;
+}
+
+/** Interface for VNFDInterface */
+export interface VNFDInterface {
+ 'external-connection-point-ref'?: string;
+ 'internal-connection-point-ref'?: string;
+ 'mgmt-interface'?: boolean;
+ name?: string;
+ 'type'?: string;
+ position?: boolean;
+ 'virtual-interface'?: VirtualInterface;
+}
+
+/** Interface for VDU Internal Connection Point */
+export interface VDUInternalConnectionPoint {
+ id: string;
+ name?: string;
+ 'short-name'?: string;
+ 'type'?: string;
+}
+
+/** Interface for VirutalInterface */
+interface VirtualInterface {
+ 'type': string;
+}
+
+/** Interface for the connection-point */
+export interface CONNECTIONPOINT {
+ nodeTypeRef?: string;
+ 'connection-point-id'?: string;
+ name?: string;
+ id: string;
+ 'type'?: string;
+}
+
+/** Interface for Internal VLD */
+export interface InternalVLD {
+ nodeTypeRef?: string;
+ id?: string;
+ 'internal-connection-point'?: VLDInternalConnectionPoint[];
+ 'ip-profile-ref'?: string;
+ name?: string;
+ 'short-name'?: string;
+ 'type'?: string;
+ 'shortName'?: string;
+ 'ipProfileRef'?: string;
+}
+
+/** Interface for VLD Internal Connection Point */
+export interface VLDInternalConnectionPoint {
+ nodeTypeRef?: string;
+ 'ip-address'?: string;
+ 'id-ref'?: string;
+ 'shortName'?: string;
+}
+
+/** Interface for monitoring params */
+export interface MonitoringParam {
+ id: string;
+ 'nfvi-metric'?: string;
+ 'interface-name-ref'?: string;
+}
+
+/** Interface for _AdminDetails */
+// tslint:disable-next-line:class-name
+export interface VNFDAdminDetails {
+ created: number;
+ modified: string;
+ onboardingState: string;
+ operationalState: string;
+ projects_read: string[];
+ projects_write: string[];
+ storage: Storage;
+ 'type': string;
+ usageState: string;
+ userDefinedData: JSON;
+}
+
+/** Interface for Storage */
+interface Storage {
+ descriptor: string;
+ folder: string;
+ fs: string;
+ path: string;
+ 'pkg-dir': string;
+ zipfile: string;
+}
+
+/** Interface for VNFData */
+export interface VNFData {
+ name?: string;
+ id?: string;
+ shortName: string;
+ identifier: string;
+ description: string;
+ vendor: string;
+ version: string;
+ 'type'?: string;
+}
+
+/** Interface for the Tick */
+export interface Tick {
+ target: TickPath;
+ source: TickPath;
+ left: boolean;
+ right: boolean;
+}
+
+/** Interface for the Path */
+export interface TickPath {
+ x: number;
+ y: number;
+ id: string;
+ 'type'?: string;
+}
+
+/** Interface Nodes Creation */
+export interface COMPOSERNODES {
+ id: string;
+ reflexive?: boolean;
+ 'type'?: string;
+ name?: string;
+ nodeTypeRef?: string;
+ x?: number;
+ y?: number;
+ fx?: number;
+ fy?: number;
+}
+
+/** Interface for the GRAPHDETAILS */
+export interface GRAPHDETAILS {
+ width: number;
+ height: number;
+ nodeHeight: number;
+ nodeWidth: number;
+ textX: number;
+ textY: number;
+ radius: number;
+ distance: number;
+ strength: number;
+ forcex: number;
+ forcey: number;
+ sourcePaddingYes: number;
+ sourcePaddingNo: number;
+ targetPaddingYes: number;
+ targetPaddingNo: number;
+ alphaTarget: number;
+ imageX: number;
+ imageY: number;
+ shiftKeyCode: number;
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @file Model for VNF Instance related information.
+ */
+
+/** Interface for VNFInstanceDetails */
+export interface VNFInstanceDetails {
+ id: string;
+ 'ip-address': string;
+ 'vnfd-id': string;
+ 'created-time': string;
+ 'vim-account-id': string;
+ vdur: VDUR[];
+ 'vnfd-ref': string;
+ 'member-vnf-index-ref': string;
+ _id: string;
+ additionalParamsForVnf: string;
+ _admin: Admin;
+ 'connection-point': ConnectionPoint[];
+ 'nsr-id-ref': string;
+}
+
+/** Interface for VDUR */
+interface VDUR {
+ 'ip-address': string;
+ 'vim-id': string;
+ 'internal-connection-point': string[];
+ name: string;
+ 'vdu-id-ref': string;
+ 'status-detailed': string;
+ 'count-index': number;
+ interfaces: VDURInterface[];
+ _id: string;
+ status: string;
+}
+
+/** Interface for VDURInterface */
+interface VDURInterface {
+ 'mac-address': string;
+ name: string;
+ 'ns-vld-id': string;
+ 'mgmt-vnf': string;
+ 'ip-address': string;
+}
+
+/** Interface for _Admin */
+interface Admin {
+ created: number;
+ projects_read: string[];
+ modified: string;
+ projects_write: string[];
+}
+
+/** Interface for ConnectionPoint */
+interface ConnectionPoint {
+ id: string;
+ name: string;
+ 'connection-point-id': string;
+}
+/** interface for the History nsdInstanceData */
+export interface VNFInstanceData {
+ identifier: string;
+ VNFD?: string;
+ VNFID?: string;
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @file Model for VimAccount Details related information.
+ */
+
+import { NSInstanceDetails } from 'NSInstanceModel';
+
+/** Interface for VimAccountDetails */
+export interface VimAccountDetails {
+ description: string;
+ 'vim_tenant_name': string;
+ schema_version: string;
+ schema_type: string;
+ config: CONFIG;
+ _id: string;
+ vim_password: string;
+ _admin: ADMIN;
+ vim_url: string;
+ vim_user: string;
+ vim_type: string;
+ name: string;
+}
+
+/** Interface for _ADMIN */
+interface ADMIN {
+ projects_write: string[];
+ deployed: Deployed;
+ operationalState: string;
+ modified: string;
+ projects_read: string[];
+ 'detailed-status': string;
+ created: string;
+}
+
+/** Interface for Deployed */
+interface Deployed {
+ 'RO-account': string;
+ RO: string;
+}
+
+/** Interface for Config */
+export interface CONFIG {
+ sdn_controller?: string;
+ use_floating_ip?: string;
+ location?: string;
+ sdn_port_mapping?: string;
+ vim_network_name?: string;
+ security_groups?: string;
+ availabilityZone?: string;
+ region_name?: string;
+ insecure?: string;
+ use_existing_flavors?: string;
+ use_internal_endpoint?: string;
+ additional_conf?: string;
+ APIversion?: string;
+ project_domain_id?: string;
+ project_domain_name?: string;
+ user_domain_id?: string;
+ user_domain_name?: string;
+ keypair?: string;
+ dataplane_physical_net?: string;
+ microversion?: string;
+ vpc_cidr_block?: string;
+ flavor_info?: string;
+ orgname?: string;
+ vcenter_ip?: string;
+ vcenter_port?: string;
+ admin_username?: string;
+ vcenter_user?: string;
+ admin_password?: string;
+ vcenter_password?: string;
+ nsx_manager?: string;
+ vrops_site?: string;
+ nsx_user?: string;
+ vrops_user?: string;
+ nsx_password?: string;
+ vrops_password?: string;
+ subscription_id?: string;
+ resource_group?: string;
+ vnet_name?: string;
+ flavors_pattern?: string;
+}
+
+/** Interface for VIMData */
+export interface VIMData {
+ name?: string;
+ identifier: string;
+ 'type': string;
+ operationalState: string;
+ description: string;
+ page?: string;
+ instancesData?: NSInstanceDetails[];
+}
+/** Interface for VIMLOCATION */
+export interface VIMLOCATION {
+ features: FEATURES[];
+ 'type': string;
+}
+/** Interface for FEATURES */
+export interface FEATURES {
+ geometry: GEOMETRY;
+ 'type': string;
+ properties: PROPERTIES;
+}
+/** Interface for GEOMETRY */
+interface GEOMETRY {
+ coordinates: [];
+}
+/** Interface for PROPERTIES */
+interface PROPERTIES {
+ extent: [];
+ country: string;
+ name: string;
+ state: string;
+}
+/** Interface for the VIMLOCATIONDATA */
+export interface VIMLOCATIONDATA {
+ label: string;
+ value: string;
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @file Model For WIM Account Details Information.
+ */
+
+/** Interface for WIMAccountModel */
+export interface WIMAccountModel {
+ config: {};
+ description: string;
+ name: string;
+ password: string;
+ schema_version: string;
+ user: string;
+ wim_type: string;
+ wim_url: string;
+ _admin: ADMIN;
+ _id: string;
+}
+
+/** Interface for _ADMIN */
+interface ADMIN {
+ created: number;
+ current_operation: boolean;
+ deployed: Deployed;
+ 'detailed-status': string;
+ modified: number;
+ operationalState: string;
+ operations: Operation[];
+ projects_read: string[];
+ projects_write: string[];
+}
+
+/** Interface for Deployed */
+interface Deployed {
+ 'RO-account': string;
+ RO: string;
+}
+
+/** Interface for Operations */
+interface Operation {
+ 'detailed-status': string;
+ lcmOperationType: string;
+ operationParams: string;
+ operationState: string;
+ startTime: number;
+ statusEnteredTime: number;
+ worker: string;
+}
+
+/** Interface for WIMAccountData */
+export interface WIMAccountData {
+ name?: string;
+ identifier: string;
+ 'type': string;
+ operationalState: string;
+ description: string;
+ page?: string;
+}
+
+/** Interface for WIM Row Values */
+export interface WIMValue {
+ name: string;
+ identifier: string;
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * This file includes polyfills needed by Angular and is loaded before the app.
+ * You can add your own extra polyfills to this file.
+ *
+ * This file is divided into 2 sections:
+ * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
+ * 2. Application imports. Files imported after ZoneJS that should be loaded before your main
+ * file.
+ *
+ * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
+ * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
+ * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
+ *
+ * Learn more in https://angular.io/guide/browser-support
+ */
+
+/***************************************************************************************************
+ * Load `$localize` onto the global scope - used if i18n tags appear in Angular templates.
+ */
+import '@angular/localize/init';
+
+/***************************************************************************************************
+ * BROWSER POLYFILLS
+ */
+
+/** IE10 and IE11 requires the following for NgClass support on SVG elements */
+// import 'classlist.js'; // Run `npm install --save classlist.js`.
+
+/**
+ * Web Animations `@angular/platform-browser/animations`
+ * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
+ * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
+ */
+import 'web-animations-js'; // Run `npm install --save web-animations-js`.
+
+/**
+ * By default, zone.js will patch all possible macroTask and DomEvents
+ * user can disable parts of macroTask/DomEvents patch by setting following flags
+ * because those flags need to be set before `zone.js` being loaded, and webpack
+ * will put import in the top of bundle, so user need to create a separate file
+ * in this directory (for example: zone-flags.ts), and put the following flags
+ * into that file, and then add the following code before importing zone.js.
+ * import './zone-flags.ts';
+ *
+ * The flags allowed in zone-flags.ts are listed here.
+ *
+ * The following flags will work for all browsers.
+ *
+ * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
+ * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
+ * (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
+ *
+ * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
+ * with the following flag, it will bypass `zone.js` patch for IE/Edge
+ *
+ * (window as any).__Zone_enable_cross_context_check = true;
+ *
+ */
+
+/***************************************************************************************************
+ * Zone JS is required by default for Angular itself.
+ */
+import 'zone.js/dist/zone'; // Included with Angular CLI.
+
+/***************************************************************************************************
+ * APPLICATION IMPORTS
+ */
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+
+/**
+ * @file Auth gaurd
+ */
+import { Injectable } from '@angular/core';
+import { CanLoad, Route } from '@angular/router';
+import { Observable } from 'rxjs';
+
+/**
+ * An Injectable is a class adorned with the @Injectable decorator function.
+ * @Injectable takes a metadata object that tells Angular how to compile and run module code
+ */
+@Injectable()
+export class AcessGuardService implements CanLoad {
+ /**
+ * check if module can be loaded
+ */
+ public canLoad(route: Route): Observable<boolean> | Promise<boolean> | boolean {
+ // Need to get the Role and valid here for authorization
+ if (localStorage.getItem('role') === 'Admin') {
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+
+/**
+ * @file Auth gaurd
+ */
+import { Injectable } from '@angular/core';
+import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router';
+import { AuthenticationService } from 'AuthenticationService';
+import { Observable } from 'rxjs';
+import { map, take } from 'rxjs/operators';
+
+/**
+ * An Injectable is a class adorned with the @Injectable decorator function.
+ * @Injectable takes a metadata object that tells Angular how to compile and run module code
+ */
+@Injectable()
+export class AuthGuardService implements CanActivate {
+ /** Holds teh instance of AuthService class of type AuthService @private */
+ private router: Router;
+ /** Holds teh instance of Router class of type Router @private */
+ private authService: AuthenticationService;
+
+ constructor(router: Router, authService: AuthenticationService) {
+ this.router = router;
+ this.authService = authService;
+ }
+
+ /**
+ * Returns Observable<boolean> if authorized @public
+ */
+ public canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
+ return this.authService.isLoggedIn
+ .pipe(
+ take(1),
+ map((isLoggedIn: boolean) => {
+ if (!isLoggedIn) {
+ this.router.navigate(['/login']).catch(() => {
+ //TODO: Handle error notification
+ });
+ }
+ return true;
+ })
+ );
+ }
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+
+/**
+ * @file HttpInterceptor file
+ */
+import {
+ HttpErrorResponse, HttpHandler, HttpHeaderResponse, HttpInterceptor, HttpProgressEvent,
+ HttpRequest, HttpResponse, HttpSentEvent, HttpUserEvent
+} from '@angular/common/http';
+import { Injectable, Injector } from '@angular/core';
+import { TranslateService } from '@ngx-translate/core';
+import { NotifierService } from 'angular-notifier';
+import { AuthenticationService } from 'AuthenticationService';
+import * as HttpStatus from 'http-status-codes';
+import { Observable, throwError } from 'rxjs';
+import { catchError, retry } from 'rxjs/operators';
+
+/**
+ * An Injectable is a class adorned with the @Injectable decorator function.
+ * @Injectable takes a metadata object that tells Angular how to compile and run module code
+ */
+@Injectable()
+export class AuthInterceptorService implements HttpInterceptor {
+ /** Holds header options @private */
+ private clonedReq: HttpRequest<{}>;
+
+ /** To inject services @private */
+ private injector: Injector;
+
+ /** Notifier service to popup notification @private */
+ private notifierService: NotifierService;
+
+ /** Contains tranlsate instance @private */
+ private translateService: TranslateService;
+
+ /** Utilizes auth service for any auth operations @private */
+ private authService: AuthenticationService;
+
+ /** create the instance of the component */
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.notifierService = this.injector.get(NotifierService);
+ this.authService = this.injector.get(AuthenticationService);
+ this.translateService = this.injector.get(TranslateService);
+ }
+
+ /**
+ * intercept logic
+ * @param req
+ * @param next
+ */
+ public intercept(req: HttpRequest<{}>, next: HttpHandler): Observable<HttpSentEvent |
+ // tslint:disable-next-line:no-any
+ HttpHeaderResponse | HttpProgressEvent | HttpResponse<{}> | HttpUserEvent<any> | any> {
+ const idToken: string = localStorage.getItem('id_token');
+ const excludedUrl: string[] = ['osm/admin/v1/tokens', 'assets/i18n/', 'osm/version'];
+ if (excludedUrl.some((x: string): boolean => { return req.url.includes(x); })) { return next.handle(req); }
+ if (idToken.length > 0) {
+ this.setHeader(req, idToken);
+ return next.handle(this.clonedReq).pipe(
+ catchError((err: HttpErrorResponse) => {
+ this.errorRes(err, req, next);
+ return throwError(err);
+ })
+ );
+ } else {
+ //TODO: Handle error via notification service
+ }
+ }
+
+ /** Set header options @public */
+ // tslint:disable-next-line:no-any
+ public setHeader(req: HttpRequest<any>, idToken: string): void {
+ if (req.body !== null && req.body.byteLength !== null) {
+ this.clonedReq = req.clone({
+ setHeaders: { Authorization: 'Bearer ' + idToken, 'Cache-Control': 'no-cache', Pragma: 'no-cache' }
+ });
+ } else {
+ this.clonedReq = req.clone({
+ setHeaders: { Authorization: 'Bearer ' + idToken, 'Content-Type': 'charset=UTF-8',
+ 'Cache-Control': 'no-cache', Pragma: 'no-cache' }
+ });
+ }
+ }
+
+ /** Handles error response @public */
+ public errorRes(err: HttpErrorResponse, req: HttpRequest<{}>, next: HttpHandler): Observable<{}> {
+ if (err instanceof HttpErrorResponse) {
+ switch (err.status) {
+ case HttpStatus.UNAUTHORIZED || HttpStatus.FORBIDDEN:
+ this.handleError(err);
+ break;
+ default: return throwError(err);
+ }
+ } else { return throwError(err); }
+ }
+
+ /** Method to handle 401 & 403 error */
+ private handleError(err: HttpErrorResponse): void {
+ if (err.error.detail === 'Expired Token or Authorization HTTP header' ||
+ err.error.detail === 'Invalid Token or Authorization HTTP header') {
+ this.notifierService.hideAll();
+ this.authService.logoutResponse();
+ if (this.authService.handle401) {
+ this.notifierService.notify('error', this.translateService.instant('SESSIONEXPIRY'));
+ this.authService.handle401 = false;
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @file Auth service
+ */
+import { HttpHeaders } from '@angular/common/http';
+import { Injectable, Injector } from '@angular/core';
+import { Router } from '@angular/router';
+import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
+import { Idle } from '@ng-idle/core';
+import { APIURLHEADER, ERRORDATA } from 'CommonModel';
+import { environment } from 'environment';
+import { BehaviorSubject, Observable } from 'rxjs';
+import { map } from 'rxjs/operators';
+import { isNullOrUndefined } from 'util';
+import { ProjectModel } from '../models/VNFDModel';
+import { RestService } from './RestService';
+
+/**
+ * An Injectable is a class adorned with the @Injectable decorator function.
+ * @Injectable takes a metadata object that tells Angular how to compile and run module code
+ */
+@Injectable()
+export class AuthenticationService {
+ /**
+ * Get method for Observable loggedIn
+ */
+ get isLoggedIn(): Observable<boolean> {
+ return this.loggedIn.asObservable();
+ }
+
+ /**
+ * Get method for Observable Username
+ */
+ get username(): Observable<string> {
+ return this.userName.asObservable();
+ }
+
+ /** Get method for project name */
+ get ProjectName(): Observable<string> {
+ return this.projectName$.asObservable();
+ }
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** Instance for modal service @public */
+ public modalService: NgbModal;
+
+ /** Handle 401 response for multiple API calls */
+ public handle401: boolean = true;
+
+ /** contains return URL link @public */
+ public returnUrl: string;
+
+ /** Holds the username in condition of type BehaviorSubject<string> @public */
+ public userName: BehaviorSubject<string> = new BehaviorSubject<string>('');
+
+ /** Holds the projectname in condition of type BehaviorSubject<string> @public */
+ public projectName$: BehaviorSubject<string> = new BehaviorSubject<string>('');
+
+ /** Holds the instance of router class @private */
+ private router: Router;
+
+ /** Holds the logged in condition of type BehaviorSubject<boolean> @private */
+ private loggedIn: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
+
+ /** Hold Rest Service Objects */
+ private restService: RestService;
+
+ /** Holds auth payloads @private */
+ private payLoad: {};
+
+ /** Holds header options for auth service @private */
+ private httpOptions: HttpHeaders;
+
+ /** handle idle time out service @private */
+ private idle: Idle;
+
+ /** create the instance of the component */
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.router = this.injector.get(Router);
+ this.restService = this.injector.get(RestService);
+ this.modalService = this.injector.get(NgbModal);
+ this.idle = this.injector.get(Idle);
+ if (localStorage.getItem('id_token') !== null) {
+ this.loggedIn.next(true);
+ } else {
+ this.loggedIn.next(false);
+ }
+ this.userName.next(localStorage.getItem('username'));
+ }
+
+ /**
+ * Send request and authenticate the user
+ * @param user of type User
+ */
+ public login(username: string, password: string): Observable<{}> {
+ this.setHeader();
+ this.setPayLoad(username, password);
+ const apiURLHeader: APIURLHEADER = {
+ url: environment.GENERATETOKEN_URL,
+ httpOptions: { headers: this.httpOptions }
+ };
+ return this.restService.postResource(apiURLHeader, this.payLoad)
+ .pipe(map((data: ProjectModel) => {
+ if (data) {
+ this.setLocalStorage(data);
+ this.idle.watch(true);
+ this.loggedIn.next(true);
+ this.handle401 = true;
+ this.userName.next(data.username);
+ return this.loggedIn;
+ }
+ }, (error: ERRORDATA) => { this.restService.handleError(error, 'post'); }
+ ));
+ }
+
+ /** Set headers for auth session @public */
+ public setHeader(): void {
+ this.httpOptions = new HttpHeaders({
+ 'Content-Type': 'application/json; charset=UTF-8',
+ Accept: 'application/json',
+ 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
+ });
+ }
+
+ /** Set payloads for auth session @public */
+ public setPayLoad(username: string, password: string): void {
+ this.payLoad = JSON.stringify({
+ username,
+ password
+ });
+ }
+
+ /** set local storage on auth process @public */
+ public setLocalStorage(data: ProjectModel): void {
+ localStorage.setItem('id_token', data.id);
+ localStorage.setItem('expires', data.expires.toString());
+ localStorage.setItem('username', data.username);
+ localStorage.setItem('isAdmin', (data.admin) ? 'true' : 'false');
+ localStorage.setItem('project_id', data.project_id);
+ localStorage.setItem('project', data.project_name);
+ localStorage.setItem('token_state', data.id);
+ this.projectName$.next(data.project_name);
+ }
+ /** Destory tokens API response handling @public */
+ public logoutResponse(): void {
+ this.loggedIn.next(false);
+ const langCode: string = localStorage.getItem('languageCode');
+ const redirecturl: string = isNullOrUndefined(localStorage.getItem('returnUrl')) ? '/' : localStorage.getItem('returnUrl');
+ localStorage.clear();
+ localStorage.setItem('languageCode', langCode);
+ localStorage.setItem('returnUrl', redirecturl);
+ localStorage.setItem('token_state', null);
+ this.idle.stop();
+ this.router.navigate(['login']).catch();
+ }
+ /**
+ * Logout the user & clearing the token.
+ */
+ public logout(): void {
+ this.returnUrl = this.router.url;
+ localStorage.setItem('returnUrl', this.returnUrl);
+ this.modalService.dismissAll();
+ this.destoryToken();
+ }
+ /** Destory tokens on logout @private */
+ private destoryToken(): void {
+ const tokenID: string = localStorage.getItem('id_token');
+ if (tokenID !== null) {
+ const deletingURl: string = environment.GENERATETOKEN_URL + '/' + tokenID;
+ this.restService.deleteResource(deletingURl).subscribe((res: {}) => {
+ this.logoutResponse();
+ }, (error: ERRORDATA) => {
+ this.restService.handleError(error, 'delete');
+ });
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+
+/**
+ * @file Data Services for user related information.
+ */
+import { Injectable } from '@angular/core';
+import { BehaviorSubject, Observable } from 'rxjs';
+
+/**
+ * This file created during the angular project creation
+ */
+@Injectable()
+/** Exporting a class @exports DataService */
+export class DataService {
+ /** message source @public */
+ public messageSource: BehaviorSubject<{}> = new BehaviorSubject<{}>({});
+
+ /** current message @public */
+ public currentMessage: Observable<{}> = this.messageSource.asObservable();
+ /** change message function @public */
+ public changeMessage(message: {}): void {
+ this.messageSource.next(message);
+ }
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+import { Injectable } from '@angular/core';
+import { BehaviorSubject, Observable } from 'rxjs';
+/**
+ * @file Provider for Device Check Service
+ */
+/**
+ * An Injectable is a class adorned with the @Injectable decorator function.
+ * @Injectable takes a metadata object that tells Angular how to compile and run module code
+ */
+@Injectable({
+ providedIn: 'root'
+})
+/** Exporting a class @exports DeviceCheckService */
+export class DeviceCheckService {
+ /** Get method for Observable isMobile */
+ get isMobile(): Observable<boolean> {
+ return this.isMobile$.asObservable();
+ }
+ /** Holds the mobile condition of type BehaviorSubject<boolean> @private */
+ private isMobile$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
+
+ /** Return the Device type @public */
+ public checkDeviceType(): void {
+ if (navigator.userAgent.match(/Android/i)
+ || navigator.userAgent.match(/webOS/i)
+ || navigator.userAgent.match(/iPhone/i)
+ || navigator.userAgent.match(/iPod/i)
+ || navigator.userAgent.match(/BlackBerry/i)
+ || navigator.userAgent.match(/Windows Phone/i)) {
+ this.isMobile$.next(true);
+ } else {
+ this.isMobile$.next(false);
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @file Project Service
+ */
+import { Injectable, Injector } from '@angular/core';
+import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
+import { AuthenticationService } from 'AuthenticationService';
+import { environment } from 'environment';
+import { ProjectData } from 'ProjectModel';
+import { BehaviorSubject, Observable, Subscription } from 'rxjs';
+import { SwitchProjectComponent } from 'SwitchProjectComponent';
+import { ProjectRoleMappings, UserDetail } from 'UserModel';
+import { ProjectModel } from 'VNFDModel';
+import { RestService } from './RestService';
+
+/**
+ * An Injectable is a class adorned with the @Injectable decorator function.
+ * @Injectable takes a metadata object that tells Angular how to compile and run module code
+ */
+@Injectable({
+ providedIn: 'root'
+})
+/** Exporting a class @exports ProjectService */
+export class ProjectService {
+ /** Get method for project list */
+ get projectList(): Observable<{}[]> {
+ return this.projectList$.asObservable();
+ }
+ /** To inject services @public */
+ public injector: Injector;
+
+ /** Holds all the projects details */
+ public allProjectList: string[];
+
+ /** Observable holds logined value @public */
+ public username$: Observable<string>;
+
+ /** Hold Rest Service Objects */
+ private restService: RestService;
+
+ /** Instance of the modal service @private */
+ private modalService: NgbModal;
+
+ /** Utilizes auth service for any auth operations @private */
+ private authService: AuthenticationService;
+
+ /** Holds the username in condition of type BehaviorSubject<string> @private */
+ private projectList$: BehaviorSubject<{}[]> = new BehaviorSubject<{}[]>([]);
+
+ constructor(injector: Injector) {
+ this.injector = injector;
+ this.restService = this.injector.get(RestService);
+ this.modalService = this.injector.get(NgbModal);
+ this.authService = this.injector.get(AuthenticationService);
+ }
+
+ /** List all the projects @public */
+ public getAllProjects(): Observable<{}> {
+ return this.restService.getResource(environment.PROJECTS_URL);
+ }
+
+ /** Get current project details from local storage @public */
+ public getCurrentProjectDetails(): Observable<{}> {
+ const project: string = localStorage.getItem('project_id');
+ return this.restService.getResource(environment.PROJECTS_URL + '/' + project);
+ }
+
+ /** Returns all the projects for a particular users @public */
+ public getUserProjects(): Observable<{}> {
+ const username: string = localStorage.getItem('username');
+ return this.restService.getResource(environment.USERS_URL + '/' + username);
+ }
+
+ /** Set header projects @public */
+ public setHeaderProjects(): void {
+ this.getUserProjects().subscribe((projects: UserDetail) => {
+ const projectList: {}[] = projects.project_role_mappings;
+ projectList.filter((list: ProjectModel) => {
+ if (list.project === localStorage.getItem('project_id')) {
+ localStorage.setItem('project', list.project_name);
+ this.authService.projectName$.next(list.project_name);
+ }
+ });
+ const projectDistinctList: {}[] = projectList.filter(
+ (thing: ProjectRoleMappings, i: number, arr: []) => arr
+ .findIndex((t: ProjectRoleMappings) => t.project_name === thing.project_name) === i
+ );
+ this.projectList$.next(projectDistinctList);
+ });
+ }
+
+ /** Toggle projects on selection @public */
+ public switchProjectModal(list: ProjectData): void {
+ const username: string = localStorage.getItem('username');
+ this.modalService.open(SwitchProjectComponent, { backdrop: 'static' })
+ .componentInstance.params = { projectID: list.project, username };
+ }
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+
+/**
+ * @file Provider for REST Service
+ */
+
+import { HttpClient, HttpHeaders } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateService } from '@ngx-translate/core';
+import { NotifierService } from 'angular-notifier';
+import { ERRORDATA } from 'CommonModel';
+import * as HttpStatus from 'http-status-codes';
+import { Observable } from 'rxjs';
+
+/**
+ * An Injectable is a class adorned with the @Injectable decorator function.
+ * @Injectable takes a metadata object that tells Angular how to compile and run module code
+ */
+@Injectable()
+/** Exporting a class @exports RestService */
+export class RestService {
+ /** convenient way to modify request made by the http service both before they are sent and after they return */
+ private http: HttpClient;
+ /** API URL. Disabled tslint since server doesn't support https protocol */
+ private apiURL: string = '';
+ /** Notifier service to popup notification @private */
+ private notifierService: NotifierService;
+ /** Instance for active modal service @public */
+ private activeModal: NgbModal;
+ /** insatnce for translate @private */
+ private translateService: TranslateService;
+
+ constructor(http: HttpClient, notifierService: NotifierService, activeModal: NgbModal, translateService: TranslateService) {
+ this.http = http;
+ this.notifierService = notifierService;
+ this.activeModal = activeModal;
+ this.translateService = translateService;
+ }
+
+ /**
+ * Get a resource from the server which identified by a URI.
+ * @param apiURL The URL of the resource to be retrieved.
+ */
+
+ public getResource(apiURL: string, httpHeaders?: { headers: HttpHeaders }): Observable<{}> {
+ return this.http.get(apiURL, httpHeaders);
+ }
+
+ /**
+ * Create a new resource on the server.
+ * @param apiURL The URL of the resource to be created.
+ * @param payload The request data to be sent to server.
+ */
+
+ public postResource(apiURLHeader: { url: string, httpOptions?: { headers: HttpHeaders } }, payload: {}): Observable<{}> {
+ return this.http.post(apiURLHeader.url, payload, apiURLHeader.httpOptions);
+ }
+
+ /**
+ * Modify the resource on the server.
+ * @param apiURL The URL of the resource to be created.
+ * @param payload The request data to be sent to server.
+ */
+
+ public patchResource(apiURLHeader: { url: string, httpOptions?: { headers: HttpHeaders } }, payload: {}): Observable<object> {
+ return this.http.patch(apiURLHeader.url, payload, apiURLHeader.httpOptions);
+ }
+
+ /**
+ * Replace the resource on the server.
+ * @param apiName The URL of the resource to be created.
+ * @param payload The request data to be sent to server.
+ */
+
+ public putResource(apiURLHeader: { url: string, httpOptions?: { headers: HttpHeaders } }, payload: {}): Observable<object> {
+ return this.http.put(apiURLHeader.url, payload, apiURLHeader.httpOptions);
+ }
+
+ /**
+ * Delete a resource identified by a URL.
+ * @param apiURL The URL of the resource to be deleted.
+ */
+
+ public deleteResource(apiURL: string, httpHeaders?: { headers: HttpHeaders }): Observable<object> {
+ return this.http.delete(apiURL, httpHeaders);
+ }
+ /**
+ * Handle Error response based on the status.
+ * @param error The error response reecieved from API call.
+ * @param method The http request method.
+ */
+ // tslint:disable-next-line: cyclomatic-complexity
+ public handleError(err: ERRORDATA, method?: string): void {
+ if (err.error.status === HttpStatus.UNAUTHORIZED) {
+ if (method !== 'get') {
+ if (err.error.detail !== 'Expired Token or Authorization HTTP header' &&
+ err.error.detail !== 'Invalid Token or Authorization HTTP header') {
+ this.notifierService.notify('error', err.error.detail !== undefined ?
+ err.error.detail : this.translateService.instant('HTTPERROR.401'));
+ }
+ this.activeModal.dismissAll();
+ }
+ } else if (err.error.status === HttpStatus.BAD_REQUEST) {
+ this.notifierService.notify('error', err.error.detail !== undefined ?
+ err.error.detail : this.translateService.instant('HTTPERROR.400'));
+ } else if (err.error.status === HttpStatus.NOT_FOUND) {
+ this.notifierService.notify('error', err.error.detail !== undefined ?
+ err.error.detail : this.translateService.instant('HTTPERROR.404'));
+ } else if (err.error.status === HttpStatus.CONFLICT) {
+ this.notifierService.notify('error', err.error.detail !== undefined ?
+ err.error.detail : this.translateService.instant('HTTPERROR.409'));
+ this.activeModal.dismissAll();
+ } else if (err.error.status === HttpStatus.INTERNAL_SERVER_ERROR) {
+ this.notifierService.notify('error', err.error.detail !== undefined ?
+ err.error.detail : this.translateService.instant('HTTPERROR.500'));
+ } else if (err.error.status === HttpStatus.BAD_GATEWAY) {
+ this.notifierService.notify('error', this.translateService.instant('HTTPERROR.502'));
+ } else if (err.error.status === HttpStatus.SERVICE_UNAVAILABLE) {
+ this.notifierService.notify('error', this.translateService.instant('HTTPERROR.503'));
+ } else if (err.error.status === HttpStatus.GATEWAY_TIMEOUT) {
+ this.notifierService.notify('error', this.translateService.instant('HTTPERROR.504'));
+ } else {
+ this.notifierService.notify('error', err.error.detail !== undefined ?
+ err.error.detail : this.translateService.instant('ERROR'));
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @file Provider for Shared Service
+ */
+import { HttpErrorResponse, HttpHeaders } from '@angular/common/http';
+import { EventEmitter, Injectable, Output } from '@angular/core';
+import { FormArray, FormGroup } from '@angular/forms';
+import { Router } from '@angular/router';
+import { CONSTANTNUMBER, ERRORDATA, GETAPIURLHEADER, PACKAGEINFO, PAGERSMARTTABLE, SMARTTABLECLASS, TARSETTINGS } from 'CommonModel';
+import { environment } from 'environment';
+import * as HttpStatus from 'http-status-codes';
+import * as untar from 'js-untar';
+import * as pako from 'pako';
+import { RestService } from 'RestService';
+import { isNullOrUndefined } from 'util';
+
+/** This is added globally by the tar.js library */
+// tslint:disable-next-line: no-any
+declare const Tar: any;
+
+/**
+ * An Injectable is a class adorned with the @Injectable decorator function.
+ * @Injectable takes a metadata object that tells Angular how to compile and run module code
+ */
+@Injectable({
+ providedIn: 'root'
+})
+/** Exporting a class @exports SharedService */
+export class SharedService {
+ /** call the parent using event information @private */
+ @Output() public dataEvent: EventEmitter<{}> = new EventEmitter<{}>();
+
+ /** Variables to hold regexp pattern for URL */
+ // tslint:disable-next-line: max-line-length
+ public REGX_URL_PATTERN: RegExp = new RegExp(/^(http?|ftp|https):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.[a-zA-Z0-9]{2,15})(:((6553[0-5])|(655[0-2][0-9])|(65[0-4][0-9]{2})|(6[0-4][0-9]{3})|([1-5][0-9]{4})|([0-5]{0,5})|([0-9]{1,4})))*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/);
+
+ /** Variables to hold regexp pattern for IP Address */
+ public REGX_IP_PATTERN: RegExp = new RegExp(/^(?:(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(?!$)|$)){4}$/);
+
+ /** Variables to hold regexp pattern for Port Number */
+ // tslint:disable-next-line: max-line-length
+ public REGX_PORT_PATTERN: RegExp = new RegExp(/^((6553[0-5])|(655[0-2][0-9])|(65[0-4][0-9]{2})|(6[0-4][0-9]{3})|([1-5][0-9]{4})|([0-5]{0,5})|([0-9]{1,4}))$/);
+
+ /** Variables to hold regexp pattern for DPID */
+ public REGX_DPID_PATTERN: RegExp = new RegExp(/^[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){7}$/);
+
+ /** Variable to hold regexp pattern for password */
+ // tslint:disable-next-line: max-line-length
+ public REGX_PASSWORD_PATTERN: RegExp = new RegExp(/^.*(?=.{8,})((?=.*[!@#$%^&*()\-_=+{};:,<.>]){1})(?=.*\d)((?=.*[a-z]){1})((?=.*[A-Z]){1}).*$/);
+
+ /** FormGroup instance added to the form @ html @public */
+ public formGroup: FormGroup;
+
+ /** Controls the go to top button on scroll @public */
+ public showGotoTop: boolean;
+
+ /** Holds OSM Version value @public */
+ public osmVersion: string;
+
+ /** express number for time manupulation -2 */
+ private epochTimeMinus2: number = -2;
+
+ /** express number for time manupulation 1000 */
+ private epochTime1000: number = 1000;
+
+ /** Random string generator length */
+ private randomStringLength: number = 4;
+
+ /** Instance of the rest service @private */
+ private restService: RestService;
+
+ /** Service holds the router information @private */
+ private router: Router;
+
+ /** Check for the root directory @private */
+ private directoryCount: number = 2;
+
+ constructor(restService: RestService, router: Router) {
+ this.restService = restService;
+ this.router = router;
+ }
+
+ /** convert epoch time function @public */
+ public convertEpochTime(unixtimestamp: number): string {
+ const monthsArr: string[] = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
+ 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
+ const date: Date = new Date(unixtimestamp * this.epochTime1000);
+ const year: number = date.getFullYear();
+ const month: string = monthsArr[date.getMonth()];
+ const day: number = date.getDate();
+ const hours: number = date.getHours();
+ const minutes: string = '0' + date.getMinutes();
+ const seconds: string = '0' + date.getSeconds();
+ return month + '-' + day + '-' + year + ' ' + hours + ':' + minutes.substr(this.epochTimeMinus2) + ':'
+ + seconds.substr(this.epochTimeMinus2);
+ }
+
+ /** Download Files function @public */
+ public downloadFiles(shortName: string, binaryData: Blob[], filetype: string): void {
+ const downloadLink: HTMLAnchorElement = document.createElement('a');
+ downloadLink.href = window.URL.createObjectURL(new Blob(binaryData, { type: filetype }));
+ if (shortName !== undefined) {
+ if (window.navigator.msSaveOrOpenBlob) {
+ window.navigator.msSaveBlob(new Blob(binaryData, { type: filetype }), 'OSM_Export_' + shortName + '.tar.gz');
+ } else {
+ downloadLink.setAttribute('download', 'OSM_Export_' + shortName + '.tar.gz');
+ document.body.appendChild(downloadLink);
+ downloadLink.click();
+ }
+ }
+ }
+
+ /** Call this method after delete perform action is completed in the ng-smart-table data @public */
+ public callData(): void {
+ this.dataEvent.emit();
+ }
+
+ /** Generate random string @public */
+ public randomString(): string {
+ const chars: string = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+ let result: string = '';
+ // tslint:disable-next-line:no-increment-decrement
+ for (let randomStringRef: number = this.randomStringLength; randomStringRef > 0; --randomStringRef) {
+ result += chars[Math.floor(Math.random() * chars.length)];
+ }
+ return result;
+ }
+ /** Function to read uploaded file String @public */
+ public async getFileString(files: FileList, fileType: string): Promise<string | ArrayBuffer> {
+ const reader: FileReader = new FileReader();
+ return new Promise<string | ArrayBuffer>((resolve: Function, reject: Function): void => {
+ if (this.vaildataFileInfo(files[0], fileType)) {
+ this.readFileContent(reader, files[0], fileType);
+ } else {
+ reject('typeError');
+ }
+ reader.onload = (): void => {
+ if (reader.result === null) {
+ reject('contentError');
+ }
+ resolve(reader.result);
+ };
+ reader.onerror = (event: Event): void => {
+ reject('contentError');
+ };
+ });
+ }
+ /** Method to handle tar and tar.gz file for shared YAML file content @public */
+ public async targzFile(packageInfo: PACKAGEINFO): Promise<string | ArrayBuffer> {
+ return new Promise<string | ArrayBuffer>((resolve: Function, reject: Function): void => {
+ const httpOptions: GETAPIURLHEADER = this.getHttpOptions();
+ let apiUrl: string = '';
+ apiUrl = packageInfo.packageType === 'nsd' ? environment.NSDESCRIPTORS_URL + '/' + packageInfo.id + '/nsd_content' :
+ environment.VNFPACKAGES_URL + '/' + packageInfo.id + '/package_content';
+ this.restService.getResource(apiUrl, httpOptions).subscribe((response: ArrayBuffer) => {
+ try {
+ // tslint:disable-next-line: no-any
+ const tar: any = new Tar();
+ const originalInput: Uint8Array = pako.inflate(response, { to: 'Uint8Array' });
+ untar(originalInput.buffer).then((extractedFiles: TARSETTINGS[]) => {
+ const getFoldersFiles: {}[] = extractedFiles;
+ const folderNameStr: string = extractedFiles[0].name;
+ getFoldersFiles.forEach((value: TARSETTINGS) => {
+ const getRootFolder: string[] = value.name.split('/');
+ if (value.name.startsWith(folderNameStr) &&
+ (value.name.endsWith('.yaml') || value.name.endsWith('.yml')) &&
+ getRootFolder.length === this.directoryCount) {
+ tar.append(value.name, packageInfo.descriptor, { type: value.type });
+ } else {
+ if (value.type !== 'L') {
+ tar.append(value.name, new Uint8Array(value.buffer), { type: value.type });
+ }
+ }
+ });
+ const out: Uint8Array = tar.out;
+ const originalOutput: Uint8Array = pako.gzip(out);
+ resolve(originalOutput.buffer);
+ }, (err: string) => {
+ reject('');
+ });
+ } catch (e) {
+ reject('');
+ }
+ }, (error: HttpErrorResponse) => {
+ if (error.status === HttpStatus.NOT_FOUND || error.status === HttpStatus.UNAUTHORIZED) {
+ this.router.navigateByUrl('404', { skipLocationChange: true }).catch();
+ } else {
+ this.restService.handleError(error, 'get');
+ reject('');
+ }
+ });
+ });
+ }
+ /** Method to check given string is JSON or not @public */
+ public checkJson(jsonString: string): boolean {
+ jsonString = jsonString.replace(/'/g, '"');
+ try {
+ JSON.parse(jsonString);
+ } catch (e) {
+ return false;
+ }
+ return true;
+ }
+ /** Clean the form before submit @public */
+ public cleanForm(formGroup: FormGroup): void {
+ Object.keys(formGroup.controls).forEach((key: string) => {
+ if ((!isNullOrUndefined((formGroup.get(key) as FormArray | FormGroup).controls)) && key !== 'vimconfig') {
+ // tslint:disable-next-line: no-shadowed-variable
+ for (const { item, index } of (formGroup.get(key).value).map((item: {}, index: number) => ({ item, index }))) {
+ const newFormGroup: FormGroup = (formGroup.get(key) as FormArray).controls[index] as FormGroup;
+ this.cleanForm(newFormGroup);
+ }
+ } else if (formGroup.get(key).value !== undefined && formGroup.get(key).value !== null && key !== 'vimconfig') {
+ if (!Array.isArray(formGroup.get(key).value)) {
+ if (typeof formGroup.get(key).value === 'string') {
+ formGroup.get(key).setValue(formGroup.get(key).value.trim());
+ }
+ }
+ } else if (key === 'vimconfig') {
+ const newFormGroup: FormGroup = formGroup.get(key) as FormGroup;
+ this.cleanForm(newFormGroup);
+ }
+ });
+ }
+ /** Method to return the config of pager value for ngSmarttable @public */
+ public paginationPagerConfig(): PAGERSMARTTABLE {
+ return {
+ display: true,
+ perPage: environment.paginationNumber
+ };
+ }
+ /** Method to return the class for the table for ngSmarttable @public */
+ public tableClassConfig(): SMARTTABLECLASS {
+ return {
+ class: 'table list-data'
+ };
+ }
+ /** Method to return all languages name and its code @public */
+ public languageCodeList(): {}[] {
+ return [
+ { code: 'en', language: 'English' },
+ { code: 'es', language: 'Spanish' },
+ { code: 'pt', language: 'Portuguese' },
+ { code: 'de', language: 'German' }
+ ];
+ }
+ /** Fetch OSM Version @public */
+ public fetchOSMVersion(): void {
+ this.restService.getResource(environment.OSM_VERSION_URL).subscribe((res: { version: string }) => {
+ const version: string[] = res.version.split('+');
+ if (!isNullOrUndefined(version[0])) {
+ this.osmVersion = version[0];
+ } else {
+ this.osmVersion = null;
+ }
+ }, (error: ERRORDATA) => {
+ this.osmVersion = null;
+ this.restService.handleError(error, 'get');
+ });
+ }
+ /** Method to validate file extension and size @private */
+ private vaildataFileInfo(fileInfo: File, fileType: string): boolean {
+ const extension: string = fileInfo.name.substring(fileInfo.name.lastIndexOf('.') + 1);
+ const packageSize: number = CONSTANTNUMBER.oneMB * environment.packageSize;
+ if (extension.toLowerCase() === fileType && fileInfo.size <= packageSize) {
+ return true;
+ }
+ return false;
+ }
+ /** Method to read file content based on type @private */
+ private readFileContent(reader: FileReader, fileInfo: File, fileType: string): void {
+ if (fileType === 'gz') {
+ reader.readAsArrayBuffer(fileInfo);
+ } else {
+ reader.readAsText(fileInfo);
+ }
+ }
+ /** Method to handle http options @public */
+ private getHttpOptions(): GETAPIURLHEADER {
+ return {
+ headers: new HttpHeaders({
+ Accept: 'application/gzip, application/json',
+ 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
+ }),
+ responseType: 'arraybuffer'
+ };
+ }
+}
--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ 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.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @file This file is required by karma.conf.js and loads recursively all the .spec and framework files.
+ */
+import { getTestBed } from '@angular/core/testing';
+import {
+ BrowserDynamicTestingModule,
+ platformBrowserDynamicTesting
+} from '@angular/platform-browser-dynamic/testing';
+import 'zone.js/dist/zone-testing';
+
+/** const variable require */
+// tslint:disable:no-reserved-keywords
+// tslint:disable-next-line:no-any
+declare const require: any;
+
+// First, initialize the Angular testing environment.
+getTestBed().initTestEnvironment(
+ BrowserDynamicTestingModule,
+ platformBrowserDynamicTesting()
+);
+
+/** const variable context */
+// Then we find all the tests.
+// tslint:disable-next-line:typedef
+const context = require.context('./', true, /\.spec\.ts$/);
+// And load the modules.
+context.keys().map(context);
--- /dev/null
+{
+ "extends": "../tsconfig.json",
+ "compilerOptions": {
+ "outDir": "../out-tsc/app",
+ "types": []
+ },
+ "exclude": [
+ "test.ts",
+ "**/*.spec.ts"
+ ],
+ "angularCompilerOptions": {
+ "enableIvy": true,
+ "fullTemplateTypeCheck": false,
+ "strictInjectionParameters": false
+ }
+}
\ No newline at end of file
--- /dev/null
+{
+ "extends": "../tsconfig.json",
+ "compilerOptions": {
+ "outDir": "../out-tsc/spec",
+ "types": [
+ "jasmine",
+ "node"
+ ]
+ },
+ "files": [
+ "test.ts",
+ "polyfills.ts"
+ ],
+ "include": [
+ "**/*.spec.ts",
+ "**/*.d.ts"
+ ]
+}
--- /dev/null
+{
+ "extends": "../tslint.json",
+ "rules": {
+ "directive-selector": [
+ true,
+ "attribute",
+ "app",
+ "camelCase"
+ ],
+ "component-selector": [
+ true,
+ "element",
+ "app",
+ "kebab-case"
+ ]
+ }
+}
--- /dev/null
+{
+ "compileOnSave": false,
+ "compilerOptions": {
+ "resolveJsonModule": true,
+ "baseUrl": ".",
+ "downlevelIteration": true,
+ "outDir": "./dist/out-tsc",
+ "sourceMap": true,
+ "declaration": false,
+ "module": "esnext",
+ "moduleResolution": "node",
+ "emitDecoratorMetadata": true,
+ "experimentalDecorators": true,
+ "importHelpers": true,
+ "target": "es5",
+ "typeRoots": [
+ "node_modules/@types"
+ ],
+ "lib": [
+ "es2018",
+ "dom"
+ ],
+ "paths": {
+ "CommonModel": ["src/models/CommonModel"],
+ "environment": ["src/environments/environment"],
+ "AuthInterceptorService": ["src/services/AuthInterceptorService"],
+ "RestService": ["src/services/RestService"],
+ "SharedService": ["src/services/SharedService"],
+ "ProjectService": ["src/services/ProjectService"],
+ "DataService": ["src/services/DataService"],
+ "AuthenticationService": ["src/services/AuthenticationService"],
+ "AuthGuardService": ["src/services/AuthGuardService"],
+ "AcessGuardService": ["src/services/AcessGuardService"],
+ "DeviceCheckService": ["src/services/DeviceCheckService"],
+ "NSDModel":["src/models/NSDModel"],
+ "VimAccountModel" : ["src/models/VimAccountModel"],
+ "LayoutComponent": ["src/app/layouts/LayoutComponent"],
+ "SidebarComponent": ["src/app/layouts/sidebar/SidebarComponent"],
+ "HeaderComponent": ["src/app/layouts/header/HeaderComponent"],
+ "UserSettingsComponent": ["src/app/user-settings/UserSettingsComponent"],
+ "LoginComponent": ["src/app/login/LoginComponent"],
+ "DashboardComponent": ["src/app/dashboard/DashboardComponent"],
+ "NSPackages" : ["src/app/packages/ns-packages/NSPackagesComponent"],
+ "NsPackagesAction": ["src/app/utilities/ns-packages-action/NsPackagesActionComponent"],
+ "InstantiateNs": ["src/app/packages/instantiate-ns/InstantiateNsComponent"],
+ "ShowContent": ["src/app/packages/show-content/ShowContentComponent"],
+ "DeleteComponent": ["src/app/utilities/delete/DeleteComponent"],
+ "EditPackagesComponent": ["src/app/utilities/edit-packages/EditPackagesComponent"],
+ "NetsliceTemplate":["src/app/packages/netslice-template/NetsliceTemplateComponent"],
+ "DragDirective": ["src/app/utilities/dragDropUpload/DragDirective"],
+ "NSComposer": ["src/app/packages/ns-packages/ns-composer/NSComposerComponent"],
+ "VNFComposer": ["src/app/packages/ns-packages/vnf-composer/VNFComposerComponent"],
+ "Packages":["src/app/packages/PackagesComponent"],
+ "VNFPackages": ["src/app/packages/vnf-packages/VNFPackagesComponent"],
+ "VNFDModel": ["src/models/VNFDModel"],
+ "VNFPackagesAction" :["src/app/utilities/vnf-packages-action/VNFPackagesActionComponent"],
+ "NetworkSliceModel" : ["src/models/NetworkSliceModel"],
+ "NetslicePackagesAction" : ["src/app/utilities/netslice-packages-action/NetslicePackagesActionComponent"],
+ "PageNotFound" : ["src/app/page-not-found/PageNotFoundComponent"],
+ "ProjectsModule" : ["src/app/projects/ProjectsModule"],
+ "ProjectModel" : ["src/models/ProjectModel"],
+ "ProjectsComponent" : ["src/app/projects/ProjectsComponent"],
+ "ProjectCreateUpdate" : ["src/app/projects/project-create-update/ProjectCreateUpdateComponent"],
+ "ProjectsAction": ["src/app/utilities/projects-action/ProjectsActionComponent"],
+ "BreadCrumb": ["src/app/layouts/breadcrumb/BreadcrumbComponent"],
+ "VNFDEdit": ["src/app/packages/vnfd-edit/VNFDEditComponent"],
+ "VNFInstanceModel": ["src/models/VNFInstanceModel"],
+ "InstancesComponent": ["src/app/instances/InstancesComponent"],
+ "VNFInstancesComponent": ["src/app/instances/vnf-instances/VNFInstancesComponent"],
+ "NSInstancesComponent": ["src/app/instances/ns-instances/NSInstancesComponent"],
+ "HistoryOperationsComponent": ["src/app/instances/ns-history-operations/HistoryOperationsComponent"],
+ "NetsliceInstancesComponent": ["src/app/instances/netslice-instances/NetsliceInstancesComponent"],
+ "VNFInstancesActionComponent": ["src/app/utilities/vnf-instances-action/VNFInstancesActionComponent"],
+ "NSInstancesActionComponent": ["src/app/utilities/ns-instances-action/NSInstancesActionComponent"],
+ "NetsliceInstancesActionComponent": ["src/app/utilities/netslice-instances-action/NetsliceInstancesActionComponent"],
+ "NSInstanceModel": ["src/models/NSInstanceModel"],
+ "ShowInfoComponent": ["src/app/utilities/show-info/ShowInfoComponent"],
+ "NSTopologyComponent": ["src/app/instances/ns-topology/NSTopologyComponent"],
+ "NSTopologyModel": ["src/models/NSTopologyModel"],
+ "SDNControllerComponent": ["src/app/sdn-controller/SDNControllerComponent"],
+ "SDNControllerDetailsComponent": ["src/app/sdn-controller/sdn-controller-details/SDNControllerDetailsComponent"],
+ "SDNControllerInfoComponent": ["src/app/sdn-controller/sdn-controller-info/SDNControllerInfoComponent"],
+ "SDNControllerActionComponent": ["src/app/utilities/sdn-controller-action/SDNControllerActionComponent"],
+ "NewSDNControllerComponent": ["src/app/sdn-controller/new-sdn-controller/NewSDNControllerComponent"],
+ "SDNControllerModel": ["src/models/SDNControllerModel"],
+ "UserModel": ["src/models/UserModel"],
+ "UsersComponent": ["src/app/users/UsersComponent"],
+ "UserDetailsComponent": ["src/app/users/user-details/UserDetailsComponent"],
+ "AddEditUserComponent": ["src/app/users/add-user/AddEditUserComponent"],
+ "UsersActionComponent": ["src/app/utilities/users-action/UsersActionComponent"],
+ "ProjectRoleComponent": ["src/app/users/project-role/ProjectRoleComponent"],
+ "PagePerRow": ["src/app/utilities/page-per-row/PagePerRow"],
+ "PagePerRowModule": ["src/app/utilities/page-per-row/PagePerRowModule"],
+ "VimAccountsModule": ["src/app/vim-accounts/VimAccountsModule"],
+ "VimAccountsComponent": ["src/app/vim-accounts/VimAccountsComponent"],
+ "VimAccountDetails": ["src/app/vim-accounts/vim-account-details/VimAccountDetailsComponent"],
+ "NewVimaccount": ["src/app/vim-accounts/new-vimaccount/NewVimaccountComponent"],
+ "InfoVim": ["src/app/vim-accounts/info-vim/InfoVimComponent"],
+ "VimAccountsAction": ["src/app/utilities/vim-accounts-action/VimAccountsActionComponent"],
+ "InstantiateNetSliceTemplate":["src/app/packages/instantiate-net-slice-template/InstantiateNetSliceTemplateComponent"],
+ "LoaderComponent": ["src/app/utilities/loader/LoaderComponent"],
+ "LoaderModule": ["src/app/utilities/loader/LoaderModule"],
+ "NSPrimitiveComponent": ["src/app/instances/ns-primitive/NSPrimitiveComponent"],
+ "ConfirmationTopology": ["src/app/utilities/confirmation-topology/ConfirmationTopologyComponent"],
+ "ComposePackages": ["src/app/utilities/compose-packages/ComposePackages"],
+ "WIMAccountsAction": ["src/app/utilities/wim-accounts-action/WIMAccountsActionComponent"],
+ "WIMAccountsModule": ["src/app/wim-accounts/WIMAccountsModule"],
+ "WIMAccountsComponent": ["src/app/wim-accounts/WIMAccountsComponent"],
+ "WIMAccountDetails": ["src/app/wim-accounts/wim-account-details/WIMAccountDetailsComponent"],
+ "NewWIMAccount": ["src/app/wim-accounts/new-wim-account/NewWIMAccountComponent"],
+ "WIMAccountInfo": ["src/app/wim-accounts/wim-account-info/WIMAccountInfoComponent"],
+ "WIMAccountModel": ["src/models/WIMAccountModel"],
+ "Roles": ["src/app/roles/RolesComponent"],
+ "RolesDetails": ["src/app/roles/roles-details/RolesDetailsComponent"],
+ "RolesAction": ["src/app/utilities/roles-action/RolesActionComponent"],
+ "RolesCreateEdit": ["src/app/roles/roles-create-edit/RolesCreateEditComponent"],
+ "RolesModel": ["src/models/RoleModel"],
+ "PDUInstancesComponent": ["src/app/instances/pdu-instances/PDUInstancesComponent"],
+ "PDUInstanceModel": ["src/models/PDUInstanceModel"],
+ "PDUInstancesActionComponent": ["src/app/utilities/pdu-instances-action/PDUInstancesActionComponent"],
+ "AddPDUInstancesComponent": ["src/app/instances/pdu-instances/add-pdu-instances/AddPDUInstancesComponent"],
+ "ClonePackage": ["src/app/utilities/clone-package/ClonePackageComponent"],
+ "K8sComponent": ["src/app/k8s/K8sComponent"],
+ "K8sClusterComponent": ["src/app/k8s/k8scluster/K8sClusterComponent"],
+ "K8sRepositoryComponent":["src/app/k8s/k8srepository/K8sRepositoryComponent"],
+ "K8sActionComponent": ["src/app/k8s/k8s-action/K8sActionComponent"],
+ "K8sModel": ["src/models/K8sModel"],
+ "K8sAddClusterComponent": ["src/app/k8s/k8s-add-cluster/K8sAddClusterComponent"],
+ "K8sAddRepoComponent": ["src/app/k8s/k8s-add-repo/K8sAddRepoComponent"],
+ "SwitchProjectComponent": ["src/app/utilities/switch-project/SwitchProjectComponent"],
+ "ProjectLinkComponent":["src/app/utilities/project-link/ProjectLinkComponent"],
+ "PageReload": ["src/app/utilities/page-reload/PageReload"],
+ "PageReloadModule": ["src/app/utilities/page-reload/PageReloadModule"],
+ "GoToTopDirective": ["src/directive/GoToTopDirective"],
+ "VNFLinkComponent": ["src/app/instances/vnf-instances/vnf-link/VNFLinkComponent"],
+ "PACKAGEJSON": ["package.json"]
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+{
+ "linterOptions" : {
+ "exclude" : [
+ "package.json"
+ ]
+ },
+ "defaultSeverity": "error",
+ "rules": {
+ "insecure-random": false,
+ "no-banned-terms": true,
+ "no-cookies": true,
+ "no-delete-expression": true,
+ "no-disable-auto-sanitization": true,
+ "no-document-domain": true,
+ "no-document-write": true,
+ "no-eval": true,
+ "no-exec-script": true,
+ "no-function-constructor-with-string-args": true,
+ "no-http-string": [
+ true,
+ "http://www.example.com/?.*",
+ "http://www.examples.com/?.*"
+ ],
+ "no-inner-html": true,
+ "no-octal-literal": true,
+ "no-reserved-keywords": true,
+ "no-string-based-set-immediate": true,
+ "no-string-based-set-interval": true,
+ "no-string-based-set-timeout": true,
+ "non-literal-require": true,
+ "possible-timing-attack": true,
+ "react-anchor-blank-noopener": true,
+ "react-iframe-missing-sandbox": true,
+ "react-no-dangerous-html": true,
+ "forin": true,
+ "jquery-deferred-must-complete": true,
+ "label-position": true,
+ "mocha-avoid-only": true,
+ "mocha-no-side-effect-code": true,
+ "no-any": true,
+ "no-arg": true,
+ "no-backbone-get-set-outside-model": true,
+ "no-bitwise": true,
+ "no-conditional-assignment": true,
+ "no-console": false,
+ "no-constant-condition": true,
+ "no-control-regex": true,
+ "no-debugger": true,
+ "no-duplicate-case": true,
+ "no-duplicate-variable": true,
+ "no-empty": true,
+ "no-increment-decrement": true,
+ "no-invalid-regexp": true,
+ "no-invalid-this": true,
+ "no-jquery-raw-elements": true,
+ "no-misused-new": true,
+ "no-regex-spaces": true,
+ "no-sparse-arrays": true,
+ "no-stateless-class": true,
+ "no-string-literal": true,
+ "no-string-throw": true,
+ "no-unnecessary-bind": true,
+ "no-unnecessary-initializer": true,
+ "no-unnecessary-override": true,
+ "no-unsafe-finally": true,
+ "no-unused-expression": true,
+ "no-with-statement": true,
+ "promise-must-complete": true,
+ "radix": true,
+ "react-this-binding-issue": true,
+ "react-unused-props-and-state": true,
+ "switch-default": true,
+ "triple-equals": [
+ true,
+ "allow-null-check"
+ ],
+ "use-isnan": true,
+ "use-named-parameter": true,
+ "valid-typeof": true,
+ "adjacent-overload-signatures": true,
+ "array-type": [
+ true,
+ "array"
+ ],
+ "arrow-parens": true,
+ "callable-types": true,
+ "chai-prefer-contains-to-index-of": true,
+ "chai-vague-errors": true,
+ "class-name": true,
+ "comment-format": true,
+ "export-name": true,
+ "function-name": true,
+ "import-name": true,
+ "interface-name": false,
+ "jsdoc-format": true,
+ "max-classes-per-file": [
+ true,
+ 3
+ ],
+ "max-file-line-count": true,
+ "max-func-body-length": [
+ true,
+ 100,
+ {
+ "ignore-parameters-to-function-regex": "describe"
+ }
+ ],
+ "max-line-length": [
+ true,
+ 140
+ ],
+ "member-access": true,
+ "member-ordering": [
+ true,
+ {
+ "order": "fields-first"
+ }
+ ],
+ "missing-jsdoc": true,
+ "mocha-unneeded-done": true,
+ "new-parens": true,
+ "no-construct": true,
+ "no-default-export": true,
+ "no-empty-interface": true,
+ "no-for-in": true,
+ "no-function-expression": true,
+ "no-inferrable-types": false,
+ "no-multiline-string": true,
+ "no-null-keyword": false,
+ "no-parameter-properties": true,
+ "no-relative-imports": false,
+ "no-require-imports": true,
+ "no-shadowed-variable": true,
+ "no-typeof-undefined": true,
+ "no-unnecessary-field-initialization": true,
+ "no-unnecessary-local-variable": true,
+ "no-var-keyword": true,
+ "no-var-requires": true,
+ "no-var-self": true,
+ "object-literal-sort-keys": false,
+ "one-variable-per-declaration": true,
+ "only-arrow-functions": [
+ true,
+ "allow-declarations",
+ "allow-named-functions"
+ ],
+ "ordered-imports": true,
+ "prefer-array-literal": true,
+ "prefer-const": true,
+ "prefer-for-of": true,
+ "prefer-method-signature": true,
+ "typedef": [
+ true,
+ "call-signature",
+ "arrow-call-signature",
+ "parameter",
+ "arrow-parameter",
+ "property-declaration",
+ "variable-declaration",
+ "member-variable-declaration"
+ ],
+ "underscore-consistent-invocation": true,
+ "unified-signatures": true,
+ "variable-name": true,
+ "react-a11y-anchors": true,
+ "react-a11y-aria-unsupported-elements": true,
+ "react-a11y-event-has-role": true,
+ "react-a11y-image-button-has-alt": true,
+ "react-a11y-img-has-alt": true,
+ "react-a11y-lang": true,
+ "react-a11y-meta": true,
+ "react-a11y-props": true,
+ "react-a11y-proptypes": true,
+ "react-a11y-role": true,
+ "react-a11y-role-has-required-aria-props": true,
+ "react-a11y-role-supports-aria-props": true,
+ "react-a11y-tabindex-no-positive": true,
+ "react-a11y-titles": true,
+ "align": [
+ true,
+ "statements"
+ ],
+ "curly": true,
+ "eofline": true,
+ "import-spacing": true,
+ "indent": [
+ true,
+ "spaces"
+ ],
+ "linebreak-style": false,
+ "no-consecutive-blank-lines": true,
+ "no-empty-line-after-opening-brace": true,
+ "no-trailing-whitespace": true,
+ "no-unnecessary-semicolons": true,
+ "object-literal-key-quotes": [
+ true,
+ "as-needed"
+ ],
+ "one-line": [
+ false
+ ],
+ "quotemark": [
+ true,
+ "single"
+ ],
+ "react-tsx-curly-spacing": true,
+ "semicolon": [
+ true,
+ "always"
+ ],
+ "trailing-comma": [
+ true,
+ {
+ "singleline": "never",
+ "multiline": "never"
+ }
+ ],
+ "typedef-whitespace": false,
+ "whitespace": [
+ true,
+ "check-branch",
+ "check-decl",
+ "check-operator",
+ "check-separator",
+ "check-type"
+ ],
+ "ban": false,
+ "cyclomatic-complexity": true,
+ "file-header": false,
+ "import-blacklist": false,
+ "interface-over-type-literal": true,
+ "no-internal-module": true,
+ "no-magic-numbers": true,
+ "no-mergeable-namespace": false,
+ "no-namespace": true,
+ "no-reference": true,
+ "no-unexternalized-strings": true,
+ "object-literal-shorthand": true,
+ "no-angle-bracket-type-assertion": true,
+ "prefer-type-cast": false,
+ "space-before-function-paren": false,
+ "missing-optional-annotation": false,
+ "no-duplicate-parameter-names": false,
+ "no-empty-interfaces": true,
+ "no-missing-visibility-modifiers": false,
+ "no-multiple-var-decl": false,
+ "no-switch-case-fall-through": true,
+ //As of 2017-08-21 'no-unused-variable' doesn't work well with generics, disabled for now
+ "no-unused-variable": false,
+ "typeof-compare": true,
+ "no-inferred-empty-object-type": true,
+ "await-promise": true,
+ "no-floating-promises": true,
+ "no-for-in-array": true,
+ "no-use-before-declare": true,
+ "promise-function-async": true,
+ "completed-docs": [
+ true,
+ {
+ "classes": {
+ "visibilities": ["all"]
+ },
+ "enums": {
+ "visibilities": ["all"]
+ },
+ "functions": {
+ "visibilities": ["all"]
+ },
+ "interfaces": {
+ "visibilities": ["all"]
+ },
+ "methods": {
+ "locations": ["all"],
+ "privacies": ["all"]
+ },
+ "namespaces": {
+ "visibilities": ["all"]
+ },
+ "properties": {
+ "locations": ["all"],
+ "privacies": ["all"]
+ },
+ "types": {
+ "visibilities": ["all"]
+ },
+ "variables": {
+ "visibilities": ["all"]
+ }
+ }
+ ],
+ "no-unnecessary-qualifier": true,
+ "no-void-expression": true,
+ "strict-boolean-expressions": [true, "allow-null-union"],
+ // The following produce too much noise with untyped or not-sufficiently typed libraries
+ "restrict-plus-operands": false,
+ "no-unsafe-any": false
+ },
+ "rulesDirectory": ["./node_modules/tslint-microsoft-contrib/"]
+}