diff options
74 files changed, 2370 insertions, 309 deletions
diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 2421e386c..000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "files.exclude": { - "**/.classpath": true, - "**/.project": true, - "**/.settings": true, - "**/.factorypath": true - } -}
\ No newline at end of file @@ -5,3 +5,46 @@ ## Reference https://github.com/pinterest/ktlint + +## Getting started + +![Basic_Architecture](./docs/media/CDS.png) + +## Basic Requirements +Before you can build this project, you must install and configure the following dependencies on your machine: + + 1- Java 8 SDK + + 2- Node and npm installed + + 3- Angular CLI & Angular v8 + + 4- MySQL Database + + 5- maven + +## Running in Development Mode + +* In the main project folder run `mvn clean install` command to install all libraries and dependencies for maven and npm. + + 1- Back-end MS + + * create `sdnctl` table in MySQL + * (Optional) You could run the project in a specific profile(dev, local) by adding `-Dspring.profiles.active=profile-name` + +2- Loop-back server: that allow your request to reach the backend from cds-ui + * move to `./cds-ui/server/` folder and run the command `npm start` + + 3- cds-ui + + * move to `./cds-ui/designer-client/` folder and run the command `npm start`, This command will make sure all the files follow the linting rules and then connect to the loopback server. + +## Using an IDE + +**Front-end** you could use `vscode` or `webstorm`. + +**Back-end** `Intellij` with kotlin plugin or any other editor + + +--- +For more information check the `docs` folder.
\ No newline at end of file diff --git a/cds-ui/designer-client/angular.json b/cds-ui/designer-client/angular.json index a84b95e39..e503c1535 100644 --- a/cds-ui/designer-client/angular.json +++ b/cds-ui/designer-client/angular.json @@ -25,6 +25,7 @@ ], "styles": [ "src/styles.css", + "node_modules/ngx-toastr/toastr.css", "./node_modules/datatables.net-dt/css/jquery.dataTables.css", "./node_modules/bootstrap/dist/css/bootstrap.min.css", "./node_modules/@angular/material/prebuilt-themes/purple-green.css", @@ -122,10 +123,7 @@ "./node_modules/@angular/material/prebuilt-themes/purple-green.css", "./node_modules/font-awesome/css/font-awesome.css" ], - "scripts": [ - - - ] + "scripts": [] } }, "lint": { diff --git a/cds-ui/designer-client/package-lock.json b/cds-ui/designer-client/package-lock.json index 9df5d033f..89d9c064c 100644 --- a/cds-ui/designer-client/package-lock.json +++ b/cds-ui/designer-client/package-lock.json @@ -361,6 +361,8 @@ "dev": true, "optional": true, "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1", "node-pre-gyp": "*" }, "dependencies": { @@ -2998,6 +3000,16 @@ "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", "dev": true }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, "blob": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", @@ -5142,6 +5154,13 @@ "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.2.tgz", "integrity": "sha512-Wz3c3XQ5xroCxd1G8b7yL0Ehkf0TC9oYC6buPFkNnU9EnaPlifeAFCyCh+iewXTyFRcg0a6j3J7FmJsIhlhBdw==" }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, + "optional": true + }, "fileset": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz", @@ -6751,6 +6770,8 @@ "dev": true, "optional": true, "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1", "node-pre-gyp": "*" }, "dependencies": { @@ -8015,6 +8036,13 @@ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" }, + "nan": { + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", + "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==", + "dev": true, + "optional": true + }, "nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", @@ -8060,6 +8088,11 @@ "brace": "^0.11.1" } }, + "ngx-bootstrap": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/ngx-bootstrap/-/ngx-bootstrap-5.6.1.tgz", + "integrity": "sha512-8fDs3VaaWgKpupakPKS0QaUc+1E/JMBGJDxUUODjyIkLtFr1A8vH4cjXiV3AfrPvhK27GH0oyTPyKWKcCjEtVg==" + }, "ngx-file-drop": { "version": "8.0.8", "resolved": "https://registry.npmjs.org/ngx-file-drop/-/ngx-file-drop-8.0.8.tgz", @@ -8068,6 +8101,14 @@ "tslib": "^1.9.0" } }, + "ngx-toastr": { + "version": "11.3.3", + "resolved": "https://registry.npmjs.org/ngx-toastr/-/ngx-toastr-11.3.3.tgz", + "integrity": "sha512-DbLFkSZHsVPuuIIrsY1ziEhdkFUQ0V1yG1N0+1nKXGI5QBVesEDxLUVtntjzxJcWw/uUV+bKApo//tGHHORabQ==", + "requires": { + "tslib": "^1.9.0" + } + }, "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", @@ -11575,6 +11616,8 @@ "dev": true, "optional": true, "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1", "node-pre-gyp": "*" }, "dependencies": { @@ -12405,6 +12448,8 @@ "dev": true, "optional": true, "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1", "node-pre-gyp": "*" }, "dependencies": { diff --git a/cds-ui/designer-client/package.json b/cds-ui/designer-client/package.json index ffad818c0..1e5128111 100644 --- a/cds-ui/designer-client/package.json +++ b/cds-ui/designer-client/package.json @@ -41,7 +41,9 @@ "lodash": "^4.17.15", "ng-sidebar": "^9.1.1", "ng2-ace-editor": "^0.3.9", + "ngx-bootstrap": "^5.6.1", "ngx-file-drop": "^8.0.8", + "ngx-toastr": "^11.3.3", "rxjs": "~6.4.0", "stream": "0.0.2", "tslib": "^1.10.0", diff --git a/cds-ui/designer-client/src/app/app.module.ts b/cds-ui/designer-client/src/app/app.module.ts index d6e9b36df..fd07d34c0 100644 --- a/cds-ui/designer-client/src/app/app.module.ts +++ b/cds-ui/designer-client/src/app/app.module.ts @@ -34,6 +34,8 @@ import {SidebarModule} from 'ng-sidebar'; import {SharedModulesModule} from './modules/shared-modules/shared-modules.module'; import {NgxFileDropModule} from 'ngx-file-drop'; import {ResourceDictionaryModule} from './modules/feature-modules/resource-dictionary/resource-dictionary.module'; +import { ToastrModule } from 'ngx-toastr'; + @NgModule({ declarations: [ @@ -51,7 +53,8 @@ import {ResourceDictionaryModule} from './modules/feature-modules/resource-dicti SharedModulesModule, NgxFileDropModule, ResourceDictionaryModule, - SidebarModule + SidebarModule, + ToastrModule.forRoot() // ToastrModule added ], providers: [ApiService], diff --git a/cds-ui/designer-client/src/app/common/core/pipes/search.pipe.ts b/cds-ui/designer-client/src/app/common/core/pipes/search.pipe.ts new file mode 100644 index 000000000..104fe0090 --- /dev/null +++ b/cds-ui/designer-client/src/app/common/core/pipes/search.pipe.ts @@ -0,0 +1,44 @@ +/* +* ============LICENSE_START======================================================= +* ONAP : CDS +* ================================================================================ +* Copyright (C) 2020 TechMahindra +*================================================================================= +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ============LICENSE_END========================================================= +*/ +import { Pipe, PipeTransform } from '@angular/core'; + +@Pipe({ + name: 'search' +}) + +export class SearchPipe implements PipeTransform { + transform(items: any[], searchText: string): any[] { + if (!items) { + return []; + } + if (!searchText) { + return items; + } + searchText = searchText.toLowerCase(); + return items.filter( it => { + if (it.name) { + return it.name.toLowerCase().includes(searchText); + } else { + return items; + } + }); + } + +} diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/configuration-dashboard/configuration-dashboard.component.html b/cds-ui/designer-client/src/app/modules/feature-modules/packages/configuration-dashboard/configuration-dashboard.component.html index 1ff03b221..6c7e1efc6 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/configuration-dashboard/configuration-dashboard.component.html +++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/configuration-dashboard/configuration-dashboard.component.html @@ -17,13 +17,12 @@ </header> - <div class="container-fluid body-container"> <div class="container"> <div class="creat-action-container"> - <a href="#" class="action-button" (click)="editBluePrint()"> + <a href="#" class="action-button save" (click)="editBluePrint()"> <i class="icon-save-sm" aria-hidden="true"></i> <span>Save</span> </a> @@ -43,13 +42,13 @@ <span>Archive</span> </a> - <a href="#" class="action-button"> + <a class="action-button" + (click)="downloadPackage(viewedPackage.artifactName,viewedPackage.artifactVersion)"> <i class="icon-download" aria-hidden="true"></i> <span>Download</span> </a> - <a href="#" class="action-button delete" - (click)="downloadPackage(viewedPackage.artifactName,viewedPackage.artifactVersion)"> + <a class="action-button delete"> <i class="icon-delete-sm" aria-hidden="true"></i> <span>Delete</span> </a> @@ -61,7 +60,7 @@ <div class="col-9"> <div class="row mb-4"> <div class="col-12 package-name deployed"> - {{viewedPackage.artifactName}}<span>.vLB.CDS</span> + {{viewedPackage.artifactName}} <img src="/assets/img/icon-deploy-inactive.svg" class="deply-status-icon"> <span class="package-version">Version 1.0.2</span> </div> @@ -84,19 +83,19 @@ <ul class="package-contributers"> <li> <button type="button" class="border-fade" data-toggle="tooltip" - data-placement="bottom" title="User name"> + data-placement="bottom" title="User name"> <img src="/assets/img/img-user1.jpeg"> </button> </li> <li> <button type="button" data-toggle="tooltip" data-placement="bottom" - title="User name"> + title="User name"> <img src="/assets/img/img-user2.jpg"> </button> </li> <li> <button type="button" data-toggle="tooltip" data-placement="bottom" - title="User name"> + title="User name"> <img src="/assets/img/img-user3.jpg"> </button> </li> @@ -109,9 +108,11 @@ </div> <div class="col-2 package-view-button pt-3"> <button class="btn btn-sm btn-primary mb-2" (click)="goToDesignerMode()">Designer - Mode</button> + Mode + </button> <button class="btn btn-sm btn-outline-secondary" (click)="deployCurrentPackage()"><i - class="fa fa-play-circle"></i> Deploy</button> + class="fa fa-play-circle"></i> Deploy + </button> </div> </div> @@ -122,17 +123,17 @@ <div class="col"> <div class="nav nav-tabs " id="nav-tab" role="tablist"> <a class="nav-item nav-link active complete" id="nav-metadata-tab" data-toggle="tab" - href="#nav-metadata" role="tab" aria-controls="nav-metadata" aria-selected="true" - autofocus #nameit (focusout)="saveMetaData()">METADATA</a> + href="#nav-metadata" role="tab" aria-controls="nav-metadata" aria-selected="true" + autofocus #nameit (focusout)="saveMetaData()">METADATA</a> <a class="nav-item nav-link" id="nav-template-tab" data-toggle="tab" href="#nav-template" - role="tab" aria-controls="nav-template" aria-selected="false">TEMPLATE & MAPPING</a> + role="tab" aria-controls="nav-template" aria-selected="false">TEMPLATE & MAPPING</a> <a class="nav-item nav-link" id="nav-scripts-tab" data-toggle="tab" href="#nav-scripts" - role="tab" aria-controls="nav-scripts" aria-selected="false">SCRIPTS</a> + role="tab" aria-controls="nav-scripts" aria-selected="false">SCRIPTS</a> <a class="nav-item nav-link" id="nav-imports-tab" data-toggle="tab" href="#nav-imports" - role="tab" aria-controls="nav-imports" aria-selected="false">DEFINITIONS</a> + role="tab" aria-controls="nav-imports" aria-selected="false">DEFINITIONS</a> <a class="nav-item nav-link" id="nav-authentication-tab" data-toggle="tab" - href="#nav-authentication" role="tab" aria-controls="nav-authentication" - aria-selected="false">EXTERNAL SYSTEM AUTHENTICATION PROPERTIES</a> + href="#nav-authentication" role="tab" aria-controls="nav-authentication" + aria-selected="false">EXTERNAL SYSTEM AUTHENTICATION PROPERTIES</a> </div> </div> @@ -141,24 +142,24 @@ <div class="col"> <div class="tab-content" id="nav-tabContent"> <div class="tab-pane fade show active" id="nav-metadata" role="tabpanel" - aria-labelledby="nav-metadata-tab"> + aria-labelledby="nav-metadata-tab"> <app-metadata-tab></app-metadata-tab> </div> <div class="tab-pane fade" id="nav-template" role="tabpanel" - aria-labelledby="nav-template-tab"> + aria-labelledby="nav-template-tab"> <app-template-mapping></app-template-mapping> </div> <div class="tab-pane fade" id="nav-scripts" role="tabpanel" - aria-labelledby="nav-scripts-tab"> + aria-labelledby="nav-scripts-tab"> <app-scripts-tab></app-scripts-tab> </div> <div class="tab-pane fade" id="nav-imports" role="tabpanel" - aria-labelledby="nav-imports-tab"> + aria-labelledby="nav-imports-tab"> <app-imports-tab></app-imports-tab> </div> <div class="tab-pane fade" id="nav-authentication" role="tabpanel" - aria-labelledby="nav-authentication-tab"> + aria-labelledby="nav-authentication-tab"> <div class="card creat-card"> <div class="editor-container"> <app-dsl-definitions-tab></app-dsl-definitions-tab> diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/designer.component.html b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/designer.component.html index bd5b07e45..6e072b18d 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/designer.component.html +++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/designer.component.html @@ -34,7 +34,7 @@ <div class="modal-body"> <div class="row package-info"> <div class="col-12"> - <h3>Test Package<span>.vLB.CDS</span> + <h3>Test Package <span class="package-version">Version 1.0.2</span></h3> </div> <div class="col-12 mb-3"> @@ -110,15 +110,44 @@ <!-- Controller SideBar --> <ng-sidebar [(opened)]="controllerSideBar" [sidebarClass]="'demo-sidebar controllerSidebar container-fluid'" [mode]="'push'" #sidebarLeft> - <div class="row"> - <h1 class="col-12">Actions</h1> - <div class="col-12 text-center p-0"> - <div class="btn-group actionBtns" role="group"> - <button (click)="insertCustomActionIntoBoard()" type="button" class="btn insert-custom">Insert - Custom</button> - <!-- <button type="button" class="btn import-action"><i class="icon-import-blue" aria-hidden="true"></i>Import Action</button> --> + + <nav class="row"> + <!--Nav Tabs--> + <div class="col-12"> + <div class="nav nav-tabs " id="nav-tab" role="tablist"> + <a class="nav-item nav-link active col-6" id="nav-action-tab" data-toggle="tab" + href="#nav-action" role="tab" aria-controls="nav-action" aria-selected="false" + autofocus #nameit >Actions</a> + <a class="nav-item nav-link col-6" id="nav-function-tab" data-toggle="tab" + href="#nav-function" role="tab" aria-controls="nav-function" aria-selected="false">Functions</a> + </div> + </div> + </nav> + + + <div class="row mt-2"> + <div class="col"> + <div class="tab-content" id="nav-tabContent"> + <div class="tab-pane fade show active" id="nav-action" role="tabpanel" + aria-labelledby="nav-action-tab"> + <div class="btn-group actionBtns col-8" role="group"> + <button (click)="insertCustomActionIntoBoard()" type="button" class="btn insert-custom"> + Insert Custom + </button> + <!-- <button type="button" class="btn import-action"><i class="icon-import-blue" aria-hidden="true"></i>Import Action</button> --> + </div> + </div> + <div class="tab-pane fade" id="nav-function" role="tabpanel" + aria-labelledby="nav-function-tab"> + <div class="col-12 text-center p-0"> + <b>Drag and drop function to Action’s box</b> + <div id="palette-paper" class="col-12 componentsList"> </div> + </div> + </div> </div> </div> + </div> + <!-- <div class="col-12 actionsList"> <b>Select from other packages:</b> <div class="actions-scroll"> @@ -153,11 +182,7 @@ </div> </div> --> - <h1 class="col-12">Functions</h1> - <b>Drag and drop function to Action’s box</b> - <div id="palette-paper" class="col-12 componentsList"> - </div> - </div> + </ng-sidebar> <!-- Page content --> diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/creationModes/DesignerCreationMode.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/creationModes/DesignerCreationMode.ts index e1efc3c22..00dcc5dab 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/creationModes/DesignerCreationMode.ts +++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/creationModes/DesignerCreationMode.ts @@ -1,8 +1,8 @@ -import { PackageCreationModes } from './PackageCreationModes'; -import { CBAPackage, Scripts } from '../mapping-models/CBAPacakge.model'; -import { FilesContent } from '../mapping-models/metadata/MetaDataTab.model'; -import { Import, Metadata, VlbDefinition } from '../mapping-models/definitions/VlbDefinition'; -import { PackageCreationUtils } from '../package-creation.utils'; +import {PackageCreationModes} from './PackageCreationModes'; +import {CBAPackage, Scripts} from '../mapping-models/CBAPacakge.model'; +import {FilesContent} from '../mapping-models/metadata/MetaDataTab.model'; +import {Import, Metadata, VlbDefinition} from '../mapping-models/definitions/VlbDefinition'; +import {PackageCreationUtils} from '../package-creation.utils'; export class DesignerCreationMode extends PackageCreationModes { @@ -41,7 +41,7 @@ export class DesignerCreationMode extends PackageCreationModes { FilesContent.putData(key, valueOfFile); }); - const filenameEntry = 'Definitions/blueprint.json'; + const filenameEntry = 'Definitions/' + cbaPackage.metaData.name + '.json'; const vlbDefinition: VlbDefinition = new VlbDefinition(); const metadata: Metadata = new Metadata(); @@ -68,7 +68,7 @@ export class DesignerCreationMode extends PackageCreationModes { vlbDefinition.metadata = metadata; const files: Import[] = []; cbaPackage.definitions.imports.forEach((valueOfFile, key) => { - files.push({ file: key }); + files.push({file: key}); }); console.log(vlbDefinition); vlbDefinition.imports = files; diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/creationModes/PackageCreationModes.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/creationModes/PackageCreationModes.ts index 8ccf0c39e..5b8db6b6d 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/creationModes/PackageCreationModes.ts +++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/creationModes/PackageCreationModes.ts @@ -11,7 +11,7 @@ export abstract class PackageCreationModes { public static setEntryPoint(metaDataTab: MetaDataTabModel) { if (metaDataTab.mode.startsWith(ModeType.Designer)) { - metaDataTab.entryFileName = 'Definitions/blueprint.json'; + metaDataTab.entryFileName = 'Definitions/' + metaDataTab.name + '.json'; } else { // TODO Not implemented metaDataTab.entryFileName = ''; diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/imports-tab/imports-tab.component.html b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/imports-tab/imports-tab.component.html index ac02c50e2..d487de3d1 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/imports-tab/imports-tab.component.html +++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/imports-tab/imports-tab.component.html @@ -36,38 +36,39 @@ <div class="card"> <div class="card-header" [id]="'head-'+mapIndex"> <h5 class="mb-0 d-flex justify-content-between"> - <button class="btn btn-link " data-toggle="collapse" - aria-expanded="false" - (click)="changeDivShow(mapIndex)" > + <button class="btn btn-link " data-toggle="collapse" aria-expanded="false" + (click)="changeDivShow(mapIndex)"> <i class="icon-file-code"></i> {{file.key}} </button> - - <a data-toggle="modal" data-target="#exampleModal" class="accordion-delete"><i - class="icon-delete-sm"></i></a> - - <!-- <a class="accordion-delete" (click)="removeFile(mapIndex)"><i class="icon-delete-sm"></i></a> --> - <!-- Delete Modal --> - <div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" - aria-labelledby="exampleModalLabel" aria-hidden="true"> - <div class="modal-dialog" role="document"> - <div class="modal-content"> - <div class="modal-header"> - <h5 class="modal-title" id="exampleModalLabel">Delete File</h5> - <button type="button" class="close" data-dismiss="modal" aria-label="Close"> - <span aria-hidden="true">×</span> - </button> - </div> - <div class="modal-body"> - <p>Are you sure you want to delete file <span>artifact_types.json</span>?</p> - </div> - <div class="modal-footer"> - <button type="button" class="btn btn-secondary" - data-dismiss="modal">Cancel</button> - <button type="button" class="btn btn-primary">Delete</button> + + <a data-toggle="modal" (click)="initDelete(file)" data-target="#exampleModal" + class="accordion-delete"><i class="icon-delete-sm"></i></a> + + <!-- <a class="accordion-delete" (click)="removeFile(mapIndex)"><i class="icon-delete-sm"></i></a> --> + <!-- Delete Modal --> + <div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" + aria-labelledby="exampleModalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h5 class="modal-title" id="exampleModalLabel">Delete File</h5> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"> + <span aria-hidden="true">×</span> + </button> + </div> + <div class="modal-body"> + <p>Are you sure you want to delete file + <span>{{fileToDelete?.key?.split('/')[1]}}</span>?</p> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-secondary" + data-dismiss="modal">Cancel</button> + <button type="button" data-dismiss="modal" (click)="removeFile()" + class="btn btn-primary">Delete</button> + </div> </div> </div> </div> - </div> </h5> </div> <div [id]="'id-'+mapIndex" class="collapse" [attr.aria-labelledby]="'head-'+mapIndex" @@ -153,7 +154,8 @@ <button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal" (click)="resetTheUploadedFiles()">Cancel </button> - <button type="button" class="btn btn-sm btn-primary" data-dismiss="modal" (click)="setFilesToStore()"> + <button type="button" class="btn btn-sm btn-primary" [disabled]="uploadedFiles?.length<=0" + data-dismiss="modal" (click)="setFilesToStore()"> Import </button> </div> diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/imports-tab/imports-tab.component.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/imports-tab/imports-tab.component.ts index 35c0918de..9858fd580 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/imports-tab/imports-tab.component.ts +++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/imports-tab/imports-tab.component.ts @@ -1,7 +1,7 @@ -import {Component, OnInit} from '@angular/core'; -import {FileSystemFileEntry, NgxFileDropEntry} from 'ngx-file-drop'; -import {PackageCreationStore} from '../package-creation.store'; -import {PackageCreationUtils} from '../package-creation.utils'; +import { Component, OnInit } from '@angular/core'; +import { FileSystemFileEntry, NgxFileDropEntry } from 'ngx-file-drop'; +import { PackageCreationStore } from '../package-creation.store'; +import { PackageCreationUtils } from '../package-creation.utils'; @Component({ @@ -14,7 +14,7 @@ export class ImportsTabComponent implements OnInit { public definitionFiles: Map<string, string> = new Map<string, string>(); public uploadedFiles: FileSystemFileEntry[] = []; private fileNames: Set<string> = new Set(); - + fileToDelete: any = {}; public files: NgxFileDropEntry[] = []; constructor(private packageCreationStore: PackageCreationStore, private packageCreationUtils: PackageCreationUtils) { @@ -40,11 +40,21 @@ export class ImportsTabComponent implements OnInit { } } } - - removeFile(fileIndex: number) { - const filename = 'Definitions/' + this.uploadedFiles[fileIndex].name; + initDelete(file) { + console.log(file); + this.fileToDelete = file; + } + removeFile() { + const filename = this.fileToDelete.key; this.packageCreationStore.removeFileFromDefinition(filename); - this.uploadedFiles.splice(fileIndex, 1); + + for (let i = 0; i < this.uploadedFiles.length; i++) { + console.log(this.uploadedFiles[i]); + if (this.uploadedFiles[i].name === filename) { + this.uploadedFiles.splice(i, 1); + break; + } + } } public fileOver(event) { diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/metadata-tab/metadata-tab.component.html b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/metadata-tab/metadata-tab.component.html index de2b3831d..6622f6700 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/metadata-tab/metadata-tab.component.html +++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/metadata-tab/metadata-tab.component.html @@ -62,7 +62,7 @@ <input type="input" (keyup.enter)="addTag($event)" [(ngModel)]="metaDataTab.tags" placeholder="Ex., vDNS-CDS"> </div> - <div class="model-note-container tag-notes">Seprate tags with comma or space</div> + <div class="model-note-container tag-notes">Use ENTER to add tag</div> <div class="model-note-container tages-container"> <span *ngFor="let tag of tags" class="single-tage">{{tag}} <i (click)="removeTag(tag)" class="fa fa-times-circle"></i> diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/package-creation.component.html b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/package-creation.component.html index 1253dc10b..ee4368711 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/package-creation.component.html +++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/package-creation.component.html @@ -20,7 +20,7 @@ <div class="container-fluid body-container"> <div class="container"> <div class="creat-action-container"> - <a href="#" class="action-button" (click)="saveBluePrint()"> + <a href="#" class="action-button save" (click)="saveBluePrint()"> <i class="icon-save-sm" aria-hidden="true"></i> <span>Save</span> </a> diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/package-creation.store.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/package-creation.store.ts index 0808223cd..8302697fe 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/package-creation.store.ts +++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/package-creation.store.ts @@ -84,6 +84,10 @@ export class PackageCreationStore extends Store<CBAPackage> { this.state.scripts.files.delete(name); } + fileExist(key: string) { + return this.state.templates.files.has(key); + } + removeFileFromDefinition(filename) { this.state.definitions.imports.delete(filename); } diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/scripts-tab/scripts-tab.component.html b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/scripts-tab/scripts-tab.component.html index 79c444061..159f7aec4 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/scripts-tab/scripts-tab.component.html +++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/scripts-tab/scripts-tab.component.html @@ -20,12 +20,12 @@ <div class="card"> <div [id]="'head-script-'+mapIndex" class="card-header"> <h5 class="mb-0 d-flex justify-content-between"> - <button (click)="changeDivShow(mapIndex)" - aria-expanded="false" class="btn btn-link collapsed" data-toggle="collapse"> + <button (click)="changeDivShow(mapIndex)" aria-expanded="false" class="btn btn-link collapsed" + data-toggle="collapse"> <i class="icon-file-code"></i> {{file.key}} </button> - <a data-toggle="modal" data-target="#exampleModal" class="accordion-delete"><i - class="icon-delete-sm"></i></a> + <a data-toggle="modal" (click)="initDelete(file)" data-target="#exampleModal" + class="accordion-delete"><i class="icon-delete-sm"></i></a> <!-- <a (click)="removeFile(file.key,mapIndex)" data-toggle="modal" data-target="#exampleModal" class="accordion-delete"><i class="icon-delete-sm"></i></a> --> <!-- Delete Modal --> @@ -40,12 +40,14 @@ </button> </div> <div class="modal-body"> - <p>Are you sure you want to delete script file <span>ConfigDeploy.py</span>?</p> + <p>Are you sure you want to delete script file + <span>{{fileToDelete?.key?.split('/')[2]}}</span>?</p> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button> - <button type="button" class="btn btn-primary">Delete</button> + <button type="button" (click)="removeFile(fileToDelete?.key,0)" + data-dismiss="modal" class="btn btn-primary">Delete</button> </div> </div> </div> @@ -114,10 +116,11 @@ <button (click)="resetTheUploadedFiles()" class="btn btn-sm btn-secondary" data-dismiss="modal" type="button">Cancel </button> - <button (click)="setFilesToStore()" class="btn btn-sm btn-primary" data-dismiss="modal" type="button"> + <button (click)="setFilesToStore()" [disabled]="uploadedFiles?.length<=0" class="btn btn-sm btn-primary" + data-dismiss="modal" type="button"> Import </button> </div> </div> </div> -</div> +</div>
\ No newline at end of file diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/scripts-tab/scripts-tab.component.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/scripts-tab/scripts-tab.component.ts index efe28e9a4..a85ccf146 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/scripts-tab/scripts-tab.component.ts +++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/scripts-tab/scripts-tab.component.ts @@ -3,6 +3,7 @@ import { FileSystemFileEntry, NgxFileDropEntry } from 'ngx-file-drop'; import { PackageCreationStore } from '../package-creation.store'; import 'ace-builds/src-noconflict/ace'; import 'ace-builds/webpack-resolver'; +declare var $: any; @Component({ selector: 'app-scripts-tab', @@ -15,6 +16,7 @@ export class ScriptsTabComponent implements OnInit { public uploadedFiles: FileSystemFileEntry[] = []; public files: NgxFileDropEntry[] = []; private fileNames: Set<string> = new Set(); + fileToDelete: any = {}; constructor( private packageCreationStore: PackageCreationStore, @@ -42,7 +44,9 @@ export class ScriptsTabComponent implements OnInit { } } } - + initDelete(file) { + this.fileToDelete = file; + } removeFile(filePath: string, FileIndex: number) { const filename = filePath.split('/')[2] || ''; // const filename = 'Scripts/' + this.getFileType(this.uploadedFiles[fileIndex].name) + '/' + this.uploadedFiles[fileIndex].name; diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-creation/templ-mapp-creation.component.css b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-creation/templ-mapp-creation.component.css index e69de29bb..7273b9c27 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-creation/templ-mapp-creation.component.css +++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-creation/templ-mapp-creation.component.css @@ -0,0 +1,4 @@ +.accordian-title { + color: #a09e9e; + font-size: .9em; +}
\ No newline at end of file diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-creation/templ-mapp-creation.component.html b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-creation/templ-mapp-creation.component.html index a33087461..e6149c883 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-creation/templ-mapp-creation.component.html +++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-creation/templ-mapp-creation.component.html @@ -12,13 +12,13 @@ </div> <div class="template-mapping-accordion"> - <div id="accordion"> + <div class="accordion" id="accordion"> <div class="card"> <div class="card-header" id="headingOne"> <h5 class="mb-0 d-flex justify-content-between"> <button class="btn btn-link" data-toggle="collapse" data-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne"> - 1. Create Template + 1. Template <span class="accordian-title">{{currentTemplate?.fileName?.split('/')[1]}}</span> </button> </h5> @@ -58,7 +58,7 @@ <a href="#" data-toggle="modal" (click)="allowedExt=[getFileExtension()]" data-target="#templateModal"><b>Import File</b></a></div> - <div class="editor-container"> + <div class="editor-container mb-4"> <app-source-editor (textChange)="textChanges($event,templateInfo.fileName)" [(text)]="templateFileContent"></app-source-editor> </div> @@ -70,7 +70,8 @@ <h5 class="mb-0"> <button class="btn btn-link collapsed" data-toggle="collapse" data-target="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo"> - 2. Manage Mapping + 2. Manage Mapping <span + class="accordian-title">{{currentMapping?.fileName?.split('/')[1]}}</span> </button> </h5> </div> @@ -87,7 +88,7 @@ class="mapping-source-load"> <i class="icon-upload-attributes"></i> <br /> - <div>Upload attribute list</div> + <div>Upload Attributes List</div> <div class="source-load-note">(Should be comma delimited file)</div> </a> <!-- <a href="#" class="mapping-source-load"> @@ -119,8 +120,10 @@ <tbody> <tr *ngFor="let dict of resourceDictionaryRes"> <td> - <img *ngIf="dict.definition?.property?.required" src="/assets/img/icon-required-no.svg"> - <img *ngIf="!dict.definition?.property?.required" src="/assets/img/icon-required-yes.svg"> + <img *ngIf="dict.definition?.property?.required" + src="/assets/img/icon-required-yes.svg"> + <img *ngIf="!dict.definition?.property?.required" + src="/assets/img/icon-required-no.svg"> </td> <td>{{ dict.name }}</td> <td>{{ dict.name }}</td> @@ -166,8 +169,10 @@ <tbody> <tr *ngFor="let dict of mappingRes"> <td> - <i *ngIf="dict.definition?.property?.required" class="fa fa-check-square mx-2"></i> - <i *ngIf="!dict.definition?.property?.required" class="fa fa-square mx-2"></i> + <img *ngIf="dict.definition?.property?.required" + src="/assets/img/icon-required-yes.svg"> + <img *ngIf="!dict.definition?.property?.required" + src="/assets/img/icon-required-no.svg"> </td> <td>{{ dict['name'] }}</td> <td>{{ dict['name'] }}</td> @@ -194,8 +199,8 @@ </div> <div class="template-mapping-action"> - <button class="btn btn-sm btn-outline-secondary">Cancel</button> - <button (click)="saveToStore()" class="btn btn-sm btn-primary">Submit</button> + <button (click)="cancel()" class="btn btn-outline-secondary">Cancel</button> + <button (click)="saveToStore()" class="btn btn-primary">Submit</button> </div> </div> </div> @@ -212,8 +217,8 @@ </button> </div> <div class="modal-body"> - <ngx-file-drop [multiple]="false" [accept]="allowedExt" dropZoneLabel="Drop files here" (onFileDrop)="dropped($event)" - (onFileOver)="fileOver($event)" (onFileLeave)="fileLeave($event)"> + <ngx-file-drop [multiple]="false" [accept]="allowedExt" dropZoneLabel="Drop files here" + (onFileDrop)="dropped($event)" (onFileOver)="fileOver($event)" (onFileLeave)="fileLeave($event)"> <ng-template ngx-file-drop-content-tmp let-openFileSelector="openFileSelector"> <div class="folder-upload"> <img src="assets/img/folder-upload.svg" /> diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-creation/templ-mapp-creation.component.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-creation/templ-mapp-creation.component.ts index 628d963ce..7d4705d69 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-creation/templ-mapp-creation.component.ts +++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-creation/templ-mapp-creation.component.ts @@ -7,7 +7,8 @@ import { ResourceDictionary } from '../../mapping-models/ResourceDictionary.mode import { DataTableDirective } from 'angular-datatables'; import { Mapping, MappingAdapter } from '../../mapping-models/mappingAdapter.model'; import { PackageCreationUtils } from '../../package-creation.utils'; -import { JsonConvert } from 'json2typescript'; +import { JsonConvert, Any } from 'json2typescript'; +import { ToastrService } from 'ngx-toastr'; @Component({ selector: 'app-templ-mapp-creation', @@ -40,13 +41,16 @@ export class TemplMappCreationComponent implements OnInit, OnDestroy { dependancies = new Map<string, Array<string>>(); dependanciesSource = new Map<string, string>(); mappingRes = []; + currentTemplate: any; + currentMapping: any; constructor( private packageCreationStore: PackageCreationStore, private templateStore: TemplateStore, - private packageCreationUtils: PackageCreationUtils + private packageCreationUtils: PackageCreationUtils, + private toastr: ToastrService ) { } @@ -56,13 +60,18 @@ export class TemplMappCreationComponent implements OnInit, OnDestroy { console.log(templateInfo); this.templateInfo = templateInfo; this.fileName = templateInfo.fileName.split('/')[1]; + if (this.fileName) { + this.fileName = this.fileName.split('-')[0]; + } if (templateInfo.type === 'mapping') { this.mappingRes = templateInfo.mapping; + this.currentMapping = templateInfo; this.resourceDictionaryRes = []; this.resTableDtTrigger.next(); } else { this.templateFileContent = templateInfo.fileContent; + this.currentTemplate = templateInfo; } }); @@ -224,28 +233,44 @@ export class TemplMappCreationComponent implements OnInit, OnDestroy { } return map.key; } + cancel() { + this.fileName = ''; + this.templateFileContent = ''; + this.resourceDictionaryRes = []; + this.mappingRes = []; + this.currentMapping = {}; + this.currentTemplate = {}; + } saveToStore() { - console.log(this.dependancies); - console.log(this.dependanciesSource); if (this.fileName) { - // Save Mapping to Store - if (this.resourceDictionaryRes && this.resourceDictionaryRes.length > 0) { - const mapArray = this.convertDictionaryToMap(this.resourceDictionaryRes); - this.packageCreationStore.addMapping('Templates/' + this.fileName + '-mapping.json', - this.packageCreationUtils.transformToJson(this.jsonConvert.serialize(mapArray))); - this.resourceDictionaryRes = []; - } - // Save Template to store - if (this.templateFileContent) { - this.packageCreationStore.addTemplate('Templates/' + this.fileName + '-template' + this.getFileExtension(), - this.templateFileContent); - this.templateFileContent = ''; + // check file duplication + if (!(this.packageCreationStore.fileExist('Templates/' + this.fileName + '-mapping.json') + || this.packageCreationStore.fileExist('Templates/' + this.fileName + '-template' + this.getFileExtension()))) { + // Save Mapping to Store + if (this.resourceDictionaryRes && this.resourceDictionaryRes.length > 0) { + const mapArray = this.convertDictionaryToMap(this.resourceDictionaryRes); + this.packageCreationStore.addMapping('Templates/' + this.fileName + '-mapping.json', + this.packageCreationUtils.transformToJson(this.jsonConvert.serialize(mapArray))); + this.resourceDictionaryRes = []; + } + // Save Template to store + if (this.templateFileContent) { + this.packageCreationStore.addTemplate('Templates/' + this.fileName + '-template' + this.getFileExtension(), + this.templateFileContent); + this.templateFileContent = ''; + } + this.fileName = ''; + this.toastr.success('File is created', 'success'); + } else { + console.log('this file already exist'); + this.toastr.error('File name already exist', 'Error'); } } else { - + this.toastr.error('Add the file name', 'Error'); } } + selectSource(dict, e) { const source = e.target.value; let keyDepend = null; diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-listing/templ-mapp-listing.component.html b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-listing/templ-mapp-listing.component.html index f5e683f28..a47963a72 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-listing/templ-mapp-listing.component.html +++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-listing/templ-mapp-listing.component.html @@ -4,7 +4,7 @@ <div class="template-mapping-accordion"> - <div id="accordion"> + <div class="accordion" id="listAccordion"> <div class="card"> <div class="card-header" id="headingThree"> <h5 class="mb-0 d-flex justify-content-between"> @@ -16,12 +16,12 @@ </h5> </div> - <div id="collapseThree" class="collapse show" aria-labelledby="headingThree" data-parent="#accordion"> + <div id="collapseThree" class="collapse show" aria-labelledby="headingThree" data-parent="#listAccordion"> <div class="card-body max-height-list"> <div class="row"> <!-- <div class="col-4" style="color:white" *ngFor="let file of templates.files | keyvalue; let mapIndex = index">--> <div class="col-4" *ngFor="let file of getKeys(templateAndMappingMap)"> - <a (click)="setSourceCodeEditor(file)" class="template-mapping-list active">{{file}} + <a (click)="setSourceCodeEditor(file)" class="template-mapping-list" [ngClass]="{'active':currentFile == file}">{{file}} <span *ngIf="getValue(file).isMapping">Mapping</span> <span *ngIf="getValue(file).isTemplate">Template</span> </a> diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-listing/templ-mapp-listing.component.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-listing/templ-mapp-listing.component.ts index 372fbca03..448899019 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-listing/templ-mapp-listing.component.ts +++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-listing/templ-mapp-listing.component.ts @@ -17,6 +17,7 @@ export class TemplMappListingComponent implements OnInit { private templates: Template; private mapping: Mapping; isCreate = true; + currentFile: string; constructor( private packageCreationStore: PackageCreationStore, @@ -72,6 +73,7 @@ export class TemplMappListingComponent implements OnInit { } setSourceCodeEditor(key: string) { + this.currentFile = key; const templateKey = 'Templates/' + key + '-template.vtl'; this.packageCreationStore.state$.subscribe(cba => { console.log('cba ------'); diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/packages-dashboard/package-list/package-list.component.html b/cds-ui/designer-client/src/app/modules/feature-modules/packages/packages-dashboard/package-list/package-list.component.html index ed67dff40..9db3ce110 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/packages-dashboard/package-list/package-list.component.html +++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/packages-dashboard/package-list/package-list.component.html @@ -8,10 +8,12 @@ <div class="card-footer row"> <div class="col text-center"> <a routerLink="/packages/createPackage" role="button" aria-pressed="true" - class="btn-create-package float"><i class="icon-create-white" aria-hidden="true"></i>Create Package + class="btn-create-package float"><i class="icon-create-white" aria-hidden="true"></i>Create + Package </a> - <br/> - <a href="#" role="button" aria-pressed="true" class="btn-import-package float mb-3"><i class="icon-import-blue" aria-hidden="true"></i>Import Package + <br /> + <a href="#" role="button" aria-pressed="true" class="btn-import-package float mb-3"><i + class="icon-import-blue" aria-hidden="true"></i>Import Package </a> </div> </div> @@ -19,102 +21,105 @@ </div> <div class="col-lg-3 col-md-6 d-flex" *ngFor="let bluePrint of viewedPackages"> <!--Card 1--> - <div class="card"> - <div class="card-body"> - <div class="row"> - <div class="col-9 pr-0"> - <a class="card-title" [routerLink]="['/packages/package', bluePrint.id]" - (click)="testDispatch(bluePrint)"> - <!-- <img class="icon-deployed" src="/assets/img/icon-deploy.svg"> --> - {{bluePrint.artifactName}}<span>.vLB.CDS</span> - <span class="package-version">Version 1.0.2</span> - </a> - - </div> - <div class="col-3"> + <div class="card"> + <div class="card-body"> + <div class="row"> + <div class="col-10 pr-0"> + <a class="card-title" [routerLink]="['/packages/package', bluePrint.id]" + (click)="testDispatch(bluePrint)"> + <!-- <img class="icon-deployed" src="/assets/img/icon-deploy.svg"> --> + <p class="packageName" tooltip="{{bluePrint.artifactName}}" placement="bottom"> + {{bluePrint.artifactName}}</p> + <span class="package-version">{{bluePrint.artifactVersion}}</span> + </a> - <div class="dropdown"> - <input class="dropdown-toggle" type="text"> - <div class="dropdown-text"> - <!-- <img src="/assets/img/icon-menuDots.svg" title="Actions"> --> - <i class="icon-menuDots" aria-hidden="true"></i> - </div> - <ul class="dropdown-content"> - <li class="action-clone"> - <a href="#"> - <i class="icon-clone-sm" aria-hidden="true"></i> - Clone - </a> - </li> - <li class="action-archive"> - <a href="#"> - <i class="icon-archive-sm" aria-hidden="true"></i> - Archive - </a> - </li> - <li class="action-archive"> - <a href="#"> - <i class="icon-download" aria-hidden="true"></i> - Download - </a> - </li> - <li class="action-delete"> - <a href="#"> - <i class="icon-delete-sm" aria-hidden="true"></i> - Delete - </a> - </li> - </ul> - </div> - - </div> </div> - <div class="row"> - <div class="col"> - <p class="mb-0 mt-1">Last modified {{ bluePrint.createdDate | date:'short' }} - </p> - <p class="mb-2">By {{bluePrint.updatedBy}}</p> - <p class="package-desc tooltip-bottom" data-tooltip="DESCRIPTION: - The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from de Finibus Bonorum et Malorum by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham.">Description text quisquam est dolorem, velit...</p> - - <ul class="package-contributers"> - <li> - <button type="button" class="border-fade" data-toggle="tooltip" - data-placement="bottom" title="User name"> - <img src="/assets/img/img-user1.jpeg"> - </button> + <div class="col-2"> + <div class="dropdown"> + <input class="dropdown-toggle" type="text"> + <div class="dropdown-text"> + <!-- <img src="/assets/img/icon-menuDots.svg" title="Actions"> --> + <i class="icon-menuDots" aria-hidden="true"></i> + </div> + <ul class="dropdown-content"> + <li class="action-clone"> + <a href="#"> + <i class="icon-clone-sm" aria-hidden="true"></i> + Clone + </a> </li> - <li> - <button type="button" data-toggle="tooltip" data-placement="bottom" - title="User name"> - <img src="/assets/img/img-user2.jpg"> - </button> + <li class="action-archive"> + <a href="#"> + <i class="icon-archive-sm" aria-hidden="true"></i> + Archive + </a> </li> - <li> - <button type="button" data-toggle="tooltip" data-placement="bottom" - title="User name"> - <img src="/assets/img/img-user3.jpg"> - </button> + <li class="action-archive"> + <a (click)="downloadPackage(bluePrint.artifactName,bluePrint.artifactVersion)"> + <i class="icon-download" aria-hidden="true"></i> + Download + </a> </li> - <li> - <a href="">5 contributors</a> + <li class="action-delete"> + <a href="#"> + <i class="icon-delete-sm" aria-hidden="true"></i> + Delete + </a> </li> </ul> </div> + </div> - <div class="card-footer"> - <div class="row"> - <div class="col"> - <button type="button" class="btn btn-card-topology"><i class="icon-btn-card-topology" aria-hidden="true"></i>Designer Mode + </div> + <div class="row"> + <div class="col"> + <p class="mb-0 mt-1">Last modified {{ bluePrint.createdDate | date:'short' }} + </p> +<!-- <p class="mb-2">By {{bluePrint.updatedBy}}</p>--> + <p class="package-desc" [delay]="300" + tooltip="DESCRIPTION: + The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from de Finibus Bonorum et Malorum by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham." + placement="auto">Description text quisquam est dolorem, velitThe standard chunk of Lorem + Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and + 1.10.33 from de Finibus Bonorum et</p> + <ul class="package-contributers"> + <li> + <button type="button" class="border-fade" data-toggle="tooltip" data-placement="bottom" + title="User name"> + <img src="/assets/img/img-user1.jpeg"> </button> - </div> - <div class="col"> - <button type="button" (click)="view(bluePrint.id)" class="btn btn-card-config"><i class="icon-btn-card-config" aria-hidden="true"></i>Configuration</button> - </div> + </li> + <li> + <button type="button" data-toggle="tooltip" data-placement="bottom" title="User name"> + <img src="/assets/img/img-user2.jpg"> + </button> + </li> + <li> + <button type="button" data-toggle="tooltip" data-placement="bottom" title="User name"> + <img src="/assets/img/img-user3.jpg"> + </button> + </li> + <li> + <a href="">5 contributors</a> + </li> + </ul> + </div> + </div> + <div class="card-footer"> + <div class="row"> + <div class="col"> + <button type="button" class="btn btn-card-topology"><i class="icon-btn-card-topology" + aria-hidden="true"></i>Designer Mode + </button> + </div> + <div class="col"> + <button type="button" (click)="view(bluePrint.id)" class="btn btn-card-config"><i + class="icon-btn-card-config" aria-hidden="true"></i>Configuration</button> </div> </div> </div> - </div> + + </div> </div> -</div>
\ No newline at end of file +</div> diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/packages-dashboard/package-list/package-list.component.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/packages-dashboard/package-list/package-list.component.ts index b7bc05ff9..352f33b91 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/packages-dashboard/package-list/package-list.component.ts +++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/packages-dashboard/package-list/package-list.component.ts @@ -1,7 +1,9 @@ -import { Component, OnInit } from '@angular/core'; -import { BlueprintModel } from '../../model/BluePrint.model'; -import { PackagesStore } from '../../packages.store'; -import { Router } from '@angular/router'; +import {Component, OnInit} from '@angular/core'; +import {BlueprintModel} from '../../model/BluePrint.model'; +import {PackagesStore} from '../../packages.store'; +import {Router} from '@angular/router'; +import {ConfigurationDashboardService} from '../../configuration-dashboard/configuration-dashboard.service'; +import {saveAs} from 'file-saver'; @Component({ selector: 'app-packages-list', @@ -13,7 +15,8 @@ export class PackageListComponent implements OnInit { viewedPackages: BlueprintModel[] = []; - constructor(private packagesStore: PackagesStore, private router: Router) { + constructor(private packagesStore: PackagesStore, private router: Router + , private configurationDashboardService: ConfigurationDashboardService) { console.log('PackageListComponent'); this.packagesStore.state$.subscribe(state => { console.log(state); @@ -30,7 +33,15 @@ export class PackageListComponent implements OnInit { view(id) { this.router.navigate(['/packages/package', id]); } + testDispatch(bluePrint: BlueprintModel) { console.log(bluePrint.id); } + + downloadPackage(artifactName: string, artifactVersion: string) { + this.configurationDashboardService.downloadResource(artifactName + '/' + artifactVersion).subscribe(response => { + const blob = new Blob([response], {type: 'application/octet-stream'}); + saveAs(blob, artifactName + '-' + artifactVersion + '-CBA.zip'); + }); + } } diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/packages.store.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/packages.store.ts index b1f730f06..863adfbd7 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/packages.store.ts +++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/packages.store.ts @@ -31,7 +31,7 @@ import {Observable, of} from 'rxjs'; }) export class PackagesStore extends Store<PackagesDashboardState> { // TDOD fixed for now as there is no requirement to change it from UI - public pageSize = 5; + public pageSize = 15; private bluePrintContent: BluePrintPage = new BluePrintPage(); constructor(private packagesServiceList: PackagesApiService) { diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/model/definition.model.ts b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/model/definition.model.ts index 96d188a54..7911c028c 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/model/definition.model.ts +++ b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/model/definition.model.ts @@ -21,10 +21,6 @@ import { Sources } from './sources.model'; export class Definition { - tag: string; - name: string; - property: string; - updatedBy: string; sources: Sources[]; } diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/model/metaData.model.ts b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/model/metaData.model.ts index e4b9be75f..609b066e2 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/model/metaData.model.ts +++ b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/model/metaData.model.ts @@ -26,4 +26,7 @@ export class MetaData { public entrySchema: string; public updatedBy: string; public createdDate: string; + public libraryInstance: string; + public required: string; + public derivedFrom: string; } diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/model/resource-dictionary.model.ts b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/model/resource-dictionary.model.ts new file mode 100644 index 000000000..85686551e --- /dev/null +++ b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/model/resource-dictionary.model.ts @@ -0,0 +1,26 @@ +/* +* ============LICENSE_START======================================================= +* ONAP : CDS +* ================================================================================ +* Copyright (C) 2020 TechMahindra +*================================================================================= +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ============LICENSE_END========================================================= +*/ +import { MetaData } from './metaData.model'; +import { Definition } from './definition.model'; + +export class ResourceDictionary { + public metaData: MetaData; + public definition: Definition; +} diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/model/sources.model.ts b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/model/sources.model.ts index 4074e5138..35d3f77c3 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/model/sources.model.ts +++ b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/model/sources.model.ts @@ -17,8 +17,6 @@ * limitations under the License. * ============LICENSE_END========================================================= */ - export class Sources { sources: []; - } diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/dictionary-creation.service.spec.ts b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/dictionary-creation.service.spec.ts new file mode 100644 index 000000000..896c7caf0 --- /dev/null +++ b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/dictionary-creation.service.spec.ts @@ -0,0 +1,31 @@ +/* +* ============LICENSE_START======================================================= +* ONAP : CDS +* ================================================================================ +* Copyright (C) 2020 TechMahindra +*================================================================================= +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ============LICENSE_END========================================================= +*/ +import { TestBed } from '@angular/core/testing'; + +import { DictionaryCreationService } from './dictionary-creation.service'; + +describe('DictionaryCreationService', () => { + beforeEach(() => TestBed.configureTestingModule({})); + + it('should be created', () => { + const service: DictionaryCreationService = TestBed.get(DictionaryCreationService); + expect(service).toBeTruthy(); + }); +}); diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/dictionary-creation.service.ts b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/dictionary-creation.service.ts new file mode 100644 index 000000000..df90e6cd1 --- /dev/null +++ b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/dictionary-creation.service.ts @@ -0,0 +1,37 @@ +/* +* ============LICENSE_START======================================================= +* ONAP : CDS +* ================================================================================ +* Copyright (C) 2020 TechMahindra +*================================================================================= +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ============LICENSE_END========================================================= +*/ +import { Injectable } from '@angular/core'; +import { ResourceDictionaryURLs } from 'src/app/common/constants/app-constants'; +import { Observable } from 'rxjs'; +import { Sources } from '../model/sources.model'; +import { ApiService } from 'src/app/common/core/services/api.service'; + +@Injectable({ + providedIn: 'root' +}) +export class DictionaryCreationService { + + constructor(private api: ApiService) { } + + getSources() { + return this.api.get(ResourceDictionaryURLs.getSources); +} + +} diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/dictionary-creation.store.ts b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/dictionary-creation.store.ts new file mode 100644 index 000000000..20cec7448 --- /dev/null +++ b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/dictionary-creation.store.ts @@ -0,0 +1,53 @@ +/* +* ============LICENSE_START======================================================= +* ONAP : CDS +* ================================================================================ +* Copyright (C) 2020 TechMahindra +*================================================================================= +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ============LICENSE_END========================================================= +*/ +import { Injectable } from '@angular/core'; +import { Store } from 'src/app/common/core/stores/Store'; +import { ResourceDictionary } from '../model/resource-dictionary.model'; +import { DictionaryCreationService } from './dictionary-creation.service'; +import { MetaData } from '../model/metaData.model'; +import { Sources } from '../model/sources.model'; +import { SourcesStore } from './sources-template/sources.store'; + +@Injectable({ + providedIn: 'root' +}) +export class DictionaryCreationStore extends Store<ResourceDictionary> { + constructor(private dictionaryCreationService: DictionaryCreationService, private sourcesStore: SourcesStore) { + super(new ResourceDictionary()); + } + + changeMetaData(metaDataObject: MetaData) { + console.log(metaDataObject); + this.setState({ + ...this.state, + metaData: metaDataObject + }); + } + + getSources() { + this.sourcesStore.state$.subscribe(data => { + console.log(data); + }); + } + + SaveResourceDictionary(resourceDictionary: ResourceDictionary) { + console.log(this.setState); + } +} diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/dictionary-editor/dictionary-editor.component.css b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/dictionary-editor/dictionary-editor.component.css new file mode 100644 index 000000000..f263c0086 --- /dev/null +++ b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/dictionary-editor/dictionary-editor.component.css @@ -0,0 +1,19 @@ +/* +* ============LICENSE_START======================================================= +* ONAP : CDS +* ================================================================================ +* Copyright (C) 2020 TechMahindra +*================================================================================= +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ============LICENSE_END========================================================= +*/
\ No newline at end of file diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/dictionary-editor/dictionary-editor.component.html b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/dictionary-editor/dictionary-editor.component.html new file mode 100644 index 000000000..93d7df7d1 --- /dev/null +++ b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/dictionary-editor/dictionary-editor.component.html @@ -0,0 +1,22 @@ +<!--/* +* ============LICENSE_START======================================================= +* ONAP : CDS +* ================================================================================ +* Copyright (C) 2020 TechMahindra +*================================================================================= +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ============LICENSE_END========================================================= +*/--> +<ace-editor [(text)]="text" [mode]="'javascript'" [autoUpdateContent]="true" +[durationBeforeCallback]="1000" (textChanged)="textChanged($event)" [theme]="'tomorrow_night_bright'" #editor style="height:500px;"> +</ace-editor> diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/dictionary-editor/dictionary-editor.component.spec.ts b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/dictionary-editor/dictionary-editor.component.spec.ts new file mode 100644 index 000000000..09dcdbd37 --- /dev/null +++ b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/dictionary-editor/dictionary-editor.component.spec.ts @@ -0,0 +1,44 @@ +/* +* ============LICENSE_START======================================================= +* ONAP : CDS +* ================================================================================ +* Copyright (C) 2020 TechMahindra +*================================================================================= +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ============LICENSE_END========================================================= +*/ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DictionaryEditorComponent } from './dictionary-editor.component'; + +describe('DictionaryEditorComponent', () => { + let component: DictionaryEditorComponent; + let fixture: ComponentFixture<DictionaryEditorComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ DictionaryEditorComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(DictionaryEditorComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/dictionary-editor/dictionary-editor.component.ts b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/dictionary-editor/dictionary-editor.component.ts new file mode 100644 index 000000000..92b27c24c --- /dev/null +++ b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/dictionary-editor/dictionary-editor.component.ts @@ -0,0 +1,38 @@ +/* +* ============LICENSE_START======================================================= +* ONAP : CDS +* ================================================================================ +* Copyright (C) 2020 TechMahindra +*================================================================================= +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ============LICENSE_END========================================================= +*/ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'app-dictionary-editor', + templateUrl: './dictionary-editor.component.html', + styleUrls: ['./dictionary-editor.component.css'] +}) +export class DictionaryEditorComponent implements OnInit { + constructor() { + } + + ngOnInit() { + } + + textChanged(event) { + console.log(event); + } +} + diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/dictionary-metadata/dictionary-metadata.component.css b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/dictionary-metadata/dictionary-metadata.component.css new file mode 100644 index 000000000..f263c0086 --- /dev/null +++ b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/dictionary-metadata/dictionary-metadata.component.css @@ -0,0 +1,19 @@ +/* +* ============LICENSE_START======================================================= +* ONAP : CDS +* ================================================================================ +* Copyright (C) 2020 TechMahindra +*================================================================================= +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ============LICENSE_END========================================================= +*/
\ No newline at end of file diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/dictionary-metadata/dictionary-metadata.component.html b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/dictionary-metadata/dictionary-metadata.component.html new file mode 100644 index 000000000..bea6081c0 --- /dev/null +++ b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/dictionary-metadata/dictionary-metadata.component.html @@ -0,0 +1,91 @@ +<!--/* +* ============LICENSE_START======================================================= +* ONAP : CDS +* ================================================================================ +* Copyright (C) 2020 TechMahindra +*================================================================================= +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ============LICENSE_END========================================================= +*/--> +<div class="card creat-card col-11"> + <div class="single-line-model"> + <label class="label-name">Name</label> + <div class="label-input"> + <input type="input" [(ngModel)]="metaDataTab.name" + placeholder="Topology name.vLB.CDS"> + </div> + <!-- <div class="model-note-container error-message"> + Package name already exists with this version. Please enter a different name or enter different version + number. + </div> --> + </div> + + <!-- <div class="single-line-model"> + <label class="label-name">Version <span>*</span></label> + <div class="label-input"> + <input type="input" [readOnly]="!packageNameAndVersionEnables" [(ngModel)]="metaDataTab.version" + (input)="validatePackageNameAndVersion()" placeholder="Example: 1.0.0"> + </div> + <div class="model-note-container error-message">{{errorMessage}}</div> + </div> --> + <div class="single-line-model"> + <label class="label-name">Entry Schema</label> + <div class="label-input"> + <input type="input" [(ngModel)]="metaDataTab.entrySchema" placeholder="Entry Schema"> + </div> + </div> + <div class="single-line-model"> + <label class="label-name">Data Type</label> + <div class="label-input"> + <input type="input" [(ngModel)]="metaDataTab.dataType" placeholder="Data Type"> + </div> + </div> + <div class="single-line-model"> + <label class="label-name">Description</label> + <div class="label-input"> + <input type="input" [(ngModel)]="metaDataTab.description" placeholder="Descripe the package"> + </div> + </div> + <div class="single-line-model"> + <label class="label-name">Required</label> + <div class="label-input"> + <input type="input" [(ngModel)]="metaDataTab.updatedBy" placeholder="required"> + </div> + </div> + <div class="single-line-model"> + <label class="label-name">Library Instance</label> + <div class="label-input"> + <input type="input" [(ngModel)]="metaDataTab.libraryInstance" placeholder="Library Instance"> + </div> + </div> + <div class="single-line-model"> + <label class="label-name">Derived From</label> + <div class="label-input"> + <input type="input" [(ngModel)]="metaDataTab.derivedFrom" placeholder="Derived From"> + </div> + </div> + + <div class="single-line-model"> + <label class="label-name">Tags</label> + <div class="label-input"> + <input type="input" (keyup.enter)="addTag($event)" [(ngModel)]="metaDataTab.tags" + placeholder="Ex., vDNS-CDS"> + + </div> + <div class="model-note-container tag-notes">Seprate tags with comma or space</div> + <div class="model-note-container tages-container"> + <span *ngFor="let tag of tags" class="single-tage">{{tag}} <i (click)="removeTag(tag)" + class="fa fa-times-circle"></i></span> + </div> + </div> +</div> diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/dictionary-metadata/dictionary-metadata.component.spec.ts b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/dictionary-metadata/dictionary-metadata.component.spec.ts new file mode 100644 index 000000000..ce9335ff9 --- /dev/null +++ b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/dictionary-metadata/dictionary-metadata.component.spec.ts @@ -0,0 +1,44 @@ +/* +* ============LICENSE_START======================================================= +* ONAP : CDS +* ================================================================================ +* Copyright (C) 2020 TechMahindra +*================================================================================= +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ============LICENSE_END========================================================= +*/ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DictionaryMetadataComponent } from './dictionary-metadata.component'; + +describe('DictionaryMetadataComponent', () => { + let component: DictionaryMetadataComponent; + let fixture: ComponentFixture<DictionaryMetadataComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ DictionaryMetadataComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(DictionaryMetadataComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/dictionary-metadata/dictionary-metadata.component.ts b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/dictionary-metadata/dictionary-metadata.component.ts new file mode 100644 index 000000000..d5c4a109b --- /dev/null +++ b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/dictionary-metadata/dictionary-metadata.component.ts @@ -0,0 +1,78 @@ +/* +* ============LICENSE_START======================================================= +* ONAP : CDS +* ================================================================================ +* Copyright (C) 2020 TechMahindra +*================================================================================= +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ============LICENSE_END========================================================= +*/ +import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; +import { DictionaryModel } from '../../model/dictionary.model'; +import { DictionaryCreationService } from '../dictionary-creation.service'; +import { DictionaryCreationStore } from '../dictionary-creation.store'; +import { MetaData } from '../../model/metaData.model'; + +@Component({ + selector: 'app-dictionary-metadata', + templateUrl: './dictionary-metadata.component.html', + styleUrls: ['./dictionary-metadata.component.css'] +}) +export class DictionaryMetadataComponent implements OnInit { + packageNameAndVersionEnables = true; + counter = 0; + tags = new Set<string>(); + private metaDataTab: MetaData = new MetaData(); + private errorMessage: string; + + constructor( + private route: ActivatedRoute, + private dictionaryCreationService: DictionaryCreationService, + private dictionaryCreationStore: DictionaryCreationStore + ) {} + + ngOnInit() { + this.dictionaryCreationStore.state$.subscribe(element => { + if (element && element.metaData) { + this.metaDataTab.name = element.metaData.name; + this.metaDataTab.description = element.metaData.description; + this.metaDataTab.dataType = element.metaData.dataType; + this.metaDataTab.tags = element.metaData.tags; + this.metaDataTab.entrySchema = element.metaData.entrySchema; + this.metaDataTab.required = element.metaData.required; + this.metaDataTab.libraryInstance = element.metaData.libraryInstance; + this.metaDataTab.derivedFrom = element.metaData.derivedFrom; + console.log(element); + } + }); + console.log(this.metaDataTab.name); + } + + removeTag(value) { + this.tags.delete(value); + } + + addTag(event) { + const value = event.target.value; + console.log(value); + if (value && value.trim().length > 0) { + event.target.value = ''; + this.tags.add(value); + } + } + + saveMetaDataToStore() { + this.dictionaryCreationStore.changeMetaData(this.metaDataTab); + } +} diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/resource-dictionary-creation.component.css b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/resource-dictionary-creation.component.css new file mode 100644 index 000000000..f02bd233d --- /dev/null +++ b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/resource-dictionary-creation.component.css @@ -0,0 +1,37 @@ +/* +* ============LICENSE_START======================================================= +* ONAP : CDS +* ================================================================================ +* Copyright (C) 2020 TechMahindra +*================================================================================= +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ============LICENSE_END========================================================= +*/ +.edit-button{ + color:white; + background:#1B3E6F; + margin-right: 60px; + border: none; + width: 80px; + height: 20px; + margin-top: 25px; + font-size: 10px; + padding-left:5px; + padding-top: 3px; + } + .ed{ + justify-content: space-between; + } + .single-line-model{ + margin:20px; + }
\ No newline at end of file diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/resource-dictionary-creation.component.html b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/resource-dictionary-creation.component.html new file mode 100644 index 000000000..bf183216d --- /dev/null +++ b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/resource-dictionary-creation.component.html @@ -0,0 +1,122 @@ +<!--/* +* ============LICENSE_START======================================================= +* ONAP : CDS +* ================================================================================ +* Copyright (C) 2020 TechMahindra +*================================================================================= +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ============LICENSE_END========================================================= +*/--> +<app-header></app-header> + +<div class="new-wrapper"> + <div class="container-fluid main-container"> + <header class="page-title"> + <div class="row"> + <h2 class="col m-0 pb-0"> + <ul class="breadcrumb-header"> + <li><a routerLink="/resource-dictionary">Resource Dictionary</a></li> + <i class="fa fa-angle-right ml-2 mr-2"></i> + <li>Dictionary Name</li> + </ul> + </h2> + </div> + </header> + <div class="container-fluid body-container"> + <div class="container card creat-card col-11"> + <div class="single-line-model customKeyTitle"> + <h5 class="label-name w-100 "> + Dictionary Name + </h5> + <!-- <label class="label-name"></label> --> + <span>Last modified {{createDate}} by me</span> + </div> + </div> + </div> + <div class="container-fluid body-container"> + <div class="container"> + <div class="creat-action-container"> + <a class="action-button" (click)="saveDictionaryToStore()"> + <i class="icon-save-sm" aria-hidden="true"></i> + <span>Save</span> + </a> + <a href="#" class="action-button" (click)="goBackToDashBorad()"> + <i class="icon-discard-sm" aria-hidden="true"></i> + <span>Discard Changes</span> + </a> + <a href="#" class="action-button"> + <i class="icon-clone-sm" aria-hidden="true"></i> + <span>Clone</span> + </a> + <a href="#" class="action-button delete"> + <i class="icon-delete-sm" aria-hidden="true"></i> + <span>Delete</span> + </a> + </div> + <nav class="row"> + <!--Nav Tabs--> + <div class="col"> + <div class="nav nav-tabs ed" id="nav-tab" role="tablist"> + <a class="nav-item nav-link active" id="nav-metadata-tab" data-toggle="tab" + href="#nav-metadata" role="tab" aria-controls="nav-metadata" aria-selected="false" + autofocus #nameit (focusout)="test()">METADATA</a> + <a class="edit-button" id="nav-editor-tab" data-toggle="tab" href="#nav-editor" + role="tab" aria-controls="nav-editor" aria-selected="false">EDITOR MODE</a> + + </div> + </div> + </nav> + <div> + <div class="row mt-4"> + <div class="col"> + <div class="tab-content" id="nav-tabContent"> + <div class="tab-pane fade show active" id="nav-metadata" role="tabpanel" + aria-labelledby="nav-metadata-tab"> + <app-dictionary-metadata></app-dictionary-metadata> + <nav class="row"> + <!--Nav Tabs--> + <div class="col"> + <div class="nav nav-tabs " id="nav-tab" role="tablist"> + <a class="nav-item nav-link active" id="nav-source-tab" data-toggle="tab" + href="#nav-source" role="tab" aria-controls="nav-source" aria-selected="false" + >SOURCES</a> + </div> + </div> + </nav> + <div class="row mt-4"> + <div class="col"> + <div class="tab-content" id="nav-tabContent"> + <div class="tab-pane fade show active" id="nav-source" role="tabpanel" + aria-labelledby="nav-source-tab"> + <app-sources-template></app-sources-template> + </div> + </div> + </div> + </div> + </div> + <div class="tab-pane fade col-11" id="nav-editor" role="tabpanel" + aria-labelledby="nav-editor-tab"> + <div class="card creat-card"> + <div class="editor-container"> + <app-dictionary-editor></app-dictionary-editor> + </div></div> + </div> + </div> + </div> + </div> + + + </div> + </div> + </div> +</div>
\ No newline at end of file diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/resource-dictionary-creation.component.spec.ts b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/resource-dictionary-creation.component.spec.ts new file mode 100644 index 000000000..b1e6b6d24 --- /dev/null +++ b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/resource-dictionary-creation.component.spec.ts @@ -0,0 +1,44 @@ +/* +* ============LICENSE_START======================================================= +* ONAP : CDS +* ================================================================================ +* Copyright (C) 2020 TechMahindra +*================================================================================= +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ============LICENSE_END========================================================= +*/ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ResourceDictionaryCreationComponent } from './resource-dictionary-creation.component'; + +describe('ResourceDictionaryCreationComponent', () => { + let component: ResourceDictionaryCreationComponent; + let fixture: ComponentFixture<ResourceDictionaryCreationComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ResourceDictionaryCreationComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ResourceDictionaryCreationComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/resource-dictionary-creation.component.ts b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/resource-dictionary-creation.component.ts new file mode 100644 index 000000000..1a3484bae --- /dev/null +++ b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/resource-dictionary-creation.component.ts @@ -0,0 +1,76 @@ +/* +* ============LICENSE_START======================================================= +* ONAP : CDS +* ================================================================================ +* Copyright (C) 2020 TechMahindra +*================================================================================= +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ============LICENSE_END========================================================= +*/ +import { Component, OnInit, ViewChild, ElementRef } from '@angular/core'; +import { Router } from '@angular/router'; +import { DictionaryCreationStore } from './dictionary-creation.store'; +import { DictionaryModel } from '../model/dictionary.model'; +import { Definition } from '../model/definition.model'; +import { DictionaryMetadataComponent } from './dictionary-metadata/dictionary-metadata.component'; +import { SourcesTemplateComponent } from './sources-template/sources-template.component'; + +@Component({ + selector: 'app-resource-dictionary-creation', + templateUrl: './resource-dictionary-creation.component.html', + styleUrls: ['./resource-dictionary-creation.component.css'] +}) +export class ResourceDictionaryCreationComponent implements OnInit { + + constructor(private router: Router, private dictionaryCreationStore: DictionaryCreationStore) { + } + + modes: object[] = [ + {name: 'Designer Mode', style: 'mode-icon icon-designer-mode'}, + {name: 'Scripting Mode', style: 'mode-icon icon-scripting-mode'} + ]; + + private metaDataTab: DictionaryModel = new DictionaryModel(); + private definition: Definition = new Definition(); + + @ViewChild(DictionaryMetadataComponent, {static: false}) + private metadataTabComponent: DictionaryMetadataComponent; + + @ViewChild(SourcesTemplateComponent, {static: false}) + private sourcesTemplateComponent: SourcesTemplateComponent; + + @ViewChild('nameit', {static: true}) + private elementRef: ElementRef; + + ngOnInit() { + this.elementRef.nativeElement.focus(); + // this.elementRef2.nativeElement.focus(); + } + + saveDictionaryToStore() { + this.dictionaryCreationStore.getSources(); + this.dictionaryCreationStore.state$.subscribe(dd => { + console.log(dd); + }); + } + + test() { + this.metadataTabComponent.saveMetaDataToStore(); + this.sourcesTemplateComponent.saveSorcesDataToStore(); + } + + goBackToDashBorad() { + this.router.navigate(['/resource-dictionary']); + } + +} diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/sources-template/sources-template.component.css b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/sources-template/sources-template.component.css new file mode 100644 index 000000000..7799d915f --- /dev/null +++ b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/sources-template/sources-template.component.css @@ -0,0 +1,208 @@ +/* +* ============LICENSE_START======================================================= +* ONAP : CDS +* ================================================================================ +* Copyright (C) 2020 TechMahindra +*================================================================================= +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ============LICENSE_END========================================================= +*/ +.source{ + left: 20px; + width: 72%; +} +.source1{ + width: 25%; + background-color:#F4F9FE; +} +h5{ + padding-top: 10px; + padding-left: 10px; + background-color:white; + height: 40px; + width: 100%; +} +.mat-form-field + .mat-form-field { + margin-left: 8px; +} +mat-expansion-panel-header{ + background-color:#E0E8F2; +} +mat-panel-title{ + color:#1B3E6F; +} +mat-expansion-panel{ + border-radius: 0px; + border-left: none; +} +.example-list .card{ + margin-bottom: 10px !important; +} +.expansion-panel{ + border: none; + background: white; + border-radius: 0px; + overflow: hidden; + display: block; + width: 100%; + color:#1B3E6F; + } +.example-container { + width: 230px; + max-width: 100%; + margin: 10px 10px 15px 0; + display: inline-block; + vertical-align: top; + border-radius: 2px; + height: 260px; + background-color:#F4F9FE; + } + .example-container2 { + width: 630px; + max-width: 100%; + margin: 10px 10px 5px 0; + display: inline-block; + vertical-align: top; + border-radius: 2px; + height: 300px; + background-color:#F4F9FE; + } + + .example-list { + min-height: 12px; + border-radius: 0px; + overflow: hidden; + display: block; + margin: 5px; + overflow-y:scroll; + overflow-x:hidden; + margin-left: 15px; + width: 195px; + margin-top: 15px; + } + + .example-list1 { + min-height: 12px; + border-radius: 0px; + overflow: hidden; + display: block; + margin: 5px; + overflow-y:hidden; + overflow-x:hidden; + } + + .checkbox{ + margin-left: 11%; + } + .example-box { + padding: 2px 1px; + display: flex; + flex-direction: row; + align-items: center; + justify-content: left; + box-sizing: border-box; + cursor: move; + font-size: 14px; + + } + .example-box1 { + padding: 1px 1px; + display: flex; + flex-direction: row; + align-items: center; + justify-content: left; + box-sizing: border-box; + cursor: move; + font-size: 14px; + border-radius: 0px !important; + } + + .cdk-drag-preview { + box-sizing: border-box; + border-radius: 4px; + box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2), + 0 8px 10px 1px rgba(0, 0, 0, 0.14), + 0 3px 14px 2px rgba(0, 0, 0, 0.12); + } + + .cdk-drag-placeholder { + opacity: 0; + } + + .cdk-drag-animating { + transition: transform 250ms cubic-bezier(0, 0, 0.2, 1); + } + + .example-box:last-child { + border: none; + } + + .example-list.cdk-drop-list-dragging .example-box:not(.cdk-drag-placeholder) { + transition: transform 250ms cubic-bezier(0, 0, 0.2, 1); + } + +.searchText{ + width: 180px; + /* border-top: solid 2px #F4F9FE; */ + border: 0px; + color: #1B3E6F; + font-size: 13px; + margin-top: 2px; +} +.searchBox{ + position: relative; + top: 0%; + right: 0%; + height: 35px; + border-top: solid 2px #F4F9FE; + width: 100%; + margin-left:0px; + background-color:white; +} + +.searchButton1{ + float: left; + padding-left: 0 !important; + height: 30px; + width:30px; + background: url(src/assets/img/icon-search.svg) center center no-repeat; + border: 0 !important; + margin-right:0px; +} +.action-button1{ + margin-left:50px; + padding: 1px 6px; + box-shadow: none; + color:white; + font-size: 14px; + height: 25px; + background-color:#007bff; + border-radius:16px; + border:solid 0.5px #ededed; +} +.footer{ + margin: 1px 0px; +} +.delete{ + color: red; + font-size: 14px; + margin: 2px; +} +.footer input{ + margin: 6px 0px 1px 5px; +} +.select-button{ + color: #007bff; + font-size: 14px; + margin: 2px; +}
\ No newline at end of file diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/sources-template/sources-template.component.html b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/sources-template/sources-template.component.html new file mode 100644 index 000000000..b274ce95d --- /dev/null +++ b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/sources-template/sources-template.component.html @@ -0,0 +1,85 @@ +<!--/* +* ============LICENSE_START======================================================= +* ONAP : CDS +* ================================================================================ +* Copyright (C) 2020 TechMahindra +*================================================================================= +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ============LICENSE_END========================================================= +*/--> +<div class="col-11"> + <div class= "row "> + <div class="card creat-card source1"> + <h5 class="label-name"> Sources Options</h5> + <div class="searchBox row"><i class="searchButton1 col-1" aria-hidden="true"></i> + <input class="searchText col-8" [(ngModel)]="searchText" type="input" placeholder="filter sources"> + </div> + + <div class="example-container"> + <div + cdkDropList + #todoList="cdkDropList" + [cdkDropListData]="option" + [cdkDropListConnectedTo]="[doneList]" + class="example-list" + (cdkDropListDropped)="drop($event)"> + <div class="example-box card creat-card" *ngFor="let item of option| search :searchText" cdkDrag> + <input type="checkbox" class="checkbox" [(ngModel)]="checked" (change)="onChange(item, $event.target.checked)"> + {{item.name}} + </div> + + </div> + + </div> + <div class="footer row"> + <a class="select-button col-sm-05">Select all</a> + <button class="action-button1 col-sm-04" >Add to list</button> + </div> + </div> + + <div class="card creat-card source"> + <h5 class="label-name">Sources List</h5> + <div class="example-container2 card creat-card"> + <div + cdkDropList + #doneList="cdkDropList" + [cdkDropListData]="sourcesOptions" + [cdkDropListConnectedTo]="[todoList]" + class="example-list1" + (cdkDropListDropped)="drop($event)"> + + <div class="example-box1" *ngFor="let item of sourcesOptions" cdkDrag> + <input type="checkbox" value="item.name"> + <mat-expansion-panel class="expansion-panel"> + <mat-expansion-panel-header [collapsedHeight]="'23px'" [expandedHeight]="'23px'"> + <mat-panel-title> + {{item.name}} + </mat-panel-title> + </mat-expansion-panel-header> + <br> + <ace-editor [(text)]=item.value [mode]="'javascript'" [autoUpdateContent]="true" + [durationBeforeCallback]="1000" (textChanged)="textChanged($event,item)" [theme]="'tomorrow_night_bright'" #editor style="height:300px;"> + </ace-editor> + </mat-expansion-panel> + </div> + + </div> + + </div> + <div> + <a type="submit" class="delete">Delete</a> + </div> + </div> +</div> +</div> + diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/sources-template/sources-template.component.spec.ts b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/sources-template/sources-template.component.spec.ts new file mode 100644 index 000000000..e9bd4ff43 --- /dev/null +++ b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/sources-template/sources-template.component.spec.ts @@ -0,0 +1,44 @@ +/* +* ============LICENSE_START======================================================= +* ONAP : CDS +* ================================================================================ +* Copyright (C) 2020 TechMahindra +*================================================================================= +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ============LICENSE_END========================================================= +*/ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SourcesTemplateComponent } from './sources-template.component'; + +describe('SourcesTemplateComponent', () => { + let component: SourcesTemplateComponent; + let fixture: ComponentFixture<SourcesTemplateComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ SourcesTemplateComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(SourcesTemplateComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/sources-template/sources-template.component.ts b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/sources-template/sources-template.component.ts new file mode 100644 index 000000000..4a4f215cd --- /dev/null +++ b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/sources-template/sources-template.component.ts @@ -0,0 +1,109 @@ +/* +* ============LICENSE_START======================================================= +* ONAP : CDS +* ================================================================================ +* Copyright (C) 2020 TechMahindra +*================================================================================= +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ============LICENSE_END========================================================= +*/ +import { Component, OnInit} from '@angular/core'; +import { CdkDragDrop, moveItemInArray, transferArrayItem } from '@angular/cdk/drag-drop'; +import { SourcesStore } from './sources.store'; + +@Component({ + selector: 'app-sources-template', + templateUrl: './sources-template.component.html', + styleUrls: ['./sources-template.component.css'] +}) +export class SourcesTemplateComponent implements OnInit { + private searchQuery = ''; + lang = 'json'; + sources = []; + option = []; + sourcesOptions = []; + textValue: any; + selectItem: boolean; + ddSource = []; + checked: boolean; + selectedArray = []; + constructor(private sourcesStore: SourcesStore) { + this.sourcesStore.state$.subscribe(sources => { + this.sources = sources.sources; + for (const key in this.sources) { + if (key) { + const sourceObj = { name: key, value: JSON.stringify(this.sources[key] )}; + this.option.push(sourceObj); + } + } + }); + } + + ngOnInit() { + this.sourcesStore.getAllSources(); + } + + saveSorcesDataToStore() { + this.sourcesStore.saveSources(this.ddSource); + } + + drop(event: CdkDragDrop<string[]>) { + this.ddSource = []; + if (event.previousContainer === event.container) { + moveItemInArray(event.container.data, event.previousIndex, event.currentIndex); + } else { + transferArrayItem(event.previousContainer.data, + event.container.data, + event.previousIndex, + event.currentIndex); + } + + for (const key2 in this.sources) { + if (key2) { + const originalSources = this.sourcesOptions; + for (const key of originalSources) { + if (key.name === key2) { + const obj = `{${key.name}: ${key.value}}`; + this.ddSource.push(obj); + } + } + } + } + } + + searchDictionary(event: any) { + this.searchQuery = event.target.value; + this.searchQuery = this.searchQuery.trim(); + console.log(this.searchQuery); + // this.dictionaryStore.search(this.searchQuery); + } + + onChange(item: string, isChecked: boolean) { + if (isChecked) { + this.selectedArray.push(item); + } + } + + textChanged(event, item) { + const editedData = JSON.parse(event); + const originalSources = this.sources; + for (const key in originalSources) { + if (key === item.name) { + this.sources[key] = editedData; + } + } + this.option = []; + this.sourcesStore.changeSources(this.sources); + } + +} diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/sources-template/sources.store.ts b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/sources-template/sources.store.ts new file mode 100644 index 000000000..7da8f03d3 --- /dev/null +++ b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/sources-template/sources.store.ts @@ -0,0 +1,60 @@ +/* +* ============LICENSE_START======================================================= +* ONAP : CDS +* ================================================================================ +* Copyright (C) 2020 TechMahindra +*================================================================================= +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ============LICENSE_END========================================================= +*/ +import { Sources } from '../../model/sources.model'; +import { Store } from 'src/app/common/core/stores/Store'; +import { Injectable } from '@angular/core'; +import { DictionaryCreationService } from '../dictionary-creation.service'; +import { Definition } from '../../model/definition.model'; + +@Injectable({ + providedIn: 'root' +}) +export class SourcesStore extends Store<Sources> { + constructor(private dictionaryCreationService: DictionaryCreationService) { + super(new Sources()); + } + + public getAllSources() { + console.log('getting all sources...'); + this.getSources(); + } + + protected getSources() { + this.dictionaryCreationService.getSources() + .subscribe((sou) => { + console.log(sou); + this.setState({ + ...this.state, + sources: sou + }); + }); + } + + public changeSources(sou) { + this.setState({ + ...this.state, + sources: sou + }); + } + + public saveSources(sources) { + console.log(sources); + } +} diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-dashboard/dictionary-list/dictionary-list.component.html b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-dashboard/dictionary-list/dictionary-list.component.html index 1cedeeb09..b6fbf5939 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-dashboard/dictionary-list/dictionary-list.component.html +++ b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-dashboard/dictionary-list/dictionary-list.component.html @@ -28,7 +28,7 @@ <div class="card-footer row"> <div class="col text-center"> <a routerLink="/resource-dictionary/createDictionary" role="button" aria-pressed="true" - class="btn-create-package float"><i class="icon-create-white" aria-hidden="true"></i>Create Package + class="btn-create-package float"><i class="icon-create-white" aria-hidden="true"></i>Create Dictionary </a> <br/> <a href="#" role="button" aria-pressed="true" class="btn-import-package float mb-3"><i class="icon-import-blue" aria-hidden="true"></i>Import Package diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-routing.module.ts b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-routing.module.ts index eb29c4c87..04b66c7bd 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-routing.module.ts +++ b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-routing.module.ts @@ -17,15 +17,19 @@ * limitations under the License. * ============LICENSE_END========================================================= */ - import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { ResourceDictionaryDashboardComponent } from './resource-dictionary-dashboard/resource-dictionary-dashboard.component'; +import { ResourceDictionaryCreationComponent } from './resource-dictionary-creation/resource-dictionary-creation.component'; const routes: Routes = [ { path: '', component: ResourceDictionaryDashboardComponent + }, + { + path: 'createDictionary', + component: ResourceDictionaryCreationComponent } ]; diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary.module.ts b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary.module.ts index 5bd6710f8..3f0f89b0d 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary.module.ts +++ b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary.module.ts @@ -36,6 +36,13 @@ import { SortDictionaryComponent } from './resource-dictionary-dashboard/sort-di import { DictionaryPaginationComponent } from './resource-dictionary-dashboard/dictionary-pagination/dictionary-pagination.component'; import { SharedModulesModule } from '../../shared-modules/shared-modules.module'; import { DictionaryListComponent } from './resource-dictionary-dashboard/dictionary-list/dictionary-list.component'; +import { SearchPipe } from 'src/app/common/core/pipes/search.pipe'; +import { ResourceDictionaryCreationComponent } from './resource-dictionary-creation/resource-dictionary-creation.component'; +import { DictionaryMetadataComponent } from './resource-dictionary-creation/dictionary-metadata/dictionary-metadata.component'; +import { SourcesTemplateComponent } from './resource-dictionary-creation/sources-template/sources-template.component'; +import { DragDropModule } from '@angular/cdk/drag-drop'; +import { MatExpansionModule } from '@angular/material'; +import { DictionaryEditorComponent } from './resource-dictionary-creation/dictionary-editor/dictionary-editor.component'; @NgModule({ declarations: [ @@ -46,6 +53,11 @@ import { DictionaryListComponent } from './resource-dictionary-dashboard/diction SortDictionaryComponent, DictionaryPaginationComponent, DictionaryListComponent, + ResourceDictionaryCreationComponent, + DictionaryMetadataComponent, + SourcesTemplateComponent, + SearchPipe, + DictionaryEditorComponent, ], imports: [ CommonModule, @@ -57,6 +69,8 @@ import { DictionaryListComponent } from './resource-dictionary-dashboard/diction NgxFileDropModule, AceEditorModule, DataTablesModule, + DragDropModule, + MatExpansionModule, ] }) export class ResourceDictionaryModule { } diff --git a/cds-ui/designer-client/src/app/modules/shared-modules/shared-modules.module.ts b/cds-ui/designer-client/src/app/modules/shared-modules/shared-modules.module.ts index 7229891f5..7663fb8dc 100644 --- a/cds-ui/designer-client/src/app/modules/shared-modules/shared-modules.module.ts +++ b/cds-ui/designer-client/src/app/modules/shared-modules/shared-modules.module.ts @@ -2,13 +2,15 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { HeaderComponent } from './header/header.component'; import { RouterModule } from '@angular/router'; +import { TooltipModule } from 'ngx-bootstrap/tooltip'; @NgModule({ declarations: [HeaderComponent], imports: [ CommonModule, RouterModule, + TooltipModule.forRoot(), ], - exports : [HeaderComponent] + exports : [HeaderComponent, TooltipModule, ] }) export class SharedModulesModule { } diff --git a/cds-ui/designer-client/src/styles.css b/cds-ui/designer-client/src/styles.css index b44a36235..3c0a049bf 100644 --- a/cds-ui/designer-client/src/styles.css +++ b/cds-ui/designer-client/src/styles.css @@ -470,13 +470,14 @@ height: 40px; } .packages-card .card-title{ margin-bottom: 0 !important; - font-size: 15px; + font-size: 13px; font-weight: bold; color: #1B3E6F; } .packages-card .card-title span{ color: #1B3E6F; font-size: 11px; + vertical-align: bottom; } .packages-card p{ font-size: 12px; @@ -485,6 +486,10 @@ height: 40px; .packages-card p.package-desc{ font-size: 13px; text-align: left; + display: -webkit-box; + -webkit-line-clamp: 1; + -webkit-box-orient: vertical; + overflow: hidden; } .packages-card p.package-desc:hover{ color: #1B3E6F !important; @@ -1046,10 +1051,23 @@ height: 40px; } .packages-card .card-title{ margin-bottom: 0 !important; - font-size: 15px; + font-size: 14px; font-weight: bold; } -.packages-card .card-title:hover{ +.packages-card .card-title .packageName{ + margin-bottom: 0; + display: inline-block; + width: auto; + max-width: 76%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + font-size: 13px; + vertical-align: bottom; + color: #1B3E6F; +} +.packages-card .card-title:hover, +.packages-card .card-title:hover .packageName{ text-decoration: none; color: #1273EB; } @@ -1157,10 +1175,13 @@ height: 40px; background: #1B3E6F; box-shadow: none; } +.package-version{ + color: #C3CDDB !important; +} .package-version::before{ content: "|"; - margin-left: 12px; - margin-right: 10px; + margin-left: 8px; + margin-right: 6px; vertical-align: text-bottom; } @@ -1579,6 +1600,32 @@ ul.package-contributers{ margin-left: 0; margin-bottom: -16px; } + +/*TooltipModule - Shady*/ +.tooltip:before, +.tooltip:after{ + width: 100% !important; +} +.tooltip .tooltip-inner{ + max-width: 280px !important; + width: 100% !important; + text-align: left!important; + color:#1B3E6F; + background-color: #F4F9FE; + border: solid 1px #E6EDF5; + border-radius: 3px !important; + font-size: 11px; +} +.bs-tooltip-bottom .arrow::before{ + border-bottom-color: #E6EDF5 !important; +}
 +.bs-tooltip-top .arrow::before{ + border-top-color: #E6EDF5 !important; +}
 + + + + .btn{ padding-right: 20px !important; padding-left: 20px !important; @@ -1911,6 +1958,9 @@ hr{ font-size: 11px; color: #C3CDDB; } +.action-button.save{ + color: #1273EB; +} .action-button.delete{ color: #BABBC3; } @@ -1951,7 +2001,7 @@ hr{ } .modal-header{ border-bottom-color: #ECEDF2 !important; - padding: 1rem 1.5rem !important; + padding: .7rem 1.5rem !important; } .modal-footer{ border-top: 0 !important; @@ -1974,6 +2024,10 @@ hr{ .modal-footer .btn-secondary:hover{ opacity: 1; } +.modal-footer .btn-secondary:active{ + background-color: #E7F1FC !important; + color: #1B3E6F !important; +} .action-button span{ width: 100%; display: inline-block; @@ -2494,6 +2548,8 @@ margin-right: 5px; } .template-mapping-action button{ border-radius: 50px; + padding: 6px 20px; + font-size: 14px; } .template-mapping-action .btn-primary{ background:#5DBDBA !important ; @@ -2521,22 +2577,22 @@ margin-right: 5px; .dataTables_empty { display: none; } -#DataTables_Table_0_length, -#DataTables_Table_0_filter{ +.dataTables_length, +.dataTables_filter{ margin-bottom: 6px; - color: #1B3E6F; + color: #1B3E6F !important; font-size: 13px; font-weight: bold; } -#DataTables_Table_0_filter input{ +.dataTables_filter input{ color: #1B3E6F; background: url(../src/assets/img/icon-search.svg) 9px center no-repeat; padding: 4px 9px 4px 24px; border: solid 1px #ECEDF2; border-radius: 4px; } -#DataTables_Table_0_filter input:focus{ +.dataTables_filter input:focus{ box-shadow: 0 2px 6px 0 rgba(47, 83, 151, 0.1); } #mapping-table th, @@ -2565,41 +2621,45 @@ table.dataTable.no-footer{ margin-bottom: 9px; border-bottom: solid 1px #ECEDF2 !important; } -#DataTables_Table_0_info{ +.dataTables_info{ padding-top: 12px; - color: #1B3E6F; + color: #1B3E6F !important; font-size: 13px; font-weight: bold; } -#DataTables_Table_0_paginate, -#DataTables_Table_0_paginate a{ +.dataTables_wrapper .dataTables_paginate, +.dataTables_wrapper .dataTables_paginate a.paginate_button, +.dataTables_wrapper .dataTables_paginate a.paginate_button.current, +.dataTables_wrapper .dataTables_paginate a.paginate_button.disabled{ margin-bottom: 3px; color: #1B3E6F !important; font-size: 13px; font-weight: bold; + border: 0 !important; } -#DataTables_Table_0_paginate .paginate_button, -#DataTables_Table_0_paginate .paginate_button:hover{ +.dataTables_wrapper .dataTables_paginate a.paginate_button:hover{ border: 0; - background: none; + color: #1B3E6F !important; + background: none !important; } -.dataTables_wrapper .dataTables_paginate .paginate_button{ +.dataTables_wrapper .dataTables_paginate a.paginate_button{ padding: 0.4em .9em !important; } -#DataTables_Table_0_paginate .paginate_button.current{ +.dataTables_wrapper .dataTables_paginate a.paginate_button.current{ color: #1B3E6F !important; background: #F4F9FE !important; - border: solid 1px #EEF4F9; + border: solid 1px #EEF4F9 !important; border-radius: 100% !important; box-shadow: 0 2px 6px 0 rgba(47, 83, 151, 0.1); outline: 0; } -#DataTables_Table_0_paginate a.paginate_button.disabled{ +.dataTables_wrapper .dataTables_paginate a.paginate_button.disabled{ opacity: .6; - } -#DataTables_Table_0_paginate a.paginate_button.disabled:hover{ +.dataTables_wrapper .dataTables_paginate a.paginate_button.disabled:hover{ cursor: default; + background: none !important; + border: 0 !important; } #mapping-table .form-control, #mapping-table .custom-select{ @@ -2620,7 +2680,13 @@ table.dataTable.no-footer{ background-color: #F4F9FE; color: #1B3E6F; } - +#mapping-table .form-control:disabled{ + padding-left: 0; + box-shadow: none; + border: 0; + background: transparent; + color: #1B3E6F; +} /* Extra small devices (portrait phones, less than 576px) */ @media (max-width: 575.98px) { .page-title{ diff --git a/docs/media/CDS.png b/docs/media/CDS.png Binary files differnew file mode 100644 index 000000000..65f4115f8 --- /dev/null +++ b/docs/media/CDS.png diff --git a/ms/blueprintsprocessor/application/src/main/docker/Dockerfile b/ms/blueprintsprocessor/application/src/main/docker/Dockerfile index 042041ebb..bd1b3804a 100755 --- a/ms/blueprintsprocessor/application/src/main/docker/Dockerfile +++ b/ms/blueprintsprocessor/application/src/main/docker/Dockerfile @@ -11,11 +11,13 @@ FROM omahoco1/alpine-java-python COPY startService.sh /startService.sh RUN addgroup -S onap && adduser -S onap -G onap RUN chown onap:onap /startService.sh +RUN touch /velocity.log && chmod 777 /velocity.log +RUN chown onap:onap /velocity.log RUN chmod 777 /startService.sh && dos2unix /startService.sh # add application COPY --from=extractor /opt /opt -RUN mkdir /opt/app/onap/blueprints +RUN mkdir -p /opt/app/onap/blueprints/deploy RUN chown onap:onap /opt -R USER onap diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBService.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBService.kt index dc1553747..1a5d062a3 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBService.kt +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBService.kt @@ -181,11 +181,11 @@ class ResourceResolutionDBService(private val resourceResolutionRepository: Reso resourceResolution.resolutionKey = resolutionKey resourceResolution.resourceType = resourceType resourceResolution.resourceId = resourceId - if (BluePrintConstants.STATUS_SUCCESS == resourceAssignment.status) { - resourceResolution.value = JacksonUtils.getValue(resourceAssignment.property?.value!!).toString() - } else { - resourceResolution.value = "" - } + resourceResolution.value = resourceAssignment.property?.value?.let { + if (BluePrintConstants.STATUS_SUCCESS == resourceAssignment.status) + JacksonUtils.getValue(it).toString() + else "" + } ?: "" resourceResolution.name = resourceAssignment.name resourceResolution.dictionaryName = resourceAssignment.dictionaryName resourceResolution.dictionaryVersion = resourceAssignment.version diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/RestResourceResolutionProcessor.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/RestResourceResolutionProcessor.kt index 7596d7d8c..c60bc7648 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/RestResourceResolutionProcessor.kt +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/RestResourceResolutionProcessor.kt @@ -24,6 +24,7 @@ import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.BluePrintRestLibPrope import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.BlueprintWebClientService import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.ExecutionServiceDomains import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException +import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants import org.onap.ccsdk.cds.controllerblueprints.core.isNotEmpty import org.onap.ccsdk.cds.controllerblueprints.core.checkNotEmpty import org.onap.ccsdk.cds.controllerblueprints.core.nullToEmpty @@ -103,6 +104,7 @@ open class RestResourceResolutionProcessor(private val blueprintRestLibPropertyS val responseBody = response.body val outputKeyMapping = sourceProperties.outputKeyMapping if (responseStatusCode in 200..299 && outputKeyMapping.isNullOrEmpty()) { + resourceAssignment.status = BluePrintConstants.STATUS_SUCCESS logger.info("AS>> outputKeyMapping==null, will not populateResource") } else if (responseStatusCode in 200..299 && !responseBody.isBlank()) { populateResource(resourceAssignment, sourceProperties, responseBody, path) @@ -117,6 +119,7 @@ open class RestResourceResolutionProcessor(private val blueprintRestLibPropertyS ResourceAssignmentUtils.assertTemplateKeyValueNotNull(resourceAssignment) } catch (e: BluePrintProcessorException) { val errorMsg = "Failed to process REST resource resolution in template key ($resourceAssignment) assignments." + ResourceAssignmentUtils.setFailedResourceDataValue(resourceAssignment, errorMsg) throw e.updateErrorMessage(ExecutionServiceDomains.RESOURCE_RESOLUTION, errorMsg, "Wrong resource definition or resolution failed.") } catch (e: Exception) { diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBServiceTest.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBServiceTest.kt index e667cd16f..672d4b75d 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBServiceTest.kt +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/db/ResourceResolutionDBServiceTest.kt @@ -18,6 +18,7 @@ package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db import io.mockk.every import io.mockk.mockk +import io.mockk.slot import kotlinx.coroutines.runBlocking import org.junit.Before import org.junit.Test @@ -225,6 +226,29 @@ open class ResourceResolutionDBServiceTest { } @Test + fun writeWithNullValue() { + val slot = slot<ResourceResolution>() + val resourceAssignment = ResourceAssignment() + resourceAssignment.status = BluePrintConstants.STATUS_SUCCESS + resourceAssignment.dictionarySource = "ddSource" + resourceAssignment.dictionaryName = "ddName" + resourceAssignment.version = 1 + resourceAssignment.name = "test" + every { + resourceResolutionRepository.saveAndFlush(capture(slot)) + } returns ResourceResolution() + runBlocking { + resourceResolutionDBService.write( + props, bluePrintRuntimeService, artifactPrefix, resourceAssignment + ) + + val res = slot.captured + + assertEquals("", res.value) + } + } + + @Test fun deleteByBlueprintNameAndBlueprintVersionAndArtifactNameAndResolutionKeyTest() { every { resourceResolutionRepository.deleteByBlueprintNameAndBlueprintVersionAndArtifactNameAndResolutionKey(any(), any(), any(), any()) diff --git a/ms/command-executor/src/main/docker/Dockerfile b/ms/command-executor/src/main/docker/Dockerfile index 7a20469b7..e84d5531b 100644 --- a/ms/command-executor/src/main/docker/Dockerfile +++ b/ms/command-executor/src/main/docker/Dockerfile @@ -11,7 +11,6 @@ COPY start.sh /opt/app/onap/start.sh RUN chmod u+x /opt/app/onap/start.sh RUN mkdir -p /opt/app/onap/logs/ && touch /opt/app/onap/logs/application.log -RUN chown onap:onap /opt -R COPY @project.build.finalName@-@assembly.id@.tar.gz /source.tar.gz RUN tar -xzf /source.tar.gz -C /tmp \ @@ -19,6 +18,9 @@ RUN tar -xzf /source.tar.gz -C /tmp \ && rm -rf /source.tar.gz \ && rm -rf /tmp/@project.build.finalName@ +RUN mkdir -p /opt/app/onap/blueprints/deploy +RUN chown onap:onap /opt -R + VOLUME /opt/app/onap/blueprints/deploy/ USER onap ENTRYPOINT /opt/app/onap/start.sh diff --git a/ms/py-executor/docker/Dockerfile b/ms/py-executor/docker/Dockerfile index bb1b0f79c..638b09f39 100644 --- a/ms/py-executor/docker/Dockerfile +++ b/ms/py-executor/docker/Dockerfile @@ -12,6 +12,7 @@ RUN tar -xzf /source.tar.gz -C /tmp \ RUN pip install --no-cache-dir -r /opt/app/onap/python/requirements/docker.txt +RUN mkdir -p /opt/app/onap/blueprints/deploy RUN chown onap:onap /opt -R VOLUME /opt/app/onap/blueprints/deploy/ diff --git a/ms/py-executor/resource_resolution/README b/ms/py-executor/resource_resolution/README.md index 353600445..3920338ae 100644 --- a/ms/py-executor/resource_resolution/README +++ b/ms/py-executor/resource_resolution/README.md @@ -1,4 +1,4 @@ -# Resource resolution client +# Resource resolution GRPC client ## How to use examples @@ -7,7 +7,7 @@ ``` from proto.BluePrintCommon_pb2_grpc import ActionIdentifiers, CommonHeader from proto.BluePrintProcessing_pb2_grpc import ExecutionServiceInput -from resource_resolution.client import Client as ResourceResolutionClient +from resource_resolution.grpc.client import Client as ResourceResolutionClient def generate_messages(): @@ -45,7 +45,7 @@ if __name__ == "__main__": ``` from proto.BluePrintCommon_pb2_grpc import ActionIdentifiers, CommonHeader from proto.BluePrintProcessing_pb2_grpc import ExecutionServiceInput -from resource_resolution.client import Client as ResourceResolutionClient +from resource_resolution.grpc.client import Client as ResourceResolutionClient def generate_messages(): @@ -84,7 +84,7 @@ if __name__ == "__main__": ``` from proto.BluePrintCommon_pb2 import ActionIdentifiers, CommonHeader from proto.BluePrintProcessing_pb2 import ExecutionServiceInput -from resource_resolution.client import Client as ResourceResolutionClient +from resource_resolution.grpc.client import Client as ResourceResolutionClient def generate_messages(): @@ -121,7 +121,7 @@ if __name__ == "__main__": ## How to use examples -### Insecure channel +### GRPC insecure channel ``` from resource_resolution.resource_resolution import ResourceResolution, WorkflowExecution, WorkflowExecutionResult @@ -140,4 +140,41 @@ if __name__ == "__main__": print(response.error_message) else: print(response.payload) +``` + +### HTTP retrieve/store template + +``` +from resource_resolution.resource_resolution import ResourceResolution + +if __name__ == "__main__": + # If you want to use only HTTP you don't have to use context manager + r = ResourceResolution( + http_server_port=8081, + http_auth_user="ccsdkapps", + http_auth_pass="ccsdkapps", + http_use_tls=False + ) + r.store_template( + blueprint_name="blueprintName", + blueprint_version="1.0.0", + artifact_name="test", + resolution_key="test", + result="test") + template = r.retrieve_template( + blueprint_name="blueprintName", + blueprint_version="1.0.0", + artifact_name="test", + resolution_key="test", + ) + assert template.result == "test" + template.result = "another value" + template.store() + another_template = r.retrieve_template( + blueprint_name="blueprintName", + blueprint_version="1.0.0", + artifact_name="test", + resolution_key="test", + ) + assert another_template.result == "another_value" ```
\ No newline at end of file diff --git a/ms/py-executor/resource_resolution/grpc/__init__.py b/ms/py-executor/resource_resolution/grpc/__init__.py new file mode 100644 index 000000000..1894680a6 --- /dev/null +++ b/ms/py-executor/resource_resolution/grpc/__init__.py @@ -0,0 +1,16 @@ +"""Copyright 2020 Deutsche Telekom. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +""" + +from .client import Client diff --git a/ms/py-executor/resource_resolution/authorization.py b/ms/py-executor/resource_resolution/grpc/authorization.py index ae5954ecc..ae5954ecc 100644 --- a/ms/py-executor/resource_resolution/authorization.py +++ b/ms/py-executor/resource_resolution/grpc/authorization.py diff --git a/ms/py-executor/resource_resolution/client.py b/ms/py-executor/resource_resolution/grpc/client.py index fee168628..fee168628 100644 --- a/ms/py-executor/resource_resolution/client.py +++ b/ms/py-executor/resource_resolution/grpc/client.py diff --git a/ms/py-executor/resource_resolution/http/__init__.py b/ms/py-executor/resource_resolution/http/__init__.py new file mode 100644 index 000000000..1894680a6 --- /dev/null +++ b/ms/py-executor/resource_resolution/http/__init__.py @@ -0,0 +1,16 @@ +"""Copyright 2020 Deutsche Telekom. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +""" + +from .client import Client diff --git a/ms/py-executor/resource_resolution/http/client.py b/ms/py-executor/resource_resolution/http/client.py new file mode 100644 index 000000000..8bb1e1be4 --- /dev/null +++ b/ms/py-executor/resource_resolution/http/client.py @@ -0,0 +1,96 @@ +"""Copyright 2020 Deutsche Telekom. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +""" +from typing import Optional, Tuple + +from requests import Session, request, Request, Response, PreparedRequest + + +class Client: + """HTTP client class.""" + + API_VERSION = "v1" + + def __init__( + self, server_address: str, server_port: int, auth_user: str = None, auth_pass: str = None, use_ssl: bool = False + ) -> None: + """HTTP client class initialization. + + Args: + server_address (str): HTTP server address + server_port (int): HTTP server port + auth_user (str, optional): Username used for authorization. Defaults to None. + auth_pass (str, optional): Password used for authorization. Defaults to None. + use_ssl (bool, optional): Determines if secure connection has to be used. Defaults to False. + """ + self.server_address: str = server_address + self.server_port: int = server_port + self.use_ssl: bool = use_ssl + + self.auth_user: str = auth_user + self.auth_pass: str = auth_pass + + @property + def auth(self) -> Optional[Tuple[str, str]]: + """Authorization data tuple or None. + + Returns None if not both auth_user and auth_pass values are set. + + Returns: + Optional[Tuple[str, str]]: Authorization tuple (auth_user, auth_pass) or None + """ + if all([self.auth_user, self.auth_pass]): + return (self.auth_user, self.auth_pass) + return None + + @property + def protocol(self) -> str: + """Protocol which is going to be used for request call. + + Returns: + str: http or https + """ + if self.use_ssl: + return "https" + return "http" + + @property + def url(self) -> str: + """Url to call requests. + + Returns: + str: Url string + """ + return f"{self.protocol}://{self.server_address}:{self.server_port}/api/{self.API_VERSION}" + + def send_request(self, method: str, endpoint: str, **kwargs) -> Response: + """Send request to server. + + Send request with `method` method to server. Pass any additional values as **kwargs. + + Args: + method (str): HTTP method + endpoint (str): Endpoint to call a request + + Raises: + requests.HTTPError: An HTTP error occurred. + + Returns: + Response: `requests.Response` object. + """ + response: Response = request( + method=method, url=f"{self.url}/{endpoint}", verify=False, auth=self.auth, **kwargs + ) + response.raise_for_status() + return response diff --git a/ms/py-executor/resource_resolution/resource_resolution.py b/ms/py-executor/resource_resolution/resource_resolution.py index e4f162f8f..3b8c19b74 100644 --- a/ms/py-executor/resource_resolution/resource_resolution.py +++ b/ms/py-executor/resource_resolution/resource_resolution.py @@ -13,8 +13,11 @@ See the License for the specific language governing permissions and limitations under the License. """ +import json +from dataclasses import dataclass, field from enum import Enum, unique from logging import Logger, getLogger +from os import getenv from types import TracebackType from typing import Any, Dict, Generator, Optional, Type @@ -22,7 +25,8 @@ from google.protobuf import json_format from proto.BluePrintProcessing_pb2 import ExecutionServiceInput, ExecutionServiceOutput -from .client import Client +from .grpc import Client as GrpcClient +from .http import Client as HttpClient @unique @@ -179,6 +183,39 @@ class WorkflowExecutionResult: return json_format.MessageToDict(self.execution_output.payload) +@dataclass +class Template: + """Template dataclass. + + Store resolved template data. + It keeps also ResourceResolution object to call `store_template` method. + """ + + resource_resolution: "ResourceResolution" = field(repr=False) + blueprint_name: str + blueprint_version: str + artifact_name: str = None + result: str = None + resolution_key: str = None + resource_type: str = None + resource_id: str = None + + def store(self) -> None: + """Store template using blueprintprocessor HTTP API. + + It uses ResourceResolution `store_template` method. + """ + self.resource_resolution.store_template( + blueprint_name=self.blueprint_name, + blueprint_version=self.blueprint_version, + artifact_name=self.artifact_name, + result=self.result, + resolution_key=self.resolution_key, + resource_type=self.resource_type, + resource_id=self.resource_id, + ) + + class ResourceResolution: """Resource resolution class. @@ -191,20 +228,26 @@ class ResourceResolution: self, *, server_address: str = "127.0.0.1", - server_port: int = "9111", + # GRPC client configuration + grpc_server_port: int = 9111, use_ssl: bool = False, root_certificates: bytes = None, private_key: bytes = None, certificate_chain: bytes = None, - # Authentication header configuration + # Authentication header configuration for GRPC client use_header_auth: bool = False, header_auth_token: str = None, + # HTTP client configuration + http_server_port: int = 8080, + http_auth_user: str = None, + http_auth_pass: str = None, + http_use_ssl: bool = True, ) -> None: """Resource resolution object initialization. Args: server_address (str, optional): gRPC server address. Defaults to "127.0.0.1". - server_port (int, optional): gRPC server address port. Defaults to "9111". + grpc_server_port (int, optional): gRPC server address port. Defaults to 9111. use_ssl (bool, optional): Boolean flag to determine if secure channel should be created or not. Defaults to False. root_certificates (bytes, optional): The PEM-encoded root certificates. None if it shouldn't be used. @@ -216,33 +259,49 @@ class ResourceResolution: use_header_auth (bool, optional): Boolean flag to determine if authorization headed shoud be added for every call or not. Defaults to False. header_auth_token (str, optional): Authorization token value. Defaults to None. + If no value is provided "AUTH_TOKEN" environment variable will be used. + http_server_port (int, optional): HTTP server address port. Defaults to 8080. + http_auth_user (str, optional): Username used for HTTP requests authorization. Defaults to None. + If no value is provided "API_USERNAME" environment variable will be used. + http_auth_pass (str, optional): Password used for HTTP requests authorization. Defaults to None. + If no value is provided "API_PASSWORD" environment variable will be used. + http_use_ssl (bool, optional): Determines if secure connection should be used for HTTP requests. + Defaults to False. """ # Logger self.logger: Logger = getLogger(__name__) - # Client settings - self.client_server_address: str = server_address - self.client_server_port: str = server_port - self.client_use_ssl: bool = use_ssl - self.client_root_certificates: bytes = root_certificates - self.client_private_key: bytes = private_key - self.client_certificate_chain: bytes = certificate_chain - self.client_use_header_auth: bool = use_header_auth - self.client_header_auth_token: str = header_auth_token - self.client: Client = None + # GrpcClient settings + self.grpc_client_server_address: str = server_address + self.grpc_client_server_port: str = grpc_server_port + self.grpc_client_use_ssl: bool = use_ssl + self.grpc_client_root_certificates: bytes = root_certificates + self.grpc_client_private_key: bytes = private_key + self.grpc_client_certificate_chain: bytes = certificate_chain + self.grpc_client_use_header_auth: bool = use_header_auth + self.grpc_client_header_auth_token: str = header_auth_token or getenv("AUTH_TOKEN") + self.grpc_client: GrpcClient = None + # HttpClient settings + self.http_client: HttpClient = HttpClient( + server_address, + server_port=http_server_port, + auth_user=http_auth_user or getenv("API_USERNAME"), + auth_pass=http_auth_pass or getenv("API_PASSWORD"), + use_ssl=http_use_ssl, + ) def __enter__(self) -> "ResourceResolution": """Enter ResourceResolution instance context. - Client connection is created. + GrpcClient connection is created. """ - self.client = Client( - server_address=f"{self.client_server_address}:{self.client_server_port}", - use_ssl=self.client_use_ssl, - root_certificates=self.client_root_certificates, - private_key=self.client_private_key, - certificate_chain=self.client_certificate_chain, - use_header_auth=self.client_use_header_auth, - header_auth_token=self.client_header_auth_token, + self.grpc_client = GrpcClient( + server_address=f"{self.grpc_client_server_address}:{self.grpc_client_server_port}", + use_ssl=self.grpc_client_use_ssl, + root_certificates=self.grpc_client_root_certificates, + private_key=self.grpc_client_private_key, + certificate_chain=self.grpc_client_certificate_chain, + use_header_auth=self.grpc_client_use_header_auth, + header_auth_token=self.grpc_client_header_auth_token, ) return self @@ -254,9 +313,9 @@ class ResourceResolution: ) -> None: """Exit ResourceResolution instance context. - Client connection is closed. + GrpcClient connection is closed. """ - self.client.close() + self.grpc_client.close() def execute_workflows(self, *workflows: WorkflowExecution) -> Generator[WorkflowExecutionResult, None, None]: """Execute provided workflows. @@ -270,7 +329,7 @@ class ResourceResolution: AttributeError: Raises if client object is not created. It occurs only if you not uses context manager. Then user have to create client instance for ResourceResolution object by himself calling: ``` - resource_resoulution.client = Client( + resource_resoulution.client = GrpcClient( server_address=f"{resource_resoulution.client_server_address}:{resource_resoulution.client_server_port}", use_ssl=resource_resoulution.client_use_ssl, root_certificates=resource_resoulution.client_root_certificates, @@ -287,8 +346,112 @@ class ResourceResolution: with both WorkflowExection object and server response for it's request. """ self.logger.debug("Execute workflows") - if not self.client: + if not self.grpc_client: raise AttributeError("gRPC client not connected") - for response, workflow in zip(self.client.process((workflow.message for workflow in workflows)), workflows): + for response, workflow in zip( + self.grpc_client.process((workflow.message for workflow in workflows)), workflows + ): yield WorkflowExecutionResult(workflow, response) + + def _check_template_resolve_params( + self, resolution_key: str = None, resource_type: str = None, resource_id: str = None + ): + """Check template API request parameters. + + It's possible to store/retrieve templates using pair of artifact name and resolution key OR + resource type and resource id. This method checks if valid combination of parameters were used. + + Args: + resolution_key (str, optional): resolutionKey HTTP request parameter value. Defaults to None. + resource_type (str, optional): resourceType HTTP request parameter value. Defaults to None. + resource_id (str, optional): resourceId HTTP request parameter value. Defaults to None. + + Raises: + AttributeError: Invalid combination of parametes used + """ + if not any([resolution_key, all([resource_type, resource_id])]): + raise AttributeError( + "To store/retrieve template resolution_key and artifact_name or both resource_type and resource_id have to be provided" + ) + + def store_template( + self, + blueprint_name: str, + blueprint_version: str, + result: str, + artifact_name: str, + resolution_key: str = None, + resource_type: str = None, + resource_id: str = None, + ) -> None: + """Store template using blueprintprocessor HTTP API. + + Prepare and send a request to store resolved template using blueprint name, blueprint version + and pair of artifact name and resolution key OR resource type and resource id. + + Method returns Template dataclass, which stores all template data and can be used to update + it's result. + + Args: + blueprint_name (str): Blueprint name + blueprint_version (str): Blueprint version + result (str): Template result + artifact_name (str): Artifact name + resolution_key (str, optional): Resolution key. Defaults to None. + resource_type (str, optional): Resource type. Defaults to None. + resource_id (str, optional): Resource ID. Defaults to None. + """ + self.logger.debug("Store template") + self._check_template_resolve_params(resolution_key, resource_type, resource_id) + base_endpoint: str = f"template/{blueprint_name}/{blueprint_version}" + if resolution_key and artifact_name: + endpoint: str = f"{base_endpoint}/{artifact_name}/{resolution_key}" + else: + endpoint: str = f"{base_endpoint}/{resource_type}/{resource_id}" + response = self.http_client.send_request( + "POST", endpoint, headers={"Content-Type": "application/json"}, data=json.dumps({"result": result}) + ) + + def retrieve_template( + self, + blueprint_name: str, + blueprint_version: str, + artifact_name: str, + resolution_key: str = None, + resource_type: str = None, + resource_id: str = None, + ) -> Template: + """Get stored template using blueprintprocessor's HTTP API. + + Prepare and send a request to retrieve resolved template using blueprint name, blueprint version + and pair of artifact name and resolution key OR resource type and resource id. + + Args: + blueprint_name (str): Blueprint name + blueprint_version (str): Blueprint version + artifact_name (str): Artifact name + resolution_key (str, optional): Resolution key. Defaults to None. + resource_type (str, optional): Resource type. Defaults to None. + resource_id (str, optional): Resource ID. Defaults to None. + """ + self.logger.debug("Retrieve template") + self._check_template_resolve_params(resolution_key, resource_type, resource_id) + params: dict = {"bpName": blueprint_name, "bpVersion": blueprint_version, "artifactName": artifact_name} + if resolution_key: + params.update({"resolutionKey": resolution_key}) + else: + params.update({"resourceType": resource_type, "resourceId": resource_id}) + response = self.http_client.send_request( + "GET", "template", headers={"Accept": "application/json"}, params=params + ) + return Template( + resource_resolution=self, + blueprint_name=blueprint_name, + blueprint_version=blueprint_version, + artifact_name=artifact_name, + resolution_key=resolution_key, + resource_type=resource_type, + resource_id=resource_id, + result=response.json()["result"], + ) diff --git a/ms/py-executor/resource_resolution/tests/authorization_interceptor_test.py b/ms/py-executor/resource_resolution/tests/authorization_interceptor_test.py index 4b03f0b36..734059f3d 100644 --- a/ms/py-executor/resource_resolution/tests/authorization_interceptor_test.py +++ b/ms/py-executor/resource_resolution/tests/authorization_interceptor_test.py @@ -17,7 +17,7 @@ from unittest.mock import MagicMock, _Call import pytest -from resource_resolution.authorization import AuthTokenInterceptor, NewClientCallDetails +from resource_resolution.grpc.authorization import AuthTokenInterceptor, NewClientCallDetails def test_resource_resolution_auth_token_interceptor(): diff --git a/ms/py-executor/resource_resolution/tests/client_test.py b/ms/py-executor/resource_resolution/tests/grpc_client_test.py index 2b94220f6..8217b0f25 100644 --- a/ms/py-executor/resource_resolution/tests/client_test.py +++ b/ms/py-executor/resource_resolution/tests/grpc_client_test.py @@ -15,10 +15,10 @@ limitations under the License. from unittest.mock import MagicMock, patch -from resource_resolution.client import Client +from resource_resolution.grpc.client import Client -@patch("resource_resolution.client.insecure_channel") +@patch("resource_resolution.grpc.client.insecure_channel") def test_resource_resoulution_insecure_channel(insecure_channel_mock: MagicMock): """Test if insecure_channel connection is called.""" with patch.object(Client, "close") as client_close_method_mock: # Type MagicMock diff --git a/ms/py-executor/resource_resolution/tests/http_client_test.py b/ms/py-executor/resource_resolution/tests/http_client_test.py new file mode 100644 index 000000000..2279fde7a --- /dev/null +++ b/ms/py-executor/resource_resolution/tests/http_client_test.py @@ -0,0 +1,38 @@ +"""Copyright 2020 Deutsche Telekom. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +""" + +from unittest.mock import MagicMock, patch + +from resource_resolution.http.client import Client + + +@patch("resource_resolution.http.client.request") +def test_http_client(request_mock): + c = Client("127.0.0.1", 8080) + assert c.auth is None + c = Client("127.0.0.1", 8080, auth_user="user") + assert c.auth is None + c = Client("127.0.0.1", 8080, auth_user="user", auth_pass="pass") + assert c.auth == ("user", "pass") + + assert c.protocol == "http" + assert c.url == "http://127.0.0.1:8080/api/v1" + + c = Client("127.0.0.1", 8081, use_ssl=True) + assert c.protocol == "https" + assert c.url == "https://127.0.0.1:8081/api/v1" + + c.send_request("GET", "something") + request_mock.assert_called_once_with(method="GET", url=f"{c.url}/something", verify=False, auth=None) diff --git a/ms/py-executor/resource_resolution/tests/resource_resolution_test.py b/ms/py-executor/resource_resolution/tests/resource_resolution_test.py index 8a41357e6..274802279 100644 --- a/ms/py-executor/resource_resolution/tests/resource_resolution_test.py +++ b/ms/py-executor/resource_resolution/tests/resource_resolution_test.py @@ -13,12 +13,17 @@ See the License for the specific language governing permissions and limitations under the License. """ +import json +from unittest.mock import patch, MagicMock + from google.protobuf import json_format from pytest import raises from resource_resolution.resource_resolution import ( ExecutionServiceInput, ExecutionServiceOutput, + ResourceResolution, + Template, WorkflowExecution, WorkflowExecutionResult, WorkflowMode, @@ -103,3 +108,62 @@ def test_workflow_execution_result_class(): execution_output.status.code = 500 assert execution_result.has_error assert execution_result.error_message == "" + + +def test_resource_resolution_check_resolve_params(): + """Check values of potentially HTTP parameters.""" + rr = ResourceResolution() + with raises(AttributeError): + rr._check_template_resolve_params() + rr._check_template_resolve_params(resource_type="test") + rr._check_template_resolve_params(resource_id="test") + rr._check_template_resolve_params(resolution_key="test") + rr._check_template_resolve_params(resource_type="test", resource_id="test") + + +def test_store_template(): + """Test store_template method. + + Checks if http_client send_request method is called with valid parameters. + """ + rr = ResourceResolution(server_address="127.0.0.1", http_server_port=8080) + rr.http_client = MagicMock() + rr.store_template( + blueprint_name="test_blueprint_name", + blueprint_version="test_blueprint_version", + artifact_name="test_artifact_name", + resolution_key="test_resolution_key", + result="test_result", + ) + rr.http_client.send_request.assert_called_once_with( + "POST", + "template/test_blueprint_name/test_blueprint_version/test_artifact_name/test_resolution_key", + data=json.dumps({"result": "test_result"}), + headers={"Content-Type": "application/json"}, + ) + + +def test_retrieve_template(): + """Test retrieve_template method. + + Checks if http_client send_request method is called with valid parameters. + """ + rr = ResourceResolution(server_address="127.0.0.1", http_server_port=8080) + rr.http_client = MagicMock() + rr.retrieve_template( + blueprint_name="test_blueprint_name", + blueprint_version="test_blueprint_version", + artifact_name="test_artifact_name", + resolution_key="test_resolution_key", + ) + rr.http_client.send_request.assert_called_once_with( + "GET", + "template", + params={ + "bpName": "test_blueprint_name", + "bpVersion": "test_blueprint_version", + "artifactName": "test_artifact_name", + "resolutionKey": "test_resolution_key", + }, + headers={"Accept": "application/json"}, + ) diff --git a/ms/sdclistener/distribution/src/main/docker/Dockerfile b/ms/sdclistener/distribution/src/main/docker/Dockerfile index 5168dd9c2..e9ecb8d66 100755 --- a/ms/sdclistener/distribution/src/main/docker/Dockerfile +++ b/ms/sdclistener/distribution/src/main/docker/Dockerfile @@ -12,7 +12,8 @@ RUN tar -xzf /source.tar.gz -C /tmp \ && rm -rf /source.tar.gz \ && rm -rf /tmp/@project.build.finalName@ -RUN mkdir /opt/app/onap/cds-sdc-listener +RUN mkdir -p /opt/app/onap/cds-sdc-listener RUN chown onap:onap /opt -R + USER onap ENTRYPOINT /startService.sh |