aboutsummaryrefslogtreecommitdiffstats
path: root/catalog-ui/app/scripts/view-models/forms
diff options
context:
space:
mode:
Diffstat (limited to 'catalog-ui/app/scripts/view-models/forms')
-rw-r--r--catalog-ui/app/scripts/view-models/forms/artifact-form/artifact-form-view-model.ts354
-rw-r--r--catalog-ui/app/scripts/view-models/forms/artifact-form/artifact-form-view.html169
-rw-r--r--catalog-ui/app/scripts/view-models/forms/artifact-form/artifact-form.less44
-rw-r--r--catalog-ui/app/scripts/view-models/forms/attribute-form/attribute-form-view.html153
-rw-r--r--catalog-ui/app/scripts/view-models/forms/attribute-form/attribute-from-view-model.ts255
-rw-r--r--catalog-ui/app/scripts/view-models/forms/env-parameters-form/env-parameters-form.html39
-rw-r--r--catalog-ui/app/scripts/view-models/forms/env-parameters-form/env-parameters-form.less74
-rw-r--r--catalog-ui/app/scripts/view-models/forms/env-parameters-form/env-parameters-form.ts149
-rw-r--r--catalog-ui/app/scripts/view-models/forms/property-form/property-form-view-model.ts330
-rw-r--r--catalog-ui/app/scripts/view-models/forms/property-form/property-form-view.html219
-rw-r--r--catalog-ui/app/scripts/view-models/forms/property-form/property-form.less63
-rw-r--r--catalog-ui/app/scripts/view-models/forms/resource-instance-name-form/resource-instance-name-model.ts105
-rw-r--r--catalog-ui/app/scripts/view-models/forms/resource-instance-name-form/resource-instance-name-view.html72
-rw-r--r--catalog-ui/app/scripts/view-models/forms/resource-instance-name-form/resource-instance-name.less29
14 files changed, 2055 insertions, 0 deletions
diff --git a/catalog-ui/app/scripts/view-models/forms/artifact-form/artifact-form-view-model.ts b/catalog-ui/app/scripts/view-models/forms/artifact-form/artifact-form-view-model.ts
new file mode 100644
index 0000000000..092594b0d5
--- /dev/null
+++ b/catalog-ui/app/scripts/view-models/forms/artifact-form/artifact-form-view-model.ts
@@ -0,0 +1,354 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+/// <reference path="../../../references"/>
+
+module Sdc.ViewModels {
+ 'use strict';
+ import Resource = Sdc.Models.Components.Resource;
+
+ export interface IEditArtifactModel {
+ artifactResource: Models.ArtifactModel;
+ artifactTypes: Array<string>;
+ artifactFile: any;
+ }
+
+ export interface IArtifactResourceFormViewModelScope extends ng.IScope {
+ forms:any;
+ $$childTail: any;
+ isNew: boolean;
+ isLoading: boolean;
+ validationPattern: RegExp;
+ urlValidationPattern: RegExp;
+ labelValidationPattern: RegExp;
+ integerValidationPattern: RegExp;
+ commentValidationPattern: RegExp;
+ artifactType: string;
+ editArtifactResourceModel: IEditArtifactModel;
+ defaultHeatTimeout: number;
+ validExtensions: any;
+ originalArtifactName: string;
+ editForm: ng.IFormController;
+ footerButtons: Array<any>;
+ modalInstanceArtifact:ng.ui.bootstrap.IModalServiceInstance;
+
+ fileExtensions():string;
+ save(doNotCloseModal?:boolean): void;
+ saveAndAnother(): void;
+ close(): void;
+ getOptions(): Array<string>;
+ isDeploymentHeat(): boolean;
+ onFileChange(): void;
+ setDefaultTimeout(): void;
+ openEditEnvParametersModal(artifact:Models.ArtifactModel):void;
+ getFormTitle():string;
+ fileUploadRequired():string;
+ isArtifactOwner():boolean;
+ }
+
+ export class ArtifactResourceFormViewModel {
+
+ private artifactArr:Array<Models.ArtifactModel>;
+
+ static '$inject' = [
+ '$scope',
+ '$modalInstance',
+ 'artifact',
+ 'Sdc.Services.CacheService',
+ 'ValidationPattern',
+ 'UrlValidationPattern',
+ 'LabelValidationPattern',
+ 'IntegerValidationPattern',
+ 'CommentValidationPattern',
+ 'ValidationUtils',
+ '$base64',
+ '$state',
+ 'ArtifactsUtils',
+ '$modal',
+ '$templateCache',
+ 'component'
+ ];
+
+ private formState:Utils.Constants.FormState;
+ private entityId:string;
+
+ constructor(private $scope:IArtifactResourceFormViewModelScope,
+ private $modalInstance:ng.ui.bootstrap.IModalServiceInstance,
+ private artifact:Models.ArtifactModel,
+ private cacheService:Services.CacheService,
+ private ValidationPattern:RegExp,
+ private UrlValidationPattern:RegExp,
+ private LabelValidationPattern:RegExp,
+ private IntegerValidationPattern : RegExp,
+ private CommentValidationPattern: RegExp,
+ private ValidationUtils: Sdc.Utils.ValidationUtils,
+ private $base64:any,
+ private $state:any,
+ private artifactsUtils:Sdc.Utils.ArtifactsUtils,
+ private $modal:ng.ui.bootstrap.IModalService,
+ private $templateCache:ng.ITemplateCacheService,
+ private component:Models.Components.Component) {
+
+
+ this.entityId = this.component.uniqueId;
+ this.artifactArr = [];
+ this.formState = angular.isDefined(artifact.artifactLabel) ? Utils.Constants.FormState.UPDATE : Utils.Constants.FormState.CREATE;
+ this.initScope();
+ }
+
+ private initEntity = ():void => {
+ this.$scope.editArtifactResourceModel.artifactResource = this.artifact;
+ this.$scope.originalArtifactName = this.artifact.artifactName;
+ };
+
+
+ private initFooterButtons = ():void =>{
+
+ this.$scope.footerButtons = [
+ {'name': 'Done', 'css': 'blue', 'callback': this.$scope.save}
+ ];
+ if (this.$scope.isNew){
+ this.$scope.footerButtons.push( {'name': 'Add Another', 'css': 'grey', 'disabled': !this.$scope.isNew && 'deployment' === this.$scope.artifactType, 'callback': this.$scope.saveAndAnother});
+ }
+
+ };
+
+
+ private initArtifactTypes = ():void => {
+
+ let artifactTypes:any = this.cacheService.get('UIConfiguration');
+
+ if('deployment' === this.$scope.artifactType) {
+
+ this.$scope.validExtensions = ('HEAT_ENV' == this.artifact.artifactType||this.component.selectedInstance)?//to remove the first condition?
+ artifactTypes.artifacts.deployment.resourceInstanceDeploymentArtifacts
+ : this.component.isResource() ? artifactTypes.artifacts.deployment.resourceDeploymentArtifacts
+ : artifactTypes.artifacts.deployment.serviceDeploymentArtifacts;
+
+ if(this.$scope.validExtensions) {
+ this.$scope.editArtifactResourceModel.artifactTypes = Object.keys(this.$scope.validExtensions);
+ }
+ this.$scope.defaultHeatTimeout = artifactTypes.defaultHeatTimeout;
+ if(this.$scope.isNew) {
+ let isHeat='HEAT_ENV' == this.artifact.artifactType;
+ _.remove(this.$scope.editArtifactResourceModel.artifactTypes, (item:string)=> {
+ return 'HEAT' == item.substring(0,4)||(!isHeat && item == "VF_MODULES_METADATA") ||
+ _.has(Utils.Constants.ArtifactType.THIRD_PARTY_RESERVED_TYPES, item);
+ });
+ }
+
+ }if (this.$scope.artifactType === 'normal') {
+ this.$scope.editArtifactResourceModel.artifactTypes = artifactTypes.artifacts.other.map((element:any)=> {
+ return element.name;
+ });
+ _.remove(this.$scope.editArtifactResourceModel.artifactTypes, (item:string)=> {
+ return _.has(Utils.Constants.ArtifactType.THIRD_PARTY_RESERVED_TYPES, item) ||
+ _.has(Utils.Constants.ArtifactType.TOSCA, item);
+ })
+ }
+
+ if(this.component.isResource() && (<Resource>this.component).isCsarComponent()) {
+ _.remove(this.$scope.editArtifactResourceModel.artifactTypes, (item:string) => {
+ return this.artifactsUtils.isLicenseType(item);
+ })
+ }
+
+ };
+
+ private initEditArtifactResourceModel = ():void => {
+ this.$scope.editArtifactResourceModel = {
+ artifactResource: null,
+ artifactTypes: null,
+ artifactFile:{}
+ };
+
+ this.initEntity();
+ };
+
+ private initScope = ():void => {
+
+ this.$scope.validationPattern = this.ValidationPattern;
+ this.$scope.urlValidationPattern = this.UrlValidationPattern;
+ this.$scope.labelValidationPattern = this.LabelValidationPattern;
+ this.$scope.integerValidationPattern = this.IntegerValidationPattern;
+ this.$scope.commentValidationPattern = this.CommentValidationPattern;
+ this.$scope.isLoading = false;
+ this.$scope.isNew = (this.formState === Utils.Constants.FormState.CREATE);
+ this.$scope.artifactType = this.artifactsUtils.getArtifactTypeByState(this.$state.current.name);
+ this.$scope.modalInstanceArtifact = this.$modalInstance;
+
+ this.initEditArtifactResourceModel();
+ this.initArtifactTypes();
+
+ // In case of edit, show the file name in browse.
+ if (this.artifact.artifactName!=="" && 'HEAT_ENV'!==this.artifact.artifactType){
+ this.$scope.editArtifactResourceModel.artifactFile = {};
+ this.$scope.editArtifactResourceModel.artifactFile.filename = this.artifact.artifactName;
+ }
+
+ //scope methods
+ this.$scope.isDeploymentHeat = ():boolean => {
+ return !this.$scope.isNew && this.$scope.artifactType === 'deployment' &&
+ 'HEAT' === this.$scope.editArtifactResourceModel.artifactResource.artifactType.substring(0,4);
+ };
+ this.$scope.onFileChange = ():void => {
+ if(this.$scope.editArtifactResourceModel.artifactFile && this.$scope.editArtifactResourceModel.artifactFile.filename) {
+ this.$scope.editArtifactResourceModel.artifactResource.artifactName = this.$scope.editArtifactResourceModel.artifactFile.filename;
+ } else {
+ this.$scope.editArtifactResourceModel.artifactResource.artifactName = this.$scope.originalArtifactName;
+ }
+ };
+ this.$scope.setDefaultTimeout = ():void => {
+ if(this.$scope.isDeploymentHeat() && !this.$scope.editArtifactResourceModel.artifactResource.timeout) {
+ this.$scope.editArtifactResourceModel.artifactResource.timeout = this.$scope.defaultHeatTimeout;
+ }
+ };
+
+ this.$scope.fileExtensions = ():string => {
+ let type:string = this.$scope.editArtifactResourceModel.artifactResource.artifactType;
+ return type && this.$scope.validExtensions && this.$scope.validExtensions[type].acceptedTypes ?
+ this.$scope.validExtensions[type].acceptedTypes.join(',') : "";
+ };
+
+ this.$scope.save = (doNotCloseModal?:boolean):void => {
+ this.$scope.isLoading = true;
+ this.$scope.editArtifactResourceModel.artifactResource.description = this.ValidationUtils.stripAndSanitize(this.$scope.editArtifactResourceModel.artifactResource.description);
+
+ if (!this.$scope.isDeploymentHeat()) {
+ this.$scope.editArtifactResourceModel.artifactResource.timeout = null;
+ }
+
+ if (this.$scope.editArtifactResourceModel.artifactFile) {
+ this.$scope.editArtifactResourceModel.artifactResource.payloadData = this.$scope.editArtifactResourceModel.artifactFile.base64;
+ this.$scope.editArtifactResourceModel.artifactResource.artifactName = this.$scope.editArtifactResourceModel.artifactFile.filename;
+ }
+
+ let onFaild = (response):void => {
+ this.$scope.isLoading = false;
+ console.info('onFaild', response);
+ };
+
+ let onSuccess = (artifactResource:Models.ArtifactModel):void => {
+ this.$scope.isLoading = false;
+ this.$scope.originalArtifactName = "";
+
+ if(this.$scope.isDeploymentHeat()){
+ if(artifactResource.heatParameters) {
+ this.$scope.openEditEnvParametersModal(artifactResource);
+ }
+ }
+
+ if (!doNotCloseModal) {
+ this.$modalInstance.close();
+ //this.artifactArr = [];
+ } else {
+ this.$scope.editArtifactResourceModel.artifactFile = null;
+ angular.element("input[type='file']").val(null); // for support chrome when upload the same file
+ this.artifactsUtils.addAnotherAfterSave(this.$scope);
+ }
+
+ };
+
+ if('HEAT_ENV' == this.artifact.artifactType){
+ this.component.uploadInstanceEnvFile(this.$scope.editArtifactResourceModel.artifactResource).then(onSuccess, onFaild);
+ }else if(this.$scope.isArtifactOwner()){
+ this.component.addOrUpdateInstanceArtifact(this.$scope.editArtifactResourceModel.artifactResource).then(onSuccess, onFaild);
+ }else {
+ this.component.addOrUpdateArtifact(this.$scope.editArtifactResourceModel.artifactResource).then(onSuccess, onFaild);
+ }
+ };
+
+ this.$scope.isArtifactOwner = ():boolean=> {
+ return this.component.isService() && !!this.component.selectedInstance;
+ };
+
+ this.$scope.saveAndAnother = ():void => {
+ this.$scope.save(true);
+ };
+
+ this.$scope.close = ():void => {
+ this.$modalInstance.close();
+ this.artifactArr = [];
+ };
+
+ this.$scope.fileUploadRequired = ():string => {
+ if (this.$scope.editArtifactResourceModel.artifactFile.filename){
+ // This is edit mode
+ return 'false';
+ } else {
+ return 'true';
+ }
+ };
+
+ this.$scope.getFormTitle =(): string =>{
+ if('HEAT_ENV' == this.artifact.artifactType){
+ return 'Update HEAT ENV';
+ }
+ if(this.$scope.isDeploymentHeat()){
+ if(!this.$scope.editArtifactResourceModel.artifactResource.artifactChecksum){
+ return 'Add HEAT Template';
+ }
+ return 'Update HEAT Template';
+ }
+ if(this.$scope.isNew){
+ return 'Add Artifact';
+ }
+ return 'Update Artifact';
+ };
+
+ this.$scope.openEditEnvParametersModal = (artifactResource:Models.ArtifactModel):void => {
+
+ let modalOptions:ng.ui.bootstrap.IModalSettings = {
+ template: this.$templateCache.get('/app/scripts/view-models/forms/env-parameters-form/env-parameters-form.html'),
+ controller: 'Sdc.ViewModels.EnvParametersFormViewModel',
+ size: 'sdc-md',
+ backdrop: 'static',
+ resolve: {
+ artifact: ():Models.ArtifactModel => {
+ return artifactResource;
+ },
+ component: ():Models.Components.Component => {
+ return this.component;
+ }
+ }
+ };
+
+ let modalInstance:ng.ui.bootstrap.IModalServiceInstance = this.$modal.open(modalOptions);
+ modalInstance
+ .result
+ .then(():void => {
+ });
+ };
+
+ this.$scope.forms = {};
+
+ this.initFooterButtons();
+
+
+ this.$scope.$watch("forms.editForm.$invalid", (newVal, oldVal) => {
+ this.$scope.footerButtons[0].disabled = this.$scope.forms.editForm.$invalid;
+ if(this.$scope.isNew){
+ this.$scope.footerButtons[1].disabled = this.$scope.forms.editForm.$invalid;
+ }
+ });
+
+ }
+
+ }
+}
diff --git a/catalog-ui/app/scripts/view-models/forms/artifact-form/artifact-form-view.html b/catalog-ui/app/scripts/view-models/forms/artifact-form/artifact-form-view.html
new file mode 100644
index 0000000000..74a19c8776
--- /dev/null
+++ b/catalog-ui/app/scripts/view-models/forms/artifact-form/artifact-form-view.html
@@ -0,0 +1,169 @@
+<sdc-modal modal="modalInstanceArtifact" type="classic" class="sdc-add-artifact" buttons="footerButtons" header="{{getFormTitle()}}" show-close-button="true" get-close-modal-response="close">
+
+ <loader data-display="isLoading"></loader>
+
+ <div class="sdc-edit-artifact-form-container"
+ data-ng-class="{'mandatory-artifact': (editArtifactResourceModel.artifactResource.mandatory && artifactType !=='deployment') || artifactType === 'api'}">
+ <form novalidate class="w-sdc-form" name="forms.editForm">
+
+ <!--------------------- ARTIFACT FILE START-------------------->
+ <div class="i-sdc-form-item">
+ <label class="required">Upload File</label>
+ <file-upload id="fileUploadElement"
+ form-element="forms.editForm"
+ element-required="{{::fileUploadRequired()}}"
+ element-name="myArtifactFile"
+ file-model="editArtifactResourceModel.artifactFile"
+ extensions="{{fileExtensions()}}"
+ element-disabled="{{!editArtifactResourceModel.artifactResource.artifactType}}"
+ data-ng-class="{'error': forms.editForm.myArtifactFile.$dirty && forms.editForm.myArtifactFile.$invalid}"></file-upload>
+
+ <div class="input-error-file-upload" data-ng-show="forms.editForm.myArtifactFile.$dirty && forms.editForm.myArtifactFile.$invalid">
+ <span ng-show="forms.editForm.myArtifactFile.$error.required && !forms.editForm.myArtifactFile.$error.emptyFile" translate="ADD_ARTIFACT_ERROR_FILE_REQUIRED"></span>
+ <span ng-show="forms.editForm.myArtifactFile.$error.maxsize" translate="VALIDATION_ERROR_MAX_FILE_SIZE"></span>
+ <span ng-if="artifactType === 'deployment'" ng-show="forms.editForm.myArtifactFile.$error.filetype" translate="ADD_ARTIFACT_ERROR_VALID_EXTENSIONS" translate-values="{'extensions': '{{fileExtensions()}}' }"></span>
+ <span ng-show="forms.editForm.myArtifactFile.$error.emptyFile" translate="VALIDATION_ERROR_EMPTY_FILE"></span>
+ </div>
+ </div>
+ <!--------------------- ARTIFACT FILE END -------------------->
+
+ <div class="w-sdc-form-columns-wrapper">
+
+ <div class="w-sdc-form-column" data-ng-if="artifactType === 'deployment' || (!editArtifactResourceModel.artifactResource.mandatory && artifactType !== 'api')">
+
+ <div class="i-sdc-form-item"
+ data-ng-class="{error:(forms.editForm.artifactLabel.$dirty && forms.editForm.artifactLabel.$invalid)}"
+ data-ng-if="!isDeploymentHeat()">
+ <label class="i-sdc-form-label required">Artifact Label</label>
+ <input class="i-sdc-form-input"
+ data-ng-maxlength="25"
+ data-ng-model="editArtifactResourceModel.artifactResource.artifactLabel"
+ type="text"
+ name="artifactLabel"
+ data-required
+ data-ng-model-options="{ debounce: 200 }"
+ data-ng-pattern="labelValidationPattern"
+ maxlength="25"
+ data-ng-disabled="!isNew"
+ data-tests-id="artifact-label"
+ autofocus/>
+
+ <div class="input-error" data-ng-show="forms.editForm.artifactLabel.$dirty && forms.editForm.artifactLabel.$invalid">
+ <span ng-show="forms.editForm.artifactLabel.$error.required" translate="ADD_ARTIFACT_ERROR_LABEL_REQUIRED"></span>
+ <span ng-show="forms.editForm.artifactLabel.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '25' }"></span>
+ <span ng-show="forms.editForm.artifactLabel.$error.pattern" translate="VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED"></span>
+ </div>
+
+ </div>
+
+ <div class="i-sdc-form-item" data-ng-class="{error:(forms.editForm.type.$dirty && forms.editForm.type.$invalid)}">
+ <label class="i-sdc-form-label required">Type</label>
+ <select class="i-sdc-form-select"
+ data-required
+ name="type"
+ data-ng-disabled="!isNew"
+ data-ng-change="setDefaultTimeout()"
+ data-ng-model="editArtifactResourceModel.artifactResource.artifactType"
+ data-ng-options="type as type for type in editArtifactResourceModel.artifactTypes track by type | uppercase"
+ data-tests-id="artifacttype">
+ <option value="">Choose Type</option>
+ </select>
+
+ <div class="input-error" data-ng-show="forms.editForm.type.$dirty && forms.editForm.type.$invalid">
+ <span ng-show="forms.editForm.type.$error.required" translate="ADD_ARTIFACT_ERROR_TYPE_REQUIRED"></span>
+ </div>
+
+ </div>
+
+ <div class="i-sdc-form-item" data-ng-class="{error:(forms.editForm.timeout.$dirty && forms.editForm.timeout.$invalid)}" data-ng-if="isDeploymentHeat()">
+ <label class="i-sdc-form-label">Deployment Timeout (minutes)</label>
+ <input class="i-sdc-form-input"
+ data-ng-maxlength="25"
+ data-ng-model="editArtifactResourceModel.artifactResource.timeout"
+ type="number"
+ name="timeout"
+ min="1"
+ max="2147483647"
+ data-ng-disabled="'HEAT_ENV'==editArtifactResourceModel.artifactResource.artifactType"
+ data-ng-model-options="{ debounce: 200 }"
+ data-ng-pattern="integerValidationPattern"
+ data-ng-init="setDefaultTimeout()"
+ data-ng-change="setDefaultTimeout()"
+ maxlength="25"
+ data-tests-id="timeout" />
+
+ <div class="input-error" data-ng-show="forms.editForm.timeout.$dirty && forms.editForm.timeout.$invalid">
+ <span ng-show="forms.editForm.timeout.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '25' }"></span>
+ <span ng-show="forms.editForm.timeout.$error.pattern" translate="ADD_ARTIFACT_ERROR_TIMEOUT_PATTERN"></span>
+ <span ng-show="forms.editForm.timeout.$error.min" translate="ADD_ARTIFACT_ERROR_TIMEOUT_MIN"></span>
+ </div>
+
+ </div>
+
+ </div><!-- w-sdc-form-column -->
+
+ <div class="w-sdc-form-column i-sdc-form-url" data-ng-if="artifactType==='api'">
+
+ <div class="i-sdc-form-item"
+ data-ng-class="{error:(forms.editForm.apiUrl.$dirty && forms.editForm.apiUrl.$invalid)}">
+ <label class="i-sdc-form-label required">URL</label>
+ <input class="i-sdc-form-input"
+ data-ng-maxlength="100"
+ data-ng-model="editArtifactResourceModel.artifactResource.apiUrl"
+ data-ng-model-options="{ debounce: 200 }"
+ type="url"
+ name="apiUrl"
+ data-required
+ ng-pattern="urlValidationPattern"
+ maxlength="100"
+ autofocus
+ invalid-characters=',#?&@$<>~^`\[]{}|")(*!+=;%' />
+
+ <div class="input-error" data-ng-show="forms.editForm.apiUrl.$dirty && forms.editForm.apiUrl.$invalid">
+ <span ng-show="forms.editForm.apiUrl.$error.required" translate="ADD_ARTIFACT_ERROR_APIURL_REQUIRED"></span>
+ <span ng-show="forms.editForm.apiUrl.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '100' }"></span>
+ <span ng-show="forms.editForm.apiUrl.$error.url || forms.editForm.apiUrl.$error.pattern || forms.editForm.apiUrl.$error.invalidCharacters" translate="ADD_ARTIFACT_ERROR_APIURL_URL"></span>
+ </div>
+
+ </div>
+
+ </div><!-- w-sdc-form-column -->
+
+ <div class="w-sdc-form-column">
+
+ <div class="i-sdc-form-item"
+ data-ng-class="{error:(forms.editForm.description.$dirty && forms.editForm.description.$invalid)}">
+ <label class="i-sdc-form-label required">Description</label>
+ <textarea class="i-sdc-form-textarea"
+ data-ng-maxlength="256"
+ maxlength="256"
+ data-required
+ name="description"
+ data-ng-model="editArtifactResourceModel.artifactResource.description"
+ data-ng-model-options="{ debounce: 200 }"
+ data-ng-pattern="commentValidationPattern"
+ data-tests-id="description"></textarea>
+
+ <div class="input-error" data-ng-show="forms.editForm.description.$dirty && forms.editForm.description.$invalid">
+ <span ng-show="forms.editForm.description.$error.required" translate="ADD_ARTIFACT_ERROR_DESCRIPTION_REQUIRED"></span>
+ <span ng-show="forms.editForm.description.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '256' }"></span>
+ <span ng-show="forms.editForm.description.$error.pattern" translate="ADD_ARTIFACT_ERROR_DESCRIPTION_PATTERN"></span>
+ </div>
+
+ <div class="w-sdc-form-column artifact-info" data-ng-show="!isNew && editArtifactResourceModel.artifactResource.esId">
+ UUID <span data-ng-bind="editArtifactResourceModel.artifactResource.artifactUUID"></span>
+ <br />
+ Version <span data-ng-bind="editArtifactResourceModel.artifactResource.artifactVersion"></span>
+ </div>
+ </div>
+
+ </div><!-- w-sdc-form-column -->
+
+ </div><!-- w-sdc-form-columns-wrapper -->
+
+ <span class="w-sdc-form-note" data-ng-show="forms.editForm.$invalid && false" translate="LABEL_ALL_FIELDS_ARE_MANDATORY"></span>
+
+ </form>
+ </div>
+</sdc-modal>
+
diff --git a/catalog-ui/app/scripts/view-models/forms/artifact-form/artifact-form.less b/catalog-ui/app/scripts/view-models/forms/artifact-form/artifact-form.less
new file mode 100644
index 0000000000..1f77958c88
--- /dev/null
+++ b/catalog-ui/app/scripts/view-models/forms/artifact-form/artifact-form.less
@@ -0,0 +1,44 @@
+.sdc-edit-artifact-form-container {
+
+ .w-sdc-form-note {
+ .h_9;
+ display: block;
+ position: relative;
+ top: 13px;
+ }
+
+ .i-sdc-form-textarea{
+ min-height: 95px;
+ }
+
+ .i-sdc-form-url {
+ padding-bottom: 0px;
+ }
+
+ &.mandatory-artifact {
+ .w-sdc-form-column {
+ width: 100%;
+ padding: 0;
+ min-height: initial;
+ }
+ }
+ .w-sdc-form .i-sdc-form-item.upload input[type="file"] {
+ display: none
+ }
+
+ .artifact-info {
+ text-align: left;
+ color: rgb(140, 140, 140);
+ font-size: 13px;
+ margin-top: -10px;
+ margin-bottom: 5px;
+ width: 100%;
+ min-height: initial;
+
+ span {
+ color: #666666;
+ padding-left: 4px;
+ }
+ }
+
+}
diff --git a/catalog-ui/app/scripts/view-models/forms/attribute-form/attribute-form-view.html b/catalog-ui/app/scripts/view-models/forms/attribute-form/attribute-form-view.html
new file mode 100644
index 0000000000..432b32fbd3
--- /dev/null
+++ b/catalog-ui/app/scripts/view-models/forms/attribute-form/attribute-form-view.html
@@ -0,0 +1,153 @@
+<sdc-modal modal="modalInstanceAttribute" type="classic" class="sdc-edit-attribute-container" buttons="footerButtons" header="{{isNew ? 'Add' : 'Update' }} Attribute" show-close-button="true">
+
+ <div class="sdc-edit-attribute-form-container" >
+ <form novalidate class="w-sdc-form two-columns" name="forms.editForm" >
+
+ <div class="w-sdc-form-columns-wrapper">
+
+ <div class="w-sdc-form-column">
+
+ <!-- Name -->
+ <div class="i-sdc-form-item" data-ng-class="{error:(forms.editForm.attributeName.$dirty && forms.editForm.attributeName.$invalid)}">
+ <label class="i-sdc-form-label required">Name</label>
+ <input class="i-sdc-form-input"
+ data-tests-id="attributeName"
+ data-ng-maxlength="50"
+ data-ng-disabled="!isNew"
+ maxlength="50"
+ data-ng-model="editAttributeModel.attribute.name"
+ type="text"
+ name="attributeName"
+ data-ng-pattern="propertyNameValidationPattern"
+ data-required
+ data-ng-model-options="{ debounce: 200 }"
+ data-ng-change="validateName()"
+ autofocus />
+ <div class="input-error" data-ng-show="forms.editForm.attributeName.$dirty && forms.editForm.attributeName.$invalid">
+ <span ng-show="forms.editForm.attributeName.$error.required" translate="VALIDATION_ERROR_REQUIRED" translate-values="{'field': 'Attribute name' }"></span>
+ <span ng-show="forms.editForm.attributeName.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '128' }"></span>
+ <span ng-show="forms.editForm.attributeName.$error.pattern" translate="VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED"></span>
+ <span ng-show="forms.editForm.attributeName.$error.nameExist" translate="NEW_ATTRIBUTE_ERROR_NAME_EXISTS"></span>
+ </div>
+ </div>
+
+ <!-- Description -->
+ <div class="i-sdc-form-item" data-ng-class="{error:(forms.editForm.description.$dirty && forms.editForm.description.$invalid)}">
+ <label class="i-sdc-form-label">Description</label>
+ <textarea class="i-sdc-form-textarea"
+ data-ng-maxlength="256"
+ data-ng-disabled="editAttributeModel.attribute.readonly"
+ maxlength="256"
+ data-ng-pattern="commentValidationPattern"
+ name="description"
+ data-ng-model="editAttributeModel.attribute.description"
+ data-ng-model-options="{ debounce: 200 }"
+ data-tests-id="description"></textarea>
+ <div class="input-error" data-ng-show="forms.editForm.description.$dirty && forms.editForm.description.$invalid">
+ <span ng-show="forms.editForm.description.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '256' }"></span>
+ <span ng-show="forms.editForm.description.$error.pattern" translate="VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED"></span>
+ <span ng-show="forms.editForm.description.$error.required" translate="VALIDATION_ERROR_REQUIRED" translate-values="{'field': 'Description' }"></span>
+ </div>
+ </div>
+
+
+ </div>
+
+ <div class="w-sdc-form-column">
+ <!-- Type -->
+ <div class="i-sdc-form-item" data-ng-class="{error:(forms.editForm.type.$dirty && forms.editForm.type.$invalid)}">
+ <label class="i-sdc-form-label required">Type</label>
+ <select class="i-sdc-form-select"
+ data-tests-id="type-field"
+ data-required
+ data-ng-disabled="editAttributeModel.attribute.readonly"
+ name="type"
+ data-ng-change="onTypeChange()"
+ data-ng-model="editAttributeModel.attribute.type"
+ data-ng-options="type for type in editAttributeModel.types">
+ <option value="">Choose Type</option>
+ </select>
+ <div class="input-error" data-ng-show="forms.editForm.type.$dirty && forms.editForm.type.$invalid">
+ <span ng-show="forms.editForm.type.$error.required" translate="VALIDATION_ERROR_REQUIRED" translate-values="{'field': 'Type' }"></span>
+ </div>
+ </div>
+
+ <!-- schema -->
+ <div class="i-sdc-form-item" data-ng-class="{error:(forms.editForm.schema.$dirty && forms.editForm.schema.$invalid)}"
+ data-ng-if="showSchema()">
+ <label class="i-sdc-form-label required">Entry Schema</label>
+ <select class="i-sdc-form-select" ng-if="isSchemaEditable()"
+ data-required
+ name="schema"
+ data-ng-disabled="editAttributeModel.attribute.readonly"
+ data-ng-change="onTypeChange(false)"
+ data-ng-model="editAttributeModel.attribute.schema.property.type"
+ data-ng-options="type for type in editAttributeModel.simpleTypes">
+ <option value="">Choose Schema Type</option>
+ </select>
+ <input class="i-sdc-form-input"
+ ng-if="!isSchemaEditable()"
+ data-tests-id="schema"
+ data-ng-disabled="true"
+ data-ng-model="editAttributeModel.attribute.schema.property.type"
+ type="text"
+ name="schema"/>
+ <div class="input-error" data-ng-show="forms.editForm.schema.$dirty && forms.editForm.schema.$invalid">
+ <span ng-show="forms.editForm.schema.$error.required" translate="VALIDATION_ERROR_REQUIRED" translate-values="{'field': 'Entry schema' }"></span>
+ </div>
+ </div>
+
+ <!-- Default value -->
+ <div class="i-sdc-form-item" data-ng-class="{error:(forms.editForm.value.$dirty && forms.editForm.value.$invalid)}">
+ <label class="i-sdc-form-label">Default Value</label>
+ <input class="i-sdc-form-input"
+ data-tests-id="defaultvalue"
+ ng-if="!(editAttributeModel.attribute.type == 'boolean')"
+ data-ng-maxlength="100"
+ data-ng-disabled="editAttributeModel.attribute.readonly && !isAttributeValueOwner()"
+ maxlength="100"
+ data-ng-model="editAttributeModel.attribute[isAttributeValueOwner()?'value':'defaultValue']"
+ type="text"
+ name="value"
+ data-custom-validation="" data-validation-func="validateUniqueKeys"
+ data-tests-id="defaultvalue"
+ data-ng-pattern="validationPattern"
+ data-ng-model-options="{ debounce: 200 }"
+ data-ng-change="!forms.editForm.value.$error.pattern && ('integer'==editAttributeModel.attribute.type && forms.editForm.value.$setValidity('pattern', validateIntRange(editAttributeModel.attribute.value)) || onValueChange())"
+ autofocus />
+ <select class="i-sdc-form-select"
+ data-tests-id="booleantype"
+ ng-if="editAttributeModel.attribute.type == 'boolean'"
+ data-ng-disabled="editAttributeModel.attribute.readonly && !isAttributeValueOwner()"
+ name="value"
+ data-ng-change="onValueChange()"
+ data-ng-model="editAttributeModel.attribute[isAttributeValueOwner()?'value':'defaultValue']">
+ <option value="true">true</option>
+ <option value="false">false</option>
+ </select>
+ <div class="input-error" data-ng-show="forms.editForm.value.$dirty && forms.editForm.value.$invalid">
+ <span ng-show="forms.editForm.value.$error.required" translate="VALIDATION_ERROR_REQUIRED" translate-values="{'field': 'Default value' }"></span>
+ <span ng-show="forms.editForm.value.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '100' }"></span>
+ <span ng-show="forms.editForm.value.$error.pattern" translate="{{getValidationTranslate()}}"></span>
+ <span ng-show="forms.editForm.value.$error.customValidation" translate="ATTRIBUTE_EDIT_MAP_UNIQUE_KEYS"></span>
+ </div>
+ </div>
+
+ <!-- hidden -->
+ <div class="i-sdc-form-item" data-ng-if="isAttributeValueOwner()">
+ <label class="i-sdc-form-label">Hidden</label>
+ <input class="i-sdc-form-input"
+ data-tests-id="hidden"
+ data-ng-disabled="editAttributeModel.attribute.readonly && !isAttributeValueOwner()"
+ data-ng-model="editAttributeModel.attribute.hidden"
+ type="checkbox"
+ name="hidden"/>
+ </div>
+ </div>
+
+ </div>
+
+ </form>
+ </div>
+
+</sdc-modal>
diff --git a/catalog-ui/app/scripts/view-models/forms/attribute-form/attribute-from-view-model.ts b/catalog-ui/app/scripts/view-models/forms/attribute-form/attribute-from-view-model.ts
new file mode 100644
index 0000000000..d369cfa5d1
--- /dev/null
+++ b/catalog-ui/app/scripts/view-models/forms/attribute-form/attribute-from-view-model.ts
@@ -0,0 +1,255 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+/// <reference path="../../../references"/>
+
+module Sdc.ViewModels {
+ 'use strict';
+
+ export interface IEditAttributeModel {
+ attribute: Models.AttributeModel;
+ types: Array<string>;
+ simpleTypes: Array<string>;
+ }
+
+ interface IAttributeFormViewModelScope extends ng.IScope {
+ $$childTail: any;
+ forms:any;
+ editForm:ng.IFormController;
+ footerButtons: Array<any>;
+ isService: boolean;
+ editAttributeModel: IEditAttributeModel;
+ modalInstanceAttribute:ng.ui.bootstrap.IModalServiceInstance;
+ isNew: boolean;
+ listRegex: Sdc.Utils.IMapRegex;
+ mapRegex: Sdc.Utils.IMapRegex;
+ propertyNameValidationPattern: RegExp;
+ commentValidationPattern: RegExp;
+ isLoading: boolean;
+ validationPattern: RegExp;
+
+ save():void;
+ close(): void;
+ onTypeChange():void;
+ onValueChange(): void;
+ isAttributeValueOwner():boolean;
+ validateIntRange(value:string):boolean;
+ validateUniqueKeys(viewValue:string):boolean;
+ getValidationTranslate(): string;
+ showSchema(): boolean;
+ isSchemaEditable(): boolean;
+ validateName():void;
+ }
+
+ export class AttributeFormViewModel {
+
+ static '$inject' = [
+ '$scope',
+ '$modalInstance',
+ 'attribute',
+ 'ValidationUtils',
+ 'CommentValidationPattern',
+ 'PropertyNameValidationPattern',
+ 'component'
+ ];
+
+ private formState: Sdc.Utils.Constants.FormState;
+
+
+ constructor(private $scope:IAttributeFormViewModelScope,
+ private $modalInstance:ng.ui.bootstrap.IModalServiceInstance,
+ private attribute: Models.AttributeModel,
+ private ValidationUtils:Sdc.Utils.ValidationUtils,
+ private CommentValidationPattern:RegExp,
+ private PropertyNameValidationPattern: RegExp,
+ private component: Models.Components.Component) {
+ this.formState = angular.isDefined(attribute.name) ? Utils.Constants.FormState.UPDATE : Utils.Constants.FormState.CREATE;
+ this.initScope();
+ }
+
+ private initResource = ():void => {
+ this.$scope.editAttributeModel.attribute = new Sdc.Models.AttributeModel(this.attribute);
+ if (this.$scope.editAttributeModel.types.indexOf(this.attribute.type) === -1) {//attribute defaulte type is string too?
+ this.attribute.type = "string";
+ }
+ };
+
+ private initEditAttributeModel = ():void => {
+ this.$scope.editAttributeModel = {
+ attribute: null,
+ types: ['integer', 'string', 'float', 'boolean', 'list', 'map'],
+ simpleTypes: ['integer', 'string', 'float', 'boolean']
+ };
+
+ this.initResource();
+ };
+
+ private initScope = ():void => {
+
+ //scope attributes
+ this.$scope.forms = {};
+ this.$scope.propertyNameValidationPattern = this.PropertyNameValidationPattern;
+ this.$scope.commentValidationPattern = this.CommentValidationPattern;
+
+ this.$scope.modalInstanceAttribute = this.$modalInstance;
+ this.$scope.listRegex = this.ValidationUtils.getPropertyListPatterns();
+ this.$scope.mapRegex = this.ValidationUtils.getPropertyMapPatterns();
+
+ this.$scope.isNew = (this.formState === Utils.Constants.FormState.CREATE);
+ this.$scope.isLoading = false;
+
+ this.initEditAttributeModel();
+ this.setValidationPattern();
+
+ //scope methods
+ this.$scope.save = ():void => {
+ if(!this.$scope.forms.editForm.$invalid){
+ let attribute:Models.AttributeModel = this.$scope.editAttributeModel.attribute;
+ this.$scope.editAttributeModel.attribute.description = this.ValidationUtils.stripAndSanitize(this.$scope.editAttributeModel.attribute.description);
+ ////if read only - just closes the modal
+ if (this.$scope.editAttributeModel.attribute.readonly && !this.$scope.isAttributeValueOwner()) {
+ this.$modalInstance.close();
+ return;
+ }
+ this.$scope.isLoading = true;
+ let onAttributeFaild = (response):void => {
+ console.info('onFaild', response);
+ this.$scope.isLoading = false;
+ };
+
+ let onAttributeSuccess = (attributeFromBE:Models.AttributeModel):void => {
+ console.info('onAttributeResourceSuccess : ', attributeFromBE);
+ this.$scope.isLoading = false;
+ this.$modalInstance.close();
+ };
+
+ //in case we have uniqueId we call update method
+ if (this.$scope.isAttributeValueOwner()) {
+ this.component.updateInstanceAttribute(attribute).then(onAttributeSuccess, onAttributeFaild);
+ } else {
+ this.component.addOrUpdateAttribute(attribute).then(onAttributeSuccess, onAttributeFaild);
+ }
+ }
+ };
+
+ this.$scope.close = ():void => {
+ this.$modalInstance.close();
+ };
+
+ this.$scope.validateName = ():void => {
+ let existsAttr: Models.AttributeModel = _.find(this.component.attributes, (attribute:Models.AttributeModel) => {
+ return attribute.name === this.$scope.editAttributeModel.attribute.name;
+ });
+ if(existsAttr){
+ this.$scope.forms.editForm["attributeName"].$setValidity('nameExist', false);
+ }else{
+ this.$scope.forms.editForm["attributeName"].$setValidity('nameExist', true);
+ }
+
+ };
+
+ this.$scope.onTypeChange = ():void => {
+ this.$scope.editAttributeModel.attribute.value = '';
+ this.$scope.editAttributeModel.attribute.defaultValue = '';
+ this.setValidationPattern();
+ };
+
+ this.$scope.isAttributeValueOwner = ():boolean=> {
+ return this.component.isService() || !!this.component.selectedInstance;
+ };
+
+ this.$scope.onValueChange = ():void => {
+ if (!this.$scope.editAttributeModel.attribute.value) {
+ if (this.$scope.isAttributeValueOwner()) {
+ this.$scope.editAttributeModel.attribute.value = this.$scope.editAttributeModel.attribute.defaultValue;
+ }
+ }
+ };
+
+
+ this.$scope.validateUniqueKeys = (viewValue:string) : boolean => {
+ if(this.$scope.editAttributeModel.attribute.type === 'map') {
+ return this.ValidationUtils.validateUniqueKeys(viewValue);
+ }
+ else {
+ return true; //always valid if not a map
+ }
+ };
+
+ this.$scope.validateIntRange = (value:string):boolean => {
+ return !value || this.ValidationUtils.validateIntRange(value);
+ };
+
+ this.$scope.isSchemaEditable = () :boolean => {
+ let schemaType=this.$scope.editAttributeModel.attribute.schema.property.type;
+ return this.$scope.editAttributeModel.simpleTypes.indexOf(schemaType) > -1||!schemaType;
+ };
+
+ this.$scope.showSchema = () :boolean => {
+ return ['list', 'map'].indexOf(this.$scope.editAttributeModel.attribute.type) > -1;
+ };
+
+ this.$scope.getValidationTranslate = () : string => {
+ let result = "ATTRIBUTE_EDIT_PATTERN";
+ if (this.$scope.showSchema()) {
+
+ result = "ATTRIBUTE_EDIT_" + this.$scope.editAttributeModel.attribute.type.toUpperCase();
+
+ if(this.$scope.editAttributeModel.attribute.schema.property.type === Utils.Constants.PROPERTY_TYPES.STRING) {
+ result += "_STRING";
+ }else if(this.$scope.editAttributeModel.attribute.schema.property.type === Utils.Constants.PROPERTY_TYPES.BOOLEAN) {
+ result += "_BOOLEAN";
+ } else {
+ result += "_GENERIC";
+ }
+ }
+
+ return result;
+ };
+
+ // Add the done button at the footer.
+ this.$scope.footerButtons = [
+ {'name': 'Done', 'css':'blue', 'callback': this.$scope.save},
+ {'name':'Cancel', 'css':'grey', 'callback': this.$scope.close}
+ ];
+
+ this.$scope.$watchCollection("forms.editForm.$invalid", (newVal, oldVal) => {
+ this.$scope.footerButtons[0].disabled = this.$scope.forms.editForm.$invalid;
+ });
+
+ }
+
+
+ private setValidationPattern = ():void => {
+
+ if(this.$scope.editAttributeModel.attribute.type === 'list') {
+ this.$scope.validationPattern = this.$scope.listRegex[this.$scope.editAttributeModel.attribute.schema.property.type];
+ }
+ else if(this.$scope.editAttributeModel.attribute.type === 'map') {
+ this.$scope.validationPattern = this.$scope.mapRegex[this.$scope.editAttributeModel.attribute.schema.property.type];
+ }
+ else{
+ this.$scope.validationPattern = this.ValidationUtils.getValidationPattern(this.$scope.editAttributeModel.attribute.type);
+ }
+
+ };
+
+
+ }
+}
diff --git a/catalog-ui/app/scripts/view-models/forms/env-parameters-form/env-parameters-form.html b/catalog-ui/app/scripts/view-models/forms/env-parameters-form/env-parameters-form.html
new file mode 100644
index 0000000000..69367dc68c
--- /dev/null
+++ b/catalog-ui/app/scripts/view-models/forms/env-parameters-form/env-parameters-form.html
@@ -0,0 +1,39 @@
+<sdc-modal modal="envParametersModal" type="classic" class="sdc-env-form-container" buttons="saveButton" header="{{isInstance()?'HEAT Template':'Update Parameters'}}" show-close-button="true">
+ <div class="sdc-env-form-container">
+ <div class="w-sdc-modal-body">
+ <span class="w-sdc-modal-body-content" data-ng-if="!isInstance()" translate="UPDATE_PARAMETERS_TEXT"></span>
+ <form novalidate class="" name="editForm">
+ <perfect-scrollbar class="perfect-scrollbar w-sdc-form w-sdc-env-form-container">
+ <div class="i-sdc-form-item" data-ng-repeat="parameter in heatParameters track by $index">
+ <div class="left-column-container">
+ <ng-form name="editForm">
+ <label class="i-sdc-env-form-label" data-ng-class="{required:parameter.defaultValue}"
+ data-ng-bind="parameter.name +' (' + parameter.type + ')'" tooltips tooltip-content="{{parameter.name +' (' + parameter.type + ')'}}"></label>
+ <input class="i-sdc-form-input" data-ng-class="{error:(editForm.currentValue.$invalid)}"
+ data-ng-model-options="{ debounce: 200 }"
+ data-ng-model="parameter.currentValue"
+ type="text"
+ name="currentValue"
+ data-ng-pattern="getValidationPattern(parameter.type, 'heat')"
+ data-ng-required="parameter.defaultValue"
+ data-ng-change="'json'==parameter.type && editForm.currentValue.$setValidity('pattern', validateJson(parameter.currentValue))"
+ data-ng-blur="(editForm.currentValue.$error.required && (parameter.currentValue=parameter.defaultValue))"
+ />
+
+ <div class="input-error" data-ng-show="editForm.currentValue.$invalid">
+ <span ng-show="editForm.currentValue.$error.required" translate="VALIDATION_ERROR_REQUIRED" translate-values="{'field': 'Value'}"></span>
+ <span ng-show="editForm.currentValue.$error.pattern && parameter.type==='string'" translate="VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED"></span>
+ <span ng-show="editForm.currentValue.$error.pattern && !(parameter.type==='string')" translate="VALIDATION_ERROR_TYPE" translate-values="{'type': '{{parameter.type}}'}"></span>
+ </div>
+ </ng-form>
+ </div>
+ <div class="i-sdc-env-form-label-description">
+ <label class="i-sdc-env-form-label" data-ng-bind="parameter.description" tooltips tooltip-content="{{parameter.description}}"></label>
+ </div>
+ </div>
+ </perfect-scrollbar>
+ <div class="env-file-generation-label" data-ng-if="isInstance()" translate="ENV_FILE_GENERATION"></div>
+ </form>
+ </div>
+ </div>
+</sdc-modal>
diff --git a/catalog-ui/app/scripts/view-models/forms/env-parameters-form/env-parameters-form.less b/catalog-ui/app/scripts/view-models/forms/env-parameters-form/env-parameters-form.less
new file mode 100644
index 0000000000..c58c94ab22
--- /dev/null
+++ b/catalog-ui/app/scripts/view-models/forms/env-parameters-form/env-parameters-form.less
@@ -0,0 +1,74 @@
+
+.sdc-env-form-container{
+ .w-sdc-modal-body{
+ padding: 20px 10px 2px 10px;
+ }
+ .w-sdc-modal-body-content{
+ .b_6;
+ display: block;
+ }
+
+ .env-file-generation-label{
+ .p_9;
+ .bold;
+ margin-bottom: 20px;
+ }
+}
+
+.w-sdc-env-form-container {
+ border-top: 1px solid #cdcdcd;
+ border-bottom: 1px solid #cdcdcd;
+ height: 356px;
+ margin: 35px 0 10px 0;
+
+ .w-sdc-form {
+ text-align: left;
+ }
+ .i-sdc-form-item{
+ display: inline-block;
+ .description{
+ margin-bottom: 2px;
+ vertical-align: baseline;
+ padding: 32px 0 0 0;
+ text-transform: capitalize;
+ .b_1;
+ }
+ }
+ .left-column-container{
+ width: 250px;
+ float: left;
+ .i-sdc-env-form-label {
+ overflow: hidden;
+ max-width: 100%;
+ text-overflow: ellipsis;
+ display: inline-block;
+ white-space: nowrap;
+
+ &.required::before {
+ color: #f33;
+ content: '*';
+ margin-right: 4px;
+ }
+ }
+ }
+ .i-sdc-env-form-label-description {
+ float: right;
+
+ .i-sdc-env-form-label {
+ .p_9;
+ // height: 20px;
+ margin: 30px 0px 0px 30px;
+ overflow: hidden;
+ max-width: 245px;
+ text-overflow: ellipsis;
+ display: inline-block;
+ white-space: nowrap;
+
+ &.required::before {
+ color: #f33;
+ content: '*';
+ margin-right: 4px;
+ }
+ }
+ }
+}
diff --git a/catalog-ui/app/scripts/view-models/forms/env-parameters-form/env-parameters-form.ts b/catalog-ui/app/scripts/view-models/forms/env-parameters-form/env-parameters-form.ts
new file mode 100644
index 0000000000..d1bae440cc
--- /dev/null
+++ b/catalog-ui/app/scripts/view-models/forms/env-parameters-form/env-parameters-form.ts
@@ -0,0 +1,149 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+/// <reference path="../../../references"/>
+
+module Sdc.ViewModels {
+ 'use strict';
+
+ export interface IEnvParametersFormViewModelScope extends ng.IScope {
+ isLoading: boolean;
+ type:string;
+ heatParameters:any;
+ editForm:ng.IFormController;
+ artifactResource:Models.ArtifactModel;
+ saveButton: Array<any>;
+ envParametersModal: ng.ui.bootstrap.IModalServiceInstance;
+
+ getValidationPattern(type:string):RegExp;
+ isInstance():boolean;
+ validateJson(json:string):boolean;
+ close(): void;
+ save():void;
+ }
+
+ export class EnvParametersFormViewModel {
+
+
+ static '$inject' = [
+ '$scope',
+ '$state',
+ '$modalInstance',
+ 'artifact',
+ // 'ArtifactsUtils',
+ 'ValidationUtils',
+ 'component'
+ ];
+
+
+ constructor(private $scope:IEnvParametersFormViewModelScope,
+ private $state:any,
+ private $modalInstance:ng.ui.bootstrap.IModalServiceInstance,
+ private artifact:Models.ArtifactModel,
+ // private artifactsUtils:Sdc.Utils.ArtifactsUtils,
+ private ValidationUtils: Sdc.Utils.ValidationUtils,
+ private component:Models.Components.Component) {
+
+
+ this.initScope();
+ }
+
+ private updateInstanceHeat = ():void => {
+ let success =(responseArtifact:Models.ArtifactModel): void => {
+ this.$scope.isLoading = false;
+ this.$modalInstance.close();
+ };
+
+ let error = ():void => {
+ this.$scope.isLoading = false;
+ console.info('Failed to load save artifact');
+ };
+
+ this.component.addOrUpdateInstanceArtifact(this.$scope.artifactResource).then(success, error);
+
+ };
+
+ private initScope = ():void => {
+ this.$scope.envParametersModal = this.$modalInstance;
+ this.$scope.artifactResource= this.artifact;
+ this.$scope.heatParameters = angular.copy(this.artifact.heatParameters);
+
+ this.$scope.getValidationPattern = (validationType:string , parameterType?:string):RegExp => {
+ return this.ValidationUtils.getValidationPattern(validationType, parameterType);
+ };
+
+ this.$scope.validateJson = (json:string):boolean => {
+ if(!json){
+ return true;
+ }
+ return this.ValidationUtils.validateJson(json);
+ };
+
+ this.$scope.isInstance =(): boolean =>{
+ return !!this.component.selectedInstance;
+ };
+
+
+ this.$scope.save = ():void => {
+ this.$scope.isLoading = true;
+ this.artifact.heatParameters = this.$scope.heatParameters;
+ this.artifact.heatParameters.forEach((parameter:any):void => {
+ /* if ("" === parameter.currentValue) {
+ parameter.currentValue = null;
+ }else */
+ if(!parameter.currentValue && parameter.defaultValue) {
+ parameter.currentValue = parameter.defaultValue;
+ }
+ });
+
+ if(this.$scope.isInstance()){
+ this.updateInstanceHeat();
+ return;
+ }
+
+ let success =(responseArtifact:Models.ArtifactModel): void => {
+ this.$scope.isLoading = false;
+ this.$modalInstance.close();
+
+ };
+
+ let error = ():void => {
+ this.$scope.isLoading = false;
+ console.info('Failed to load save artifact');
+ };
+
+ this.component.addOrUpdateArtifact(this.$scope.artifactResource).then(success, error);
+ };
+
+ this.$scope.saveButton = [
+ {'name': 'Save', 'css': 'blue', 'callback': this.$scope.save}
+ ];
+
+ this.$scope.close = ():void => {
+ //this.artifact.heatParameters.forEach((parameter:any):void => {
+ // if (!parameter.currentValue && parameter.defaultValue) {
+ // parameter.currentValue = parameter.defaultValue;
+ // }
+ //});
+ this.$modalInstance.dismiss();
+ };
+
+ };
+ }
+}
diff --git a/catalog-ui/app/scripts/view-models/forms/property-form/property-form-view-model.ts b/catalog-ui/app/scripts/view-models/forms/property-form/property-form-view-model.ts
new file mode 100644
index 0000000000..c9732aa9a6
--- /dev/null
+++ b/catalog-ui/app/scripts/view-models/forms/property-form/property-form-view-model.ts
@@ -0,0 +1,330 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+/// <reference path="../../../references"/>
+
+module Sdc.ViewModels {
+ 'use strict';
+
+ export interface IEditPropertyModel {
+ property: Models.PropertyModel;
+ types: Array<string>;
+ simpleTypes: Array<string>;
+ sources: Array<string>;
+ }
+
+ interface IPropertyFormViewModelScope extends ng.IScope {
+ forms:any;
+ editForm:ng.IFormController;
+ footerButtons: Array<any>;
+ isNew: boolean;
+ isLoading: boolean;
+ isService: boolean;
+ validationPattern: RegExp;
+ propertyNameValidationPattern: RegExp;
+ commentValidationPattern: RegExp;
+ editPropertyModel: IEditPropertyModel;
+ modalInstanceProperty:ng.ui.bootstrap.IModalServiceInstance;
+ currentPropertyIndex:number;
+ isLastProperty:boolean;
+ myValue:any;
+ nonPrimitiveTypes:Array<string>;
+ dataTypes:Models.DataTypesMap;
+ isTypeDataType:boolean;
+ maxLength:number;
+
+ save(doNotCloseModal?:boolean): void;
+ getValidationPattern(type:string): RegExp;
+ validateIntRange(value:string):boolean;
+ close(): void;
+ onValueChange(): void;
+ onSchemaTypeChange():void;
+ onTypeChange(resetSchema:boolean): void;
+ isPropertyValueOwner():boolean;
+ showSchema(): boolean;
+ delete(property:Models.PropertyModel): void;
+ getPrev(): void;
+ getNext(): void;
+ isSimpleType(typeName:string):boolean;
+ getDefaultValue():any;
+ }
+
+ export class PropertyFormViewModel {
+
+ static '$inject' = [
+ '$scope',
+ 'Sdc.Services.DataTypesService',
+ '$modalInstance',
+ 'property',
+ 'ValidationPattern',
+ 'PropertyNameValidationPattern',
+ 'CommentValidationPattern',
+ 'ValidationUtils',
+ 'component',
+ '$filter',
+ 'ModalsHandler',
+ 'filteredProperties',
+ '$timeout'
+ ];
+
+ private formState: Sdc.Utils.Constants.FormState;
+
+ constructor(private $scope:IPropertyFormViewModelScope,
+ private DataTypesService:Sdc.Services.DataTypesService,
+ private $modalInstance:ng.ui.bootstrap.IModalServiceInstance,
+ private property: Models.PropertyModel,
+ private ValidationPattern:RegExp,
+ private PropertyNameValidationPattern: RegExp,
+ private CommentValidationPattern:RegExp,
+ private ValidationUtils:Sdc.Utils.ValidationUtils,
+ private component: Models.Components.Component,
+ private $filter:ng.IFilterService,
+ private ModalsHandler:Utils.ModalsHandler,
+ private filteredProperties: Array<Models.PropertyModel>,
+ private $timeout: ng.ITimeoutService) {
+
+ this.formState = angular.isDefined(property.name) ? Utils.Constants.FormState.UPDATE : Utils.Constants.FormState.CREATE;
+ this.initScope();
+ }
+
+ private initResource = ():void => {
+ this.$scope.editPropertyModel.property = new Sdc.Models.PropertyModel(this.property);
+ this.$scope.editPropertyModel.property.type = this.property.type? this.property.type: null;
+ this.setMaxLength();
+ // if (this.$scope.editPropertyModel.types.indexOf(this.property.type) === -1 && !this.$scope.isNew) {
+ // this.property.type = "string";
+ // }
+ };
+
+ private initEditPropertyModel = ():void => {
+ this.$scope.editPropertyModel = {
+ property: null,
+ types: Utils.Constants.PROPERTY_DATA.TYPES,
+ simpleTypes: Utils.Constants.PROPERTY_DATA.SIMPLE_TYPES,
+ sources: Utils.Constants.PROPERTY_DATA.SOURCES
+ };
+
+ this.initResource();
+ };
+
+ private initForNotSimpleType = ():void => {
+ let property = this.$scope.editPropertyModel.property;
+ this.$scope.isTypeDataType=this.DataTypesService.isDataTypeForPropertyType(this.$scope.editPropertyModel.property,this.$scope.dataTypes);
+ if(property.type && this.$scope.editPropertyModel.simpleTypes.indexOf(property.type)==-1){
+ if(!(property.value||property.defaultValue)) {
+ switch (property.type) {
+ case Utils.Constants.PROPERTY_TYPES.MAP:
+ this.$scope.myValue = {'':null};
+ break;
+ case Utils.Constants.PROPERTY_TYPES.LIST:
+ this.$scope.myValue = [];
+ break;
+ default:
+ this.$scope.myValue = {};
+ }
+ }else{
+ this.$scope.myValue = JSON.parse(property.value||property.defaultValue);
+ }
+ }
+ };
+
+ private setMaxLength = ():void => {
+ switch (this.$scope.editPropertyModel.property.type) {
+ case Utils.Constants.PROPERTY_TYPES.MAP:
+ case Utils.Constants.PROPERTY_TYPES.LIST:
+ this.$scope.maxLength = this.$scope.editPropertyModel.property.schema.property.type == Utils.Constants.PROPERTY_TYPES.JSON?
+ Utils.Constants.PROPERTY_VALUE_CONSTRAINTS.JSON_MAX_LENGTH:
+ Utils.Constants.PROPERTY_VALUE_CONSTRAINTS.MAX_LENGTH;
+ break;
+ case Utils.Constants.PROPERTY_TYPES.JSON:
+ this.$scope.maxLength = Utils.Constants.PROPERTY_VALUE_CONSTRAINTS.JSON_MAX_LENGTH;
+ break;
+ default:
+ this.$scope.maxLength = Utils.Constants.PROPERTY_VALUE_CONSTRAINTS.MAX_LENGTH;
+ }
+ };
+
+
+ private initScope = ():void => {
+
+ //scope properties
+ this.$scope.forms = {};
+ this.$scope.validationPattern = this.ValidationPattern;
+ this.$scope.propertyNameValidationPattern = this.PropertyNameValidationPattern;
+ this.$scope.commentValidationPattern = this.CommentValidationPattern;
+ this.$scope.isLoading = false;
+ this.$scope.isNew = (this.formState === Utils.Constants.FormState.CREATE);
+ this.$scope.isService = this.component.isService();
+ this.$scope.modalInstanceProperty = this.$modalInstance;
+ this.$scope.currentPropertyIndex = _.findIndex(this.filteredProperties, i=> i.name == this.property.name );
+ this.$scope.isLastProperty= this.$scope.currentPropertyIndex==(this.filteredProperties.length-1);
+
+ this.initEditPropertyModel();
+
+ this.DataTypesService.getAllDataTypes().then((response:any) => {
+ this.$scope.dataTypes = response;
+ delete response['tosca.datatypes.Root'];
+ this.$scope.nonPrimitiveTypes =_.filter(Object.keys(response),(type:string)=>{
+ return this.$scope.editPropertyModel.types.indexOf(type)==-1;
+ });
+ this.initForNotSimpleType();
+ }, (err)=> {});
+
+
+
+
+
+ //scope methods
+ this.$scope.save = (doNotCloseModal?:boolean):void => {
+ let property:Models.PropertyModel = this.$scope.editPropertyModel.property;
+ this.$scope.editPropertyModel.property.description = this.ValidationUtils.stripAndSanitize(this.$scope.editPropertyModel.property.description);
+ ////if read only - just closes the modal
+ if (this.$scope.editPropertyModel.property.readonly && !this.$scope.isPropertyValueOwner()) {
+ this.$modalInstance.close();
+ return;
+ }
+
+ this.$scope.isLoading = true;
+
+ let onPropertyFaild = (response):void => {
+ console.info('onFaild', response);
+ this.$scope.isLoading = false;
+ };
+
+ let onPropertySuccess = (propertyFromBE:Models.PropertyModel):void => {
+ console.info('onPropertyResourceSuccess : ', propertyFromBE);
+ this.$scope.isLoading = false;
+
+ if (!doNotCloseModal) {
+ this.$modalInstance.close();
+ } else {
+ this.$scope.forms.editForm.$setPristine();
+ this.$scope.editPropertyModel.property = new Models.PropertyModel();
+ }
+ };
+
+ //in case we have uniqueId we call update method
+ if (this.$scope.isPropertyValueOwner()) {
+ if(!this.$scope.editPropertyModel.property.simpleType && !this.$scope.isSimpleType(property.type)){
+ let myValueString:string = JSON.stringify(this.$scope.myValue);
+ property.value = myValueString;
+ }
+ this.component.updateInstanceProperty(property).then(onPropertySuccess, onPropertyFaild);
+ } else {
+ if(!this.$scope.editPropertyModel.property.simpleType && !this.$scope.isSimpleType(property.type)){
+ let myValueString:string = JSON.stringify(this.$scope.myValue);
+ property.defaultValue = myValueString;
+ }else{
+ this.$scope.editPropertyModel.property.defaultValue = this.$scope.editPropertyModel.property.value;
+ }
+ this.component.addOrUpdateProperty(property).then(onPropertySuccess, onPropertyFaild);
+ }
+ };
+
+
+ this.$scope.isPropertyValueOwner = ():boolean=> {
+ return this.component.isService() || !!this.component.selectedInstance;
+ };
+
+ this.$scope.getPrev = ():void=> {
+ this.property = this.filteredProperties[--this.$scope.currentPropertyIndex];
+ this.initResource();
+ this.initForNotSimpleType();
+ this.$scope.isLastProperty=false;
+ };
+
+ this.$scope.getNext = ():void=> {
+ this.property = this.filteredProperties[++this.$scope.currentPropertyIndex];
+ this.initResource();
+ this.initForNotSimpleType();
+ this.$scope.isLastProperty= this.$scope.currentPropertyIndex==(this.filteredProperties.length-1);
+ };
+
+ this.$scope.isSimpleType = (typeName:string):boolean=>{
+ return typeName && this.$scope.editPropertyModel.simpleTypes.indexOf(typeName)!=-1;
+ };
+
+ this.$scope.showSchema = () :boolean => {
+ return [Utils.Constants.PROPERTY_TYPES.LIST, Utils.Constants.PROPERTY_TYPES.MAP].indexOf(this.$scope.editPropertyModel.property.type) > -1;
+ };
+
+ this.$scope.getValidationPattern = (type:string):RegExp => {
+ return this.ValidationUtils.getValidationPattern(type);
+ };
+
+ this.$scope.validateIntRange = (value:string):boolean => {
+ return !value || this.ValidationUtils.validateIntRange(value);
+ };
+
+ this.$scope.close = ():void => {
+ this.$modalInstance.close();
+ };
+
+ // put default value when instance value is empty
+ this.$scope.onValueChange = ():void => {
+ if (!this.$scope.editPropertyModel.property.value) {
+ if (this.$scope.isPropertyValueOwner()) {
+ this.$scope.editPropertyModel.property.value = this.$scope.editPropertyModel.property.defaultValue;
+ }
+ }
+ };
+
+ // Add the done button at the footer.
+ this.$scope.footerButtons = [
+ {'name': 'Save', 'css': 'blue', 'callback': this.$scope.save },
+ {'name': 'Cancel', 'css': 'grey', 'callback':this.$scope.close }
+ ];
+
+ this.$scope.$watch("forms.editForm.$invalid", (newVal, oldVal) => {
+ this.$scope.footerButtons[0].disabled = this.$scope.forms.editForm.$invalid;
+ });
+
+ this.$scope.getDefaultValue = ():any => {
+ return this.$scope.isPropertyValueOwner() ? this.$scope.editPropertyModel.property.defaultValue : null;
+ };
+
+ this.$scope.onTypeChange = ():void => {
+ this.$scope.editPropertyModel.property.value = '';
+ this.$scope.editPropertyModel.property.defaultValue = '';
+ this.setMaxLength();
+ this.initForNotSimpleType();
+ };
+
+ this.$scope.onSchemaTypeChange = ():void => {
+ if(this.$scope.editPropertyModel.property.type==Utils.Constants.PROPERTY_TYPES.MAP){
+ this.$scope.myValue={'':null};
+ }else if(this.$scope.editPropertyModel.property.type==Utils.Constants.PROPERTY_TYPES.LIST){
+ this.$scope.myValue=[];
+ }
+ this.setMaxLength();
+ };
+
+ this.$scope.delete = (property:Models.PropertyModel):void => {
+ let onOk = ():void => {
+ this.component.deleteProperty(property.uniqueId).then(
+ this.$scope.close
+ );
+ };
+ let title:string = this.$filter('translate')("PROPERTY_VIEW_DELETE_MODAL_TITLE");
+ let message:string = this.$filter('translate')("PROPERTY_VIEW_DELETE_MODAL_TEXT", "{'name': '" + property.name + "'}");
+ this.ModalsHandler.openConfirmationModal(title, message, false).then(onOk);
+ };
+ }
+ }
+}
diff --git a/catalog-ui/app/scripts/view-models/forms/property-form/property-form-view.html b/catalog-ui/app/scripts/view-models/forms/property-form/property-form-view.html
new file mode 100644
index 0000000000..d593d47a77
--- /dev/null
+++ b/catalog-ui/app/scripts/view-models/forms/property-form/property-form-view.html
@@ -0,0 +1,219 @@
+<sdc-modal modal="modalInstanceProperty" type="classic" class="sdc-edit-property-container" buttons="footerButtons" header="{{isNew ? 'Add' : 'Update' }} Property" show-close-button="true" data-tests-id="sdc-edit-property-container">
+ <div class="sdc-modal-top-bar" data-ng-if="!isNew">
+ <div class="sdc-modal-top-bar-buttons">
+ <span ng-click="delete(editPropertyModel.property)" data-ng-class="{'disabled' : isPropertyValueOwner()||editPropertyModel.property.readonly}" class="sprite-new delete-btn" data-tests-id="delete_property" sdc-smart-tooltip="">Delete</span>
+ <span class="delimiter"></span>
+ <span data-ng-click="getPrev()" data-ng-class="{'disabled' : !currentPropertyIndex }" class="sprite-new left-arrow" data-tests-id="get-prev" sdc-smart-tooltip="">Previous</span>
+ <span data-ng-click="getNext()" data-ng-class="{'disabled' : isLastProperty }" class="sprite-new right-arrow" data-tests-id="get-next" sdc-smart-tooltip="">Next</span>
+ </div>
+ </div>
+
+ <div class="sdc-edit-property-form-container" >
+ <perfect-scrollbar scroll-y-margin-offset="0" include-padding="true" class="scrollbar-container">
+ <form novalidate class="w-sdc-form two-columns" name="forms.editForm" >
+
+ <div class="w-sdc-form-columns-wrapper">
+
+ <div class="w-sdc-form-column">
+
+ <!-- Name -->
+ <div class="i-sdc-form-item" data-ng-class="{error:(forms.editForm.propertyName.$dirty && forms.editForm.propertyName.$invalid)}">
+ <label class="i-sdc-form-label" ng-class="{'required': !isService}">Name</label>
+ <input class="i-sdc-form-input"
+ data-tests-id="propertyName"
+ data-ng-maxlength="50"
+ data-ng-disabled="!isNew || editPropertyModel.property.readonly"
+ maxlength="50"
+ data-ng-model="editPropertyModel.property.name"
+ type="text"
+ name="propertyName"
+ data-ng-pattern="propertyNameValidationPattern"
+ data-required
+ data-ng-model-options="{ debounce: 200 }"
+ autofocus />
+
+ <div class="input-error" data-ng-show="forms.editForm.propertyName.$dirty && forms.editForm.propertyName.$invalid">
+ <span ng-show="forms.editForm.propertyName.$error.required" translate="VALIDATION_ERROR_REQUIRED" translate-values="{'field': 'Property name' }"></span>
+ <span ng-show="forms.editForm.propertyName.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '128' }"></span>
+ <span ng-show="forms.editForm.propertyName.$error.pattern" translate="VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED"></span>
+ </div>
+
+ </div>
+
+ <!-- Input source -->
+ <!--div class="i-sdc-form-item" data-ng-class="{error:(forms.editForm.source.$dirty && forms.editForm.source.$invalid)}">
+ <label class="i-sdc-form-label required">Input Source</label>
+ <select class="i-sdc-form-select"
+ data-required
+ name="source"
+ data-ng-model="editPropertyModel.property.source"
+ data-ng-options="source for source in editPropertyModel.sources">
+ <option value="" >Choose Input Source</option>
+ </select>
+ <sdc-error-tooltip data-ng-show="forms.editForm.source.$dirty && forms.editForm.source.$invalid">
+ <span ng-show="forms.editForm.source.$error.required">source is required.</span>
+ </sdc-error-tooltip>
+ </div-->
+
+
+ </div>
+
+ <div class="w-sdc-form-column">
+ <div class="w-sdc-form-columns-wrapper">
+ <div class="w-sdc-form-column">
+ <!-- Type -->
+ <div class="i-sdc-form-item" data-ng-class="{error:(forms.editForm.type.$dirty && forms.editForm.type.$invalid)}">
+ <label class="i-sdc-form-label" ng-class="{'required': !isService}">Type</label>
+ <select class="i-sdc-form-select"
+ data-tests-id="propertyType"
+ data-required
+ data-ng-disabled="isPropertyValueOwner() || editPropertyModel.property.readonly"
+ name="type"
+ data-ng-change="onTypeChange()"
+ data-ng-model="editPropertyModel.property.type">
+ <option value="">Choose Type</option>
+ <option data-ng-repeat="type in editPropertyModel.types"
+ value="{{type}}">{{type}}</option>
+ <option data-ng-repeat="type in nonPrimitiveTypes"
+ value="{{type}}">{{type.replace("org.openecomp.datatypes.heat.","")}}</option>
+ </select>
+
+ <div class="input-error" data-ng-show="forms.editForm.type.$dirty && forms.editForm.type.$invalid">
+ <span ng-show="forms.editForm.type.$error.required" translate="VALIDATION_ERROR_REQUIRED" translate-values="{'field': 'Type' }"></span>
+ </div>
+ </div>
+ </div>
+ <div class="w-sdc-form-column" data-ng-if="showSchema()">
+ <!-- Entry Schema -->
+ <div class="i-sdc-form-item" data-ng-class="{error:(forms.editForm.schemaType.$dirty && forms.editForm.schemaType.$invalid)}">
+ <label class="i-sdc-form-label required">Entry Schema</label>
+ <select class="i-sdc-form-select"
+ data-required
+ data-tests-id="schema-type"
+ data-ng-disabled="isPropertyValueOwner() || editPropertyModel.property.readonly"
+ name="schemaType"
+ data-ng-change="onSchemaTypeChange()"
+ data-ng-model="editPropertyModel.property.schema.property.type">
+ <option value="">Choose Schema Type</option>
+ <option data-ng-repeat="type in editPropertyModel.simpleTypes"
+ value="{{type}}">{{type}}</option>
+ <option data-ng-repeat="type in nonPrimitiveTypes"
+ value="{{type}}">{{type.replace("org.openecomp.datatypes.heat.","")}}</option>
+ </select>
+
+ <div class="input-error" data-ng-show="forms.editForm.schemaType.$dirty && forms.editForm.schemaType.$invalid">
+ <span ng-show="forms.editForm.schemaType.$error.required" translate="VALIDATION_ERROR_REQUIRED" translate-values="{'field': 'Entry schema' }"></span>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <!-- Constraints by type -->
+ <div class="i-sdc-form-item" data-ng-if="false">
+ <label class="i-sdc-form-label required">Constraints by type</label>
+ <div>
+ Should be constraints by type(TBD)
+ </div>
+ </div>
+
+ </div>
+
+ </div>
+ <!-- Description -->
+ <div class="i-sdc-form-item" data-ng-class="{error:(forms.editForm.description.$dirty && forms.editForm.description.$invalid)}">
+ <label class="i-sdc-form-label">Description</label>
+ <textarea class="i-sdc-form-textarea"
+ data-ng-maxlength="256"
+ data-ng-disabled="isPropertyValueOwner() || editPropertyModel.property.readonly"
+ maxlength="256"
+ data-ng-pattern="commentValidationPattern"
+ name="description"
+ data-ng-model="editPropertyModel.property.description"
+ data-ng-model-options="{ debounce: 200 }"
+ data-tests-id="description"
+ ></textarea>
+
+ <div class="input-error" data-ng-show="forms.editForm.description.$dirty && forms.editForm.description.$invalid">
+ <span ng-show="forms.editForm.description.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '256' }"></span>
+ <span ng-show="forms.editForm.description.$error.pattern" translate="VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED"></span>
+ <span ng-show="forms.editForm.description.$error.required" translate="VALIDATION_ERROR_REQUIRED" translate-values="{'field': 'Description' }"></span>
+ </div>
+ </div>
+ <!-- Default value -->
+
+ <div data-ng-if="dataTypes" class="default-value-section i-sdc-form-item">
+ <label class="i-sdc-form-label">Default Value</label>
+ <div data-ng-if="isTypeDataType">
+ <fields-structure value-obj-ref="myValue"
+ type-name="editPropertyModel.property.type"
+ parent-form-obj="forms.editForm"
+ fields-prefix-name="currentPropertyIndex"
+ read-only="editPropertyModel.property.readonly && !isPropertyValueOwner()"
+ default-value="{{getDefaultValue()}}"
+ types="dataTypes"
+ expand-by-default="true"></fields-structure>
+
+ </div>
+ <div data-ng-if="!isTypeDataType" ng-switch="editPropertyModel.property.type">
+ <div ng-switch-when="map">
+ <type-map value-obj-ref="myValue"
+ schema-property="editPropertyModel.property.schema.property"
+ parent-form-obj="forms.editForm"
+ fields-prefix-name="currentPropertyIndex"
+ read-only="editPropertyModel.property.readonly && !isPropertyValueOwner()"
+ default-value="{{getDefaultValue()}}"
+ types="dataTypes"
+ max-length="maxLength"></type-map>
+ </div>
+ <div ng-switch-when="list">
+ <type-list value-obj-ref="myValue"
+ schema-property="editPropertyModel.property.schema.property"
+ parent-form-obj="forms.editForm"
+ fields-prefix-name="currentPropertyIndex"
+ read-only="editPropertyModel.property.readonly && !isPropertyValueOwner()"
+ default-value="{{getDefaultValue()}}"
+ types="dataTypes"
+ max-length="maxLength"></type-list>
+ </div>
+ <div ng-switch-default>
+ <div class="i-sdc-form-item" data-ng-class="{error:(forms.editForm.value.$dirty && forms.editForm.value.$invalid)}">
+ <input class="i-sdc-form-input"
+ data-tests-id="defaultvalue"
+ ng-if="!((editPropertyModel.property.simpleType||editPropertyModel.property.type) == 'boolean')"
+ data-ng-maxlength="maxLength"
+ data-ng-disabled="editPropertyModel.property.readonly && !isPropertyValueOwner()"
+ maxlength="{{maxLength}}"
+ data-ng-model="editPropertyModel.property.value"
+ type="text"
+ name="value"
+ data-ng-pattern="getValidationPattern((editPropertyModel.property.simpleType||editPropertyModel.property.type))"
+ data-ng-model-options="{ debounce: 200 }"
+ data-ng-change="!forms.editForm.value.$error.pattern && ('integer'==editPropertyModel.property.type && forms.editForm.value.$setValidity('pattern', validateIntRange(editPropertyModel.property.value)) || onValueChange())"
+ autofocus />
+ <select class="i-sdc-form-select"
+ data-tests-id="booleantype"
+ ng-if="(editPropertyModel.property.simpleType||editPropertyModel.property.type) == 'boolean'"
+ data-ng-disabled="editPropertyModel.property.readonly && !isPropertyValueOwner()"
+ name="value"
+ data-ng-change="onValueChange()"
+ data-ng-model="editPropertyModel.property.value">
+ <option value="true">true</option>
+ <option value="false">false</option>
+ </select>
+
+ <div class="input-error" data-ng-show="forms.editForm.value.$dirty && forms.editForm.value.$invalid">
+ <span ng-show="forms.editForm.value.$error.required" translate="VALIDATION_ERROR_REQUIRED" translate-values="{'field': 'Property' }"></span>
+ <span ng-show="forms.editForm.value.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '{{maxLength}}' }"></span>
+ <span ng-show="forms.editForm.value.$error.pattern" translate="PROPERTY_EDIT_PATTERN"></span>
+ <span ng-show="forms.editForm.value.$error.customValidation" translate="PROPERTY_EDIT_MAP_UNIQUE_KEYS"></span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <span class="w-sdc-form-note" data-ng-show="forms.editForm.$invalid && false" translate="LABEL_ALL_FIELDS_ARE_MANDATORY"></span>
+ </form>
+ </perfect-scrollbar>
+ </div>
+
+</sdc-modal>
diff --git a/catalog-ui/app/scripts/view-models/forms/property-form/property-form.less b/catalog-ui/app/scripts/view-models/forms/property-form/property-form.less
new file mode 100644
index 0000000000..15e30af4ee
--- /dev/null
+++ b/catalog-ui/app/scripts/view-models/forms/property-form/property-form.less
@@ -0,0 +1,63 @@
+.sdc-edit-property-container {
+ .scrollbar-container{
+ height: 415px;
+ width: 830px;
+ .perfect-scrollbar;
+ }
+
+ form{
+ width: 813px;
+ [name="description"]{
+ min-height:50px;
+ }
+ }
+
+ .sdc-modal-top-bar{
+ height: 40px;
+ .sdc-modal-top-bar-buttons {
+ float: right;
+
+ > span:not(.delimiter){
+ vertical-align: middle;
+ .hand;
+
+ &.sprite-new {
+ text-indent: 100%;
+ }
+ &.disabled, &:hover.disabled {
+ pointer-events: none;
+ }
+ }
+
+ .delete-btn{
+ margin-right: 6px;
+ }
+
+ .left-arrow{
+ margin-right: 8px;
+ }
+
+ .delimiter {
+ height: 20px;
+ width: 1px;
+ background-color: #959595;
+ display: inline-block;
+ vertical-align: middle;
+ margin-right: 10px;
+ }
+ }
+ }
+
+ .w-sdc-form-note {
+ .h_9;
+ display: block;
+ position: relative;
+ top: 13px;
+ }
+
+ .default-value-section{
+ border-top: solid 1px @main_color_a;
+ padding-top: 15px;
+ margin-top: 15px;
+ }
+}
diff --git a/catalog-ui/app/scripts/view-models/forms/resource-instance-name-form/resource-instance-name-model.ts b/catalog-ui/app/scripts/view-models/forms/resource-instance-name-form/resource-instance-name-model.ts
new file mode 100644
index 0000000000..b69bf4a2a6
--- /dev/null
+++ b/catalog-ui/app/scripts/view-models/forms/resource-instance-name-form/resource-instance-name-model.ts
@@ -0,0 +1,105 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+/// <reference path="../../../references"/>
+
+module Sdc.ViewModels {
+ 'use strict';
+
+ interface IResourceInstanceViewModelScope extends ng.IScope {
+
+ componentInstanceModel: Sdc.Models.ComponentsInstances.ComponentInstance;
+ validationPattern: RegExp;
+ oldName:string;
+ isAlreadyPressed:boolean;
+ footerButtons: Array<any>;
+ forms:any;
+ modalInstanceName:ng.ui.bootstrap.IModalServiceInstance;
+
+ save(): void;
+ close(): void;
+ }
+
+ export class ResourceInstanceNameViewModel {
+
+ static '$inject' = [
+ '$scope',
+ 'ValidationPattern',
+ '$modalInstance',
+ 'ComponentInstanceFactory',
+ 'component'
+ ];
+
+
+ constructor(private $scope:IResourceInstanceViewModelScope,
+ private ValidationPattern:RegExp,
+ private $modalInstance:ng.ui.bootstrap.IModalServiceInstance,
+ private ComponentInstanceFactory:Utils.ComponentInstanceFactory,
+ private component:Models.Components.Component) {
+
+ this.initScope();
+ }
+
+
+ private initScope = ():void => {
+ this.$scope.forms = {};
+ this.$scope.validationPattern = this.ValidationPattern;
+ this.$scope.componentInstanceModel = Utils.ComponentInstanceFactory.createComponentInstance(this.component.selectedInstance);
+ this.$scope.oldName = this.component.selectedInstance.name;
+ this.$scope.modalInstanceName = this.$modalInstance;
+
+ this.$scope.isAlreadyPressed = false;
+
+
+ this.$scope.close = ():void => {
+ this.$modalInstance.dismiss();
+ };
+
+ this.$scope.save = ():void => {
+
+ let onFailed = () => {
+ this.$scope.isAlreadyPressed = true;
+ };
+
+ let onSuccess = (componentInstance:Models.ComponentsInstances.ComponentInstance) => {
+ this.$modalInstance.close();
+ this.$scope.isAlreadyPressed = false;
+ this.$scope.componentInstanceModel = componentInstance;
+ //this.component.name = componentInstance.name;//DE219124
+ this.component.selectedInstance.name = componentInstance.name;
+
+ };
+
+ this.$scope.isAlreadyPressed = true;
+ if (this.$scope.oldName != this.$scope.componentInstanceModel.name) {
+ this.component.updateComponentInstance(this.$scope.componentInstanceModel).then(onSuccess, onFailed);
+ }
+ };
+
+ this.$scope.footerButtons = [
+ {'name': 'OK', 'css': 'blue', 'callback': this.$scope.save, 'disabled': (!this.$scope.componentInstanceModel.name || this.$scope.componentInstanceModel.name === this.$scope.oldName) || this.$scope.isAlreadyPressed},
+ {'name': 'Cancel', 'css': 'grey', 'callback': this.$scope.close}
+ ];
+
+ this.$scope.$watch("forms.editNameForm.$invalid", (newVal, oldVal) => {
+ this.$scope.footerButtons[0].disabled = this.$scope.forms.editNameForm.$invalid;
+ });
+ }
+ }
+}
diff --git a/catalog-ui/app/scripts/view-models/forms/resource-instance-name-form/resource-instance-name-view.html b/catalog-ui/app/scripts/view-models/forms/resource-instance-name-form/resource-instance-name-view.html
new file mode 100644
index 0000000000..e04343adbd
--- /dev/null
+++ b/catalog-ui/app/scripts/view-models/forms/resource-instance-name-form/resource-instance-name-view.html
@@ -0,0 +1,72 @@
+<sdc-modal modal="modalInstanceName" type="classic" class="w-sdc-modal-resource-instance-name modal-type-confirmation" buttons="footerButtons" header="Instance Name" show-close-button="true">
+
+ <form novalidate class="w-sdc-form" name="forms.editNameForm">
+ <div class="i-sdc-form-item" data-ng-class="{error:(editNameForm.componentInstanceName.$dirty && editNameForm.resourceInstanceName.$invalid)}">
+ <label class="i-sdc-form-label required">Instance Name</label>
+ <input class="w-sdc-modal-resource-instance-input i-sdc-form-input"
+ name="componentInstanceName"
+ data-ng-maxlength="50"
+ data-ng-model="componentInstanceModel.name"
+ type="text"
+ data-required
+ data-ng-pattern="validationPattern"
+ maxlength="50"
+ autofocus
+ placeholder="Enter instance name..."
+ data-tests-id="instanceName"
+ />
+
+ <div class="input-error" data-ng-show="forms.editNameForm.componentInstanceName.$dirty && forms.editNameForm.componentInstanceName.$invalid">
+ <span ng-show="forms.editNameForm.componentInstanceName.$error.required" translate="VALIDATION_ERROR_REQUIRED" translate-values="{'field': 'Resource name' }"></span>
+ <span ng-show="forms.editNameForm.componentInstanceName.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '50' }"></span>
+ <span ng-show="forms.editNameForm.componentInstanceName.$error.pattern" translate="VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED"></span>
+ </div>
+
+ </div>
+ </form>
+
+</sdc-modal>
+
+
+
+<!--
+
+<div class="w-sdc-modal w-sdc-modal-resource-instance-name">
+ <header>
+ <div class="w-sdc-modal-head">
+ Instance Name
+ </div>
+ </header>
+ <div>
+ <form novalidate class="w-sdc-modal-body w-sdc-form" name="editNameForm">
+ <div class="i-sdc-form-item" data-ng-class="{error:(editNameForm.componentInstanceName.$dirty && editNameForm.resourceInstanceName.$invalid)}">
+ <label class="i-sdc-form-label required">Instance Name</label>
+ <input class="w-sdc-modal-resource-instance-input i-sdc-form-input"
+ name="componentInstanceName"
+ data-ng-maxlength="50"
+ data-ng-model="componentInstanceModel.name"
+ type="text"
+ data-required
+ data-ng-pattern="validationPattern"
+ maxlength="50"
+ autofocus
+ placeholder="Enter instance name..."
+ data-tests-id="instanceName"
+ />
+
+ <div class="input-error" data-ng-show="editNameForm.componentInstanceName.$dirty && editNameForm.componentInstanceName.$invalid">
+ <span ng-show="editNameForm.componentInstanceName.$error.required" translate="VALIDATION_ERROR_REQUIRED" translate-values="{'field': 'Resource name' }"></span>
+ <span ng-show="editNameForm.componentInstanceName.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '50' }"></span>
+ <span ng-show="editNameForm.componentInstanceName.$error.pattern" translate="VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED"></span>
+ </div>
+
+ </div>
+ </form>
+
+ <div class="w-sdc-modal-action">
+ <button class="w-sdc-btn-blue" data-ng-click="save()" type="button" data-ng-disabled="(!componentInstanceModel.name || componentInstanceModel.name === oldName) || isAlreadyPressed">Ok</button>
+ <button class="w-sdc-btn-dark-gray" data-ng-click="close()" type="button">Cancel</button>
+ </div>
+ </div>
+</div>
+-->
diff --git a/catalog-ui/app/scripts/view-models/forms/resource-instance-name-form/resource-instance-name.less b/catalog-ui/app/scripts/view-models/forms/resource-instance-name-form/resource-instance-name.less
new file mode 100644
index 0000000000..57698bef17
--- /dev/null
+++ b/catalog-ui/app/scripts/view-models/forms/resource-instance-name-form/resource-instance-name.less
@@ -0,0 +1,29 @@
+.w-sdc-modal-resource-instance-name {
+
+ .w-sdc-modal-body {
+ overflow: visible;
+ }
+
+ .w-sdc-modal-action {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+
+ .w-sdc-modal-resource-instance-input {
+ .p_1;
+ border: solid 1px @color_p;
+ height: 45px;
+ padding: 0 20px;
+ margin: 0 auto 0 auto;
+ display: block;
+ }
+ .w-sdc-modal-body {
+ border-bottom: none;
+ }
+
+ .w-sdc-form .i-sdc-form-item.error::after {
+ top: 13px;
+ }
+
+}