aboutsummaryrefslogtreecommitdiffstats
path: root/catalog-ui/app/scripts/view-models/wizard/wizard-creation-base.ts
diff options
context:
space:
mode:
Diffstat (limited to 'catalog-ui/app/scripts/view-models/wizard/wizard-creation-base.ts')
-rw-r--r--catalog-ui/app/scripts/view-models/wizard/wizard-creation-base.ts399
1 files changed, 399 insertions, 0 deletions
diff --git a/catalog-ui/app/scripts/view-models/wizard/wizard-creation-base.ts b/catalog-ui/app/scripts/view-models/wizard/wizard-creation-base.ts
new file mode 100644
index 0000000000..365d3aedf6
--- /dev/null
+++ b/catalog-ui/app/scripts/view-models/wizard/wizard-creation-base.ts
@@ -0,0 +1,399 @@
+/*-
+ * ============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.Wizard {
+ 'use strict';
+
+ export class StepNames {
+ static general = "General";
+ static icon = "Icon";
+ static deploymentArtifact = "Deployment Artifact";
+ static informationArtifact = "Information Artifact";
+ static properties = "Properties";
+ static hierarchy = "Hierarchy";
+ }
+
+ class FooterButtons {
+ static cancel = "Cancel";
+ static back = "Back";
+ static next = "Next";
+ static finish = "Finish";
+ }
+
+ export class WizardCreationTypes {
+ static importAsset = "importAsset";
+ static create = "create";
+ static edit = "edit";
+ }
+
+ export class _CreationStep {
+ name:string;
+ url:string;
+ }
+
+ export class CurrentStep {
+ assetCreationStep:_CreationStep;
+ reference:IWizardCreationStep;
+ index:number;
+ valid: boolean;
+ }
+
+ export interface IWizardCreationStep {
+ save(callback:Function):void;
+ back(callback:Function):void;
+ }
+
+ export interface IWizardCreationStepScope extends ng.IScope {
+ data:any;
+ getComponent():Sdc.Models.Components.Component;
+ setComponent(component: Sdc.Models.Components.Component):void;
+ registerChild(child:IWizardCreationStep):void; // Called from the step
+ setValidState(valid:boolean):void; // Called from the step
+ }
+
+ export interface IWizardCreationScope extends ng.IScope {
+ isLoading: boolean;
+ data:any; // data passed from dashboard (opener), need it on the scope, because general step will use this (extends the scope)
+ directiveSteps: Array<Sdc.Directives.IWizardStep>; // Steps for the directive, on the scope (on the scope because need to pass to directive via HTML)
+ templateUrl: string; // On the scope because need to pass to <ng-include> via HTML
+ footerButtons: Array<Sdc.Directives.ISdcModalButton>; // Wizard footer buttons (on the scope because need to pass to directive via HTML)
+ assetCreationControl:any; // Link to wizard directive functions.
+ modalInstance:ng.ui.bootstrap.IModalServiceInstance; // Reference to the modal, so we can close it (on the scope because need to pass to directive via HTML)
+ assetName:string;
+ assetType:string;
+ modalTitle:string;
+ getComponent():Sdc.Models.Components.Component;
+ setComponent(component: Sdc.Models.Components.Component):void;
+ registerChild(child:IWizardCreationStep):void; // Called from the step
+ setValidState(valid:boolean):void; // Called from the step
+ }
+
+ export class WizardCreationBaseViewModel {
+
+ component: Sdc.Models.Components.Component;
+ protected assetCreationSteps: Array<_CreationStep>; // Contains URL and name so we can replace them
+ currentStep:CurrentStep;
+ protected type:string;
+
+ constructor(protected $scope:IWizardCreationScope,
+ protected data:any,
+ protected ComponentFactory: Utils.ComponentFactory,
+ protected $modalInstance: ng.ui.bootstrap.IModalServiceInstance
+ ) {
+
+ this.$scope.data = data;
+ this.currentStep = new CurrentStep();
+ this.currentStep.valid=false;
+ this.$scope.modalInstance = this.$modalInstance;
+ this.initScope();
+ this.noBackspaceNav();
+
+ // In case the modal was opened with filled resource (edit mode).
+ if (data.component){
+ this.$scope.setComponent(data.component);
+ data.componentType = this.$scope.getComponent().componentType;
+ window.setTimeout(()=>{
+ this.safeApply(this.setCurrentStepByIndex(0, false));
+ },100);
+ } else {
+ // Default step to start with
+ window.setTimeout(()=>{
+ this.safeApply(this.setCurrentStepByIndex(0, false));
+ },100);
+ }
+
+ }
+
+ private safeApply = (fn:any) => {
+ let phase = this.$scope.$root.$$phase;
+ if (phase == '$apply' || phase == '$digest') {
+ if (fn && (typeof(fn) === 'function')) {
+ fn();
+ }
+ } else {
+ this.$scope.$apply(fn);
+ }
+ };
+
+ private initScope = ():void => {
+
+ // Control to call functions on wizard step directive
+ this.$scope.assetCreationControl = {};
+
+ // Footer buttons definitions for the modal directive.
+ this.$scope.footerButtons = [
+ {"name":FooterButtons.cancel, "css":'white cancel',"callback": ()=>{this.btnCancelClicked();}},
+ {"name":FooterButtons.back, "disabled":true, "css":'white back',"callback": ()=>{this.btnBackClicked();}},
+ {"name":FooterButtons.next, "disabled":true, "css":'blue next',"callback": ()=>{this.btnNextClicked();}},
+ {"name":FooterButtons.finish, "disabled":true, "css":'white finish',"callback": ()=>{this.btnFinishedClicked();}}
+ ];
+
+ // Will be called from step constructor to register him.
+ // So the current step will be the reference.
+ this.$scope.registerChild=(child:IWizardCreationStep):void => {
+ this.currentStep.reference=child;
+ };
+
+ // Will be called from each step to notify if the step is valid
+ // The wizard will set the "Next", "Finish" buttons accordingly.
+ this.$scope.setValidState = (valid:boolean):void => {
+ this.currentStep.valid=valid;
+ let currentDirectiveStep:Sdc.Directives.IWizardStep = this.$scope.directiveSteps[this.currentStep.index];
+ this.$scope.assetCreationControl.setStepValidity(currentDirectiveStep, valid);
+ this.footerButtonsStateMachine();
+ this.wizardButtonsIconsStateMachine();
+ };
+
+ /**
+ * Will be called from each step to get current entity.
+ * This will return copy of the entity (not reference), because I do not want that the step will change entity parameters.
+ * If the step need to update the entity it can call setComponent function.
+ * @returns {Sdc.Models.IEntity}
+ */
+ this.$scope.getComponent = ():Sdc.Models.Components.Component => {
+ return this.component;
+ };
+
+ // Will be called from each step after save to update the resource.
+ this.$scope.setComponent = (component:Sdc.Models.Components.Component):void => {
+ this.component = component;
+ };
+
+ };
+
+ protected setCurrentStepByName = (stepName:string):boolean => {
+ let stepIndex:number = this.getStepIndex(stepName);
+ return this.setCurrentStepByIndex(stepIndex);
+ };
+
+ // Set the current step, change the URL in ng-include.
+ protected setCurrentStepByIndex = (index:number, doSave:boolean=true):boolean => {
+ let result:boolean = false;
+ if (this.currentStep.index!==index) { // Check that not pressing on same step, also the first time currentStepIndex=undefined
+ if (doSave===true) {
+ this.callStepSave(() => {
+ // This section will be executed only if success save.
+
+ // Set current step in the left wizard directive = valid
+ let currentDirectiveStep:Sdc.Directives.IWizardStep = this.$scope.directiveSteps[this.currentStep.index];
+ this.$scope.assetCreationControl.setStepValidity(currentDirectiveStep, true);
+
+ // Move to next step
+ let step:_CreationStep = this.assetCreationSteps[index];
+ this.currentStep.index = index;
+ this.currentStep.assetCreationStep = step;
+ this.$scope.templateUrl = step.url;
+
+ // Update the next/back buttons and steps buttons.
+ this.footerButtonsStateMachine();
+ this.wizardButtonsIconsStateMachine();
+
+ // Can not perform step click without enabling the step
+ this.$scope.directiveSteps[index].enabled = true; // Need to set the step enabled, before clicking it.
+ this.$scope.assetCreationControl.stepClicked(step.name);
+
+ // After saving the asset name and type will be shown in the top right of the screen.
+ this.fillAssetNameAndType();
+
+ result=true;
+ });
+ } else {
+ // For the first time
+ let step:_CreationStep = this.assetCreationSteps[index];
+ this.currentStep.index = index;
+ this.currentStep.assetCreationStep=step;
+ this.$scope.templateUrl = step.url;
+ this.$scope.directiveSteps[index].enabled = true; // Need to set the step enabled, before clicking it.
+ this.$scope.assetCreationControl.stepClicked(step.name);
+ result=true;
+ }
+
+ //this.updateFooterButtonsStates();
+
+ } else {
+ result=true;
+ }
+ return result;
+ };
+
+ // Save the current step
+ private callStepSave = (successCallback:Function):void => {
+ this.$scope.isLoading = true;
+ this.currentStep.reference.save((result:boolean)=>{
+ this.$scope.isLoading = false;
+ if (result===true){
+ successCallback();
+ } else {
+ // Set the next and finish button enabled.
+ //this.updateFooterButtonsStates(true);
+ }
+ });
+ };
+
+ // Save the current step
+ private callStepBack = (successCallback:Function):void => {
+ this.$scope.isLoading = true;
+ this.currentStep.reference.back((result:boolean)=>{
+ this.$scope.isLoading = false;
+ if (result===true){
+ successCallback();
+ } else {
+ // Set the next and finish button enabled.
+ //this.updateFooterButtonsStates(true);
+ }
+ });
+ };
+
+ private getStepIndex = (stepName:string):number => {
+ let index:number=-1;
+ let tmp = _.find(this.assetCreationSteps, function (item, indx) {
+ index = indx;
+ return item.name === stepName;
+ });
+ return index;
+ };
+
+ private btnNextClicked = ():void => {
+ if (this.hasNext()===true) {
+ let tmp = this.currentStep.index+1;
+ this.setCurrentStepByIndex(tmp);
+ }
+ };
+
+ private btnBackClicked = ():void => {
+ if (this.hasBack()===true) {
+ this.callStepBack(() => {
+ let tmp = this.currentStep.index-1;
+ this.setCurrentStepByIndex(tmp, false);
+ });
+ }
+ };
+
+ private btnCancelClicked = ():void => {
+ this.$modalInstance.dismiss(this.$scope.getComponent());
+ };
+
+ private btnFinishedClicked = ():void => {
+ this.callStepSave(() => {
+ this.$modalInstance.close(this.$scope.getComponent());
+ });
+ };
+
+ // Check if we can move next
+ private hasNext = ():boolean => {
+ if (this.assetCreationSteps.length-1>this.currentStep.index){
+ return true;
+ } else {
+ return false;
+ }
+ };
+
+ // Check if we can move back
+ private hasBack = ():boolean => {
+ if (this.currentStep.index===0){
+ return false;
+ } else {
+ return true;
+ }
+ };
+
+ private fillAssetNameAndType=():void => {
+ this.$scope.assetName = this.$scope.getComponent().name;
+ this.$scope.assetType = this.$scope.getComponent().getComponentSubType();
+
+ };
+
+ protected enableAllWizardSteps=():void => {
+ this.$scope.directiveSteps.forEach((step:Sdc.Directives.IWizardStep) => {
+ step.enabled=true;
+ });
+ };
+
+ protected disableAllWizardSteps=():void => {
+ this.$scope.directiveSteps.forEach((step:Sdc.Directives.IWizardStep) => {
+ step.enabled=false;
+ });
+ };
+
+ private footerButtonsStateMachine = ():void => {
+ //console.log("footerButtonsStateMachine, current step validity: " + this.currentStep.valid);
+ let stepIndex:number = this.currentStep.index;
+ let cancelButton = this.$scope.footerButtons[0];
+ let backButton = this.$scope.footerButtons[1];
+ let nextButton = this.$scope.footerButtons[2];
+ let finishButton = this.$scope.footerButtons[3];
+
+ // NEXT button
+ // Disable next button if it is the last step, and if not check the validity of the step.
+ if (this.hasNext()){
+ nextButton.disabled = !this.currentStep.valid;
+ } else {
+ nextButton.disabled = true;
+ }
+
+ // BACK button
+ backButton.disabled = !this.hasBack();
+
+ // FINISH button
+ // If step 2 is valid show the finish button.
+ if (stepIndex>=1 && this.currentStep.valid===true) {
+ finishButton.disabled = false;
+ }
+ if (this.currentStep.valid===false){
+ finishButton.disabled = true;
+ }
+
+ // EDIT
+ if (this.type===WizardCreationTypes.edit && this.currentStep.valid===true){
+ finishButton.disabled = false;
+ }
+
+ };
+
+
+
+ private wizardButtonsIconsStateMachine = ():void => {
+
+ // Enable or disable wizard directive next step, in case the current step form is valid or not.
+ let stepIndex:number = this.currentStep.index;
+ if (this.$scope.directiveSteps[stepIndex + 1]) {
+ this.$scope.directiveSteps[stepIndex + 1].enabled = this.currentStep.valid;
+ }
+
+ // In case step 1 and 2 are valid, we can open all other steps.
+ if (this.$scope.directiveSteps[0].valid===true && this.$scope.directiveSteps[1].valid===true){
+ // Enable all wizard directive steps
+ this.enableAllWizardSteps();
+ } else if (this.currentStep.valid===false) {
+ // Disable all steps
+ this.disableAllWizardSteps();
+ }
+ };
+
+ private noBackspaceNav:Function = ():void => {
+ this.$scope.$on('$locationChangeStart', (event, newUrl, oldUrl):void =>{
+ event.preventDefault();
+ })
+ };
+
+
+ }
+
+}