Add DOT to property's name permitted chars
[sdc.git] / catalog-ui / src / app / app.ts
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 'use strict';
22
23 import { AuthenticationService } from 'app/ng2/services/authentication.service';
24 import * as _ from 'lodash';
25 import 'ng-infinite-scroll';
26 import { SdcUiCommon, SdcUiComponents, SdcUiServices } from 'onap-ui-angular';
27 import 'reflect-metadata';
28 import { IAppConfigurtaion, IAppMenu, IHostedApplication, Resource } from './models';
29 import { Component } from './models/components/component';
30 import { IUserProperties } from './models/user';
31 import './modules/directive-module.ts';
32 import './modules/filters.ts';
33 import './modules/service-module';
34 import './modules/utils.ts';
35 import './modules/view-model-module.ts';
36 import { WorkspaceService } from './ng2/pages/workspace/workspace.service';
37 import { CookieService, DataTypesService, EcompHeaderService, LeftPaletteLoaderService } from './services';
38 import { CacheService, CatalogService, HomeService } from './services-ng2';
39 import { CHANGE_COMPONENT_CSAR_VERSION_FLAG, PREVIOUS_CSAR_COMPONENT, States } from './utils';
40 import { ComponentFactory } from './utils/component-factory';
41
42 const moduleName: string = 'sdcApp';
43 const viewModelsModuleName: string = 'Sdc.ViewModels';
44 const directivesModuleName: string = 'Sdc.Directives';
45 const servicesModuleName: string = 'Sdc.Services';
46 const filtersModuleName: string = 'Sdc.Filters';
47 const utilsModuleName: string = 'Sdc.Utils';
48
49 // Load configuration according to environment.
50 declare var __ENV__: string;
51 let sdcConfig: IAppConfigurtaion;
52 let sdcMenu: IAppMenu;
53 let pathPrefix: string = '';
54 if (__ENV__ === 'dev') {
55   sdcConfig = require('./../../configurations/dev.js');
56 } else if (__ENV__ === 'prod') {
57   sdcConfig = require('./../../configurations/prod.js');
58   pathPrefix = 'sdc1/';
59 } else {
60   console.log('ERROR: Environment configuration not found!');
61 }
62 sdcMenu = require('./../../configurations/menu.js');
63
64 const dependentModules: string[] = [
65   'ui.router',
66   'ui.bootstrap',
67   'ui.bootstrap.tpls',
68   'ngDragDrop',
69   'ui-notification',
70   'ngResource',
71   'ngSanitize',
72   'naif.base64',
73   'base64',
74   'uuid4',
75   'checklist-model',
76   'angular.filter',
77   'pascalprecht.translate',
78   '720kb.tooltips',
79   'restangular',
80   'angular-clipboard',
81   'angularResizable',
82   'infinite-scroll',
83   viewModelsModuleName,
84   directivesModuleName,
85   servicesModuleName,
86   filtersModuleName,
87   utilsModuleName
88 ];
89
90 // ===================== Hosted applications section ====================
91 // Define here new hosted apps
92 const hostedApplications: IHostedApplication[] = [
93   {
94     moduleName: 'dcaeApp',
95     navTitle: 'DCAE',
96     defaultState: 'dcae.app.home',
97     state: {
98       name: 'dcae',
99       url: '/dcae',
100       relativeHtmlPath: 'dcae-app/dcae-app-view.html',
101       controllerName: '.DcaeAppViewModel'
102     }
103   }
104 ];
105
106 // Check if module exists (in case the javascript was not loaded).
107 const isModuleExists = (moduleName: string): boolean => {
108   try {
109     angular.module(moduleName);
110     dependentModules.push(moduleName);
111     return true;
112   } catch (e) {
113     console.log('Module ' + moduleName + ' does not exists');
114     return false;
115   }
116 };
117
118 // Check which hosted applications exists
119 _.each(hostedApplications, (hostedApp) => {
120   if (isModuleExists(hostedApp.moduleName)) {
121     hostedApp.exists = true;
122   }
123 });
124 // ===================== Hosted applications section ====================
125
126 export const ng1appModule: ng.IModule = angular.module(moduleName, dependentModules);
127
128 ng1appModule.config([
129   '$stateProvider',
130   '$translateProvider',
131   '$urlRouterProvider',
132   '$httpProvider',
133   'tooltipsConfigProvider',
134   'NotificationProvider',
135   ($stateProvider: any,
136    $translateProvider: any,
137    $urlRouterProvider: ng.ui.IUrlRouterProvider,
138    $httpProvider: ng.IHttpProvider,
139    tooltipsConfigProvider: any,
140    NotificationProvider: any): void => {
141
142     NotificationProvider.setOptions({
143       delay: 5000,
144       startTop: 10,
145       startRight: 10,
146       closeOnClick: true,
147       verticalSpacing: 20,
148       horizontalSpacing: 20,
149       positionX: 'right',
150       positionY: 'top'
151     });
152     NotificationProvider.options.templateUrl = 'notification-custom-template.html';
153
154     $translateProvider.useStaticFilesLoader({
155       prefix: pathPrefix + 'assets/languages/',
156       langKey: '',
157       suffix: '.json?d=' + (new Date()).getTime()
158     });
159     $translateProvider.useSanitizeValueStrategy('escaped');
160     $translateProvider.preferredLanguage('en_US');
161
162     $httpProvider.interceptors.push('Sdc.Services.HeaderInterceptor');
163     $urlRouterProvider.otherwise('dashboard');
164
165     $stateProvider.state(
166         'dashboard', {
167           url: '/dashboard?show&folder&filter.term&filter.status&filter.distributed',
168           template: '<home-page></home-page>',
169           permissions: ['DESIGNER']
170         },
171     );
172
173     const componentsParam: any[] = ['$stateParams', 'HomeService', 'CatalogService', 'Sdc.Services.CacheService', ($stateParams: any, HomeService: HomeService, CatalogService: CatalogService, cacheService: CacheService) => {
174       if (cacheService.get('breadcrumbsComponentsState') === $stateParams.previousState) {
175         const breadcrumbsComponents = cacheService.get('breadcrumbsComponents');
176         if (breadcrumbsComponents) {
177           return breadcrumbsComponents;
178         }
179       } else {
180         let breadcrumbsComponentsObservable;
181         if ($stateParams.previousState === 'dashboard') {
182           breadcrumbsComponentsObservable = HomeService.getAllComponents(true);
183         } else if ($stateParams.previousState === 'catalog') {
184           breadcrumbsComponentsObservable = CatalogService.getCatalog();
185         } else {
186           cacheService.remove('breadcrumbsComponentsState');
187           cacheService.remove('breadcrumbsComponents');
188           return [];
189         }
190         breadcrumbsComponentsObservable.subscribe((components) => {
191           cacheService.set('breadcrumbsComponentsState', $stateParams.previousState);
192           cacheService.set('breadcrumbsComponents', components);
193         });
194         return breadcrumbsComponentsObservable;
195       }
196     }];
197
198     const oldWorkspaceController: any[] = ['$location', ($location: ng.ILocationService) => {
199       // redirect old /workspace/* urls to /catalog/workspace/* url
200       const newUrl = '/catalog' + $location.url();
201       console.log('old workspace path - redirecting to:', newUrl);
202       $location.url(newUrl);
203     }];
204
205     $stateProvider.state(
206         'workspace-old', {
207           url: '/workspace/:id/:type/*workspaceInnerPath',
208           controller: oldWorkspaceController
209         }
210     );
211
212     $stateProvider.state(
213         States.TYPE_WORKSPACE, {
214           url: '/:previousState/type-workspace/:type/:id/:subPage',
215           params: {
216               importedFile: null
217           },
218           template: '<app-type-workspace></app-type-workspace>'
219         }
220     );
221
222     $stateProvider.state(
223         States.WORKSPACE, {
224           url: '/:previousState/workspace/:id/:type/',
225           params: {
226             importedFile: null,
227             componentCsar: null,
228             resourceType: null,
229             disableButtons: null
230           },
231           templateUrl: './view-models/workspace/workspace-view.html',
232           controller: viewModelsModuleName + '.WorkspaceViewModel',
233           resolve: {
234             injectComponent: ['$stateParams', 'ComponentFactory', 'workspaceService', 'Sdc.Services.CacheService', function($stateParams, ComponentFactory: ComponentFactory, workspaceService: WorkspaceService, cacheService: CacheService) {
235               if ($stateParams.id && $stateParams.id.length) { // need to check length in case ID is an empty string
236                 return ComponentFactory.getComponentWithMetadataFromServer($stateParams.type.toUpperCase(), $stateParams.id).then(
237                     (component: Component) => {
238                       if ($stateParams.componentCsar && component.isResource()) {
239                         if ((component as Resource).csarVersion != $stateParams.componentCsar.csarVersion) {
240                           cacheService.set(PREVIOUS_CSAR_COMPONENT, angular.copy(component));
241                         }
242                         component = ComponentFactory.updateComponentFromCsar($stateParams.componentCsar, component as Resource);
243                       }
244                       workspaceService.setComponentMetadata(component.componentMetadata);
245                       return component;
246                     });
247               } else if ($stateParams.componentCsar && $stateParams.componentCsar.csarUUID) {
248                 return $stateParams.componentCsar;
249               } else {
250                 const emptyComponent = ComponentFactory.createEmptyComponent($stateParams.type.toUpperCase());
251                 if (emptyComponent.isResource() && $stateParams.resourceType) {
252                   // Set the resource type
253                   (emptyComponent as Resource).resourceType = $stateParams.resourceType;
254                 }
255                 if ($stateParams.importedFile) {
256                   (emptyComponent as Resource).importedFile = $stateParams.importedFile;
257                 }
258                 return emptyComponent;
259               }
260             }],
261             components: componentsParam
262           }
263         }
264     );
265
266     $stateProvider.state(
267         States.WORKSPACE_GENERAL, {
268           url: 'general',
269           parent: 'workspace',
270           controller: viewModelsModuleName + '.GeneralViewModel',
271           templateUrl: './view-models/workspace/tabs/general/general-view.html',
272           data: {unsavedChanges: false, bodyClass: 'general'}
273         }
274     );
275
276     $stateProvider.state(
277         States.WORKSPACE_INFORMATION_ARTIFACTS, {
278           url: 'information_artifacts',
279           parent: 'workspace',
280           template: '<information-artifact-page></information-artifact-page>'
281         }
282     );
283
284     $stateProvider.state(
285         States.WORKSPACE_TOSCA_ARTIFACTS, {
286           url: 'tosca_artifacts',
287           parent: 'workspace',
288           template: '<tosca-artifact-page></tosca-artifact-page>'
289         }
290     );
291
292     $stateProvider.state(
293         States.WORKSPACE_DEPLOYMENT_ARTIFACTS, {
294           url: 'deployment_artifacts',
295           parent: 'workspace',
296           template: '<deployment-artifact-page></deployment-artifact-page>'
297         }
298     );
299
300     $stateProvider.state(
301         States.WORKSPACE_PROPERTIES, {
302           url: 'properties',
303           parent: 'workspace',
304           controller: viewModelsModuleName + '.PropertiesViewModel',
305           templateUrl: './view-models/workspace/tabs/properties/properties-view.html',
306           data: {
307             bodyClass: 'properties'
308           }
309         }
310     );
311
312     $stateProvider.state(
313         States.WORKSPACE_PROPERTIES_ASSIGNMENT, {
314           url: 'properties_assignment',
315           params: {component: null},
316           template: '<properties-assignment></properties-assignment>',
317           parent: 'workspace',
318           resolve: {
319             componentData: ['injectComponent', '$stateParams', function(injectComponent: Component, $stateParams) {
320               $stateParams.component = injectComponent;
321               return injectComponent;
322             }],
323           },
324           data: {
325             bodyClass: 'properties-assignment'
326           }
327         }
328     );
329
330     $stateProvider.state(
331         States.WORKSPACE_ATTRIBUTES, {
332           url: 'attributes',
333           parent: 'workspace',
334           template: '<attributes></attributes>',
335         }
336     );
337
338     $stateProvider.state(
339         States.WORKSPACE_ATTRIBUTES_OUTPUTS, {
340           url: 'attributes_outputs',
341           parent: 'workspace',
342           template: '<attributes-outputs></attributes-outputs>',
343           resolve: {
344             componentData: ['injectComponent', '$stateParams', function(injectComponent: Component, $stateParams) {
345               $stateParams.component = injectComponent;
346               return injectComponent;
347             }],
348           },
349           data: {
350             bodyClass: 'attributes-outputs'
351           }
352         }
353     );
354
355     $stateProvider.state(
356         States.WORKSPACE_REQUIREMENTS_AND_CAPABILITIES, {
357           url: 'req_and_capabilities',
358           parent: 'workspace',
359           template: '<req-and-capabilities></req-and-capabilities>',
360           data: {
361             bodyClass: 'attributes'
362           }
363         }
364     );
365     $stateProvider.state(
366         States.WORKSPACE_REQUIREMENTS_AND_CAPABILITIES_EDITABLE, {
367           url: 'req_and_capabilities_editable',
368           parent: 'workspace',
369           template: '<req-and-capabilities></req-and-capabilities>',
370           data: {
371             bodyClass: 'attributes'
372           }
373         }
374     );
375
376     $stateProvider.state(
377         States.WORKSPACE_MANAGEMENT_WORKFLOW, {
378           parent: 'workspace',
379           url: 'management_workflow',
380           templateUrl: './view-models/workspace/tabs/management-workflow/management-workflow-view.html',
381           controller: viewModelsModuleName + '.ManagementWorkflowViewModel'
382         }
383     );
384
385     $stateProvider.state(
386         States.WORKSPACE_NETWORK_CALL_FLOW, {
387           parent: 'workspace',
388           url: 'network_call_flow',
389           templateUrl: './view-models/workspace/tabs/network-call-flow/network-call-flow-view.html',
390           controller: viewModelsModuleName + '.NetworkCallFlowViewModel'
391         }
392     );
393
394     $stateProvider.state(
395         States.WORKSPACE_COMPOSITION, {
396           url: 'composition/',
397           params: {component: null},
398           parent: 'workspace',
399           template: '<composition-page></composition-page>',
400           resolve: {
401             componentData: ['injectComponent', '$stateParams', function(injectComponent: Component, $stateParams) {
402               $stateParams.component = injectComponent;
403               return injectComponent;
404             }],
405           },
406           data: {
407             bodyClass: 'composition'
408           }
409         }
410     );
411
412     $stateProvider.state(
413         States.WORKSPACE_ACTIVITY_LOG, {
414           url: 'activity_log/',
415           parent: 'workspace',
416           template: '<activity-log></activity-log>',
417         }
418     );
419
420     $stateProvider.state(
421         States.WORKSPACE_DISTRIBUTION, {
422           url: 'distribution',
423           parent: 'workspace',
424           template: '<distribution></distribution>',
425         }
426     );
427
428     $stateProvider.state(
429         States.WORKSPACE_DEPLOYMENT, {
430           url: 'deployment/',
431           parent: 'workspace',
432           template: '<deployment-page></deployment-page>',
433
434         }
435     );
436
437     $stateProvider.state(
438         'workspace.composition.details', {
439           url: 'details',
440           parent: 'workspace.composition',
441           resolve: {
442             componentData: ['injectComponent', '$stateParams', function(injectComponent: Component, $stateParams) {
443               $stateParams.component = injectComponent;
444               return injectComponent;
445             }],
446           }
447
448         }
449     );
450
451     $stateProvider.state(
452         'workspace.composition.properties', {
453           url: 'properties',
454           parent: 'workspace.composition'
455         }
456     );
457
458     $stateProvider.state(
459         'workspace.composition.artifacts', {
460           url: 'artifacts',
461           parent: 'workspace.composition'
462
463         }
464     );
465
466     $stateProvider.state(
467         'workspace.composition.relations', {
468           url: 'relations',
469           parent: 'workspace.composition'
470         }
471     );
472
473     $stateProvider.state(
474         'workspace.composition.structure', {
475           url: 'structure',
476           parent: 'workspace.composition'
477         }
478     );
479     $stateProvider.state(
480         'workspace.composition.lifecycle', {
481           url: 'lifecycle',
482           parent: 'workspace.composition'
483         }
484     );
485
486     $stateProvider.state(
487         'workspace.composition.api', {
488           url: 'api',
489           parent: 'workspace.composition'
490         }
491     );
492     $stateProvider.state(
493         'workspace.composition.deployment', {
494           url: 'deployment',
495           parent: 'workspace.composition'
496         }
497     );
498
499     $stateProvider.state(
500         States.WORKSPACE_INTERFACE_OPERATION, {
501           url: 'interface_operation',
502           parent: 'workspace',
503           controller: viewModelsModuleName + '.InterfaceOperationViewModel',
504           templateUrl: './view-models/workspace/tabs/interface-operation/interface-operation-view.html',
505           data: {
506             bodyClass: 'interface_operation'
507           }
508         }
509     );
510
511     $stateProvider.state(
512         States.WORKSPACE_INTERFACE_DEFINITION, {
513           url: 'interfaceDefinition',
514           parent: 'workspace',
515           controller: viewModelsModuleName + '.InterfaceDefinitionViewModel',
516           templateUrl: './view-models/workspace/tabs/interface-definition/interface-definition-view.html',
517           data: {
518             bodyClass: 'interfaceDefinition'
519           }
520         }
521     );
522
523     $stateProvider.state(
524         'workspace.plugins', {
525           url: 'plugins/*path',
526           parent: 'workspace',
527           template: '<plugin-context-view></plugin-context-view>',
528           resolve: {
529             componentData: ['injectComponent', '$stateParams', function(injectComponent: Component, $stateParams) {
530               $stateParams.component = injectComponent;
531               return injectComponent;
532             }],
533           }
534
535         }
536     );
537
538     $stateProvider.state(
539         'adminDashboard', {
540           url: '/adminDashboard',
541           templateUrl: './view-models/admin-dashboard/admin-dashboard-view.html',
542           controller: viewModelsModuleName + '.AdminDashboardViewModel',
543           permissions: ['ADMIN']
544         }
545     );
546
547     $stateProvider.state(
548         'onboardVendor', {
549           url: '/onboardVendor',
550           templateUrl: './view-models/onboard-vendor/onboard-vendor-view.html',
551           controller: viewModelsModuleName + '.OnboardVendorViewModel'
552         }
553     );
554
555     $stateProvider.state(
556         'plugins', {
557           url: '/plugins/*path',
558           template: '<plugin-tab-view></plugin-tab-view>'
559         }
560     );
561
562     // Build the states for all hosted apps dynamically
563     _.each(hostedApplications, (hostedApp) => {
564       if (hostedApp.exists) {
565         $stateProvider.state(
566             hostedApp.state.name, {
567               url: hostedApp.state.url,
568               templateUrl: './view-models/dcae-app/dcae-app-view.html',
569               controller: viewModelsModuleName + hostedApp.state.controllerName
570             }
571         );
572       }
573     });
574
575     $stateProvider.state(
576         'catalog', {
577           url: '/catalog?filter.components&filter.resourceSubTypes&filter.categories&filter.statuses&filter.order&filter.term&filter.active',
578           template: '<catalog-page></catalog-page>',
579           resolve: {
580             auth: ['$q', 'AuthenticationServiceNg2', ($q: any, authService: AuthenticationService) => {
581               const userInfo: IUserProperties = authService.getLoggedinUser();
582               if (userInfo) {
583                 return $q.when(userInfo);
584               } else {
585                 return $q.reject({authenticated: false});
586               }
587             }]
588           }
589         }
590     );
591
592     $stateProvider.state(
593         'error-403', {
594           url: '/error-403',
595           templateUrl: './view-models/modals/error-modal/error-403-view.html',
596           controller: viewModelsModuleName + '.ErrorViewModel'
597         }
598     );
599
600     tooltipsConfigProvider.options({
601       side: 'bottom',
602       delay: '600',
603       class: 'tooltip-custom',
604       lazy: 0,
605       try: 0
606     });
607
608   }
609 ]);
610
611 ng1appModule.value('ValidationPattern', /^[\s\w\&_.:-]{1,1024}$/);
612 ng1appModule.value('ComponentNameValidationPattern', /^(?=.*[^. ])[\s\w\&_.:-]{1,1024}$/); // DE250513 - same as ValidationPattern above, plus requirement that name not consist of dots and/or spaces alone.
613 ng1appModule.value('PropertyNameValidationPattern', /^[a-zA-Z0-9._:\-@]{1,100}$/); // DE210977
614 ng1appModule.value('TagValidationPattern', /^[\s\w_.-]{1,50}$/);
615 ng1appModule.value('VendorReleaseValidationPattern', /^[\x20-\x21\x23-\x29\x2B-\x2E\x30-\x39\x3B\x3D\x40-\x5B\x5D-\x7B\x7D-\xFF]{1,25}$/);
616 ng1appModule.value('VendorNameValidationPattern', /^[\x20-\x21\x23-\x29\x2B-\x2E\x30-\x39\x3B\x3D\x40-\x5B\x5D-\x7B\x7D-\xFF]{1,60}$/);
617 ng1appModule.value('VendorModelNumberValidationPattern', /^[\x20-\x21\x23-\x29\x2B-\x2E\x30-\x39\x3B\x3D\x40-\x5B\x5D-\x7B\x7D-\xFF]{1,65}$/);
618 ng1appModule.value('ServiceTypeAndRoleValidationPattern', /^[\x20-\x21\x23-\x29\x2B-\x2E\x30-\x39\x3B\x3D\x40-\x5B\x5D-\x7B\x7D-\xFF]{1,256}$/);
619 ng1appModule.value('ContactIdValidationPattern', /^[\s\w-]{1,50}$/);
620 ng1appModule.value('UserIdValidationPattern', /^[\s\w-]{1,50}$/);
621 ng1appModule.value('LabelValidationPattern', /^[\sa-zA-Z0-9+-]{1,25}$/);
622 ng1appModule.value('UrlValidationPattern', /^(https?|ftp):\/\/(((([A-Za-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([A-Za-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([A-Za-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([A-Za-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([A-Za-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([A-Za-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([A-Za-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([A-Za-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([A-Za-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([A-Za-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([A-Za-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([A-Za-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/);
623 ng1appModule.value('IntegerValidationPattern', /^(([-+]?\d+)|([-+]?0x[0-9a-fA-F]+))$/);
624 ng1appModule.value('IntegerNoLeadingZeroValidationPattern', /^(0|[-+]?[1-9][0-9]*|[-+]?0x[0-9a-fA-F]+|[-+]?0o[0-7]+)$/);
625 ng1appModule.value('FloatValidationPattern', /^[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?f?$/);
626 ng1appModule.value('NumberValidationPattern', /^((([-+]?\d+)|([-+]?0x[0-9a-fA-F]+))|([-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?))$/);
627 ng1appModule.value('KeyValidationPattern', /^[\s\w-]{1,50}$/);
628 ng1appModule.value('CommentValidationPattern', /^[\u0000-\u00BF]*$/);
629 ng1appModule.value('BooleanValidationPattern', /^([Tt][Rr][Uu][Ee]|[Ff][Aa][Ll][Ss][Ee])$/);
630 ng1appModule.value('MapKeyValidationPattern', /^[\w]{1,50}$/);
631
632 ng1appModule.constant('sdcConfig', sdcConfig);
633 ng1appModule.constant('sdcMenu', sdcMenu);
634
635 ng1appModule.run([
636   '$http',
637   'Sdc.Services.CacheService',
638   'Sdc.Services.CookieService',
639   'AuthenticationServiceNg2',
640   '$state',
641   '$rootScope',
642   '$location',
643   'sdcMenu',
644   'Sdc.Services.EcompHeaderService',
645   'LeftPaletteLoaderService',
646   'Sdc.Services.DataTypesService',
647   'AngularJSBridge',
648   '$templateCache',
649   'ModalServiceSdcUI',
650   ($http: ng.IHttpService,
651    cacheService: CacheService,
652    cookieService: CookieService,
653    authService: AuthenticationService,
654    $state: ng.ui.IStateService,
655    $rootScope: ng.IRootScopeService,
656    $location: ng.ILocationService,
657    sdcMenu: IAppMenu,
658    ecompHeaderService: EcompHeaderService,
659    LeftPaletteLoaderService: LeftPaletteLoaderService,
660    DataTypesService: DataTypesService,
661    AngularJSBridge,
662    $templateCache: ng.ITemplateCacheService,
663    ModalServiceSdcUI: SdcUiServices.ModalService): void => {
664     $templateCache.put('notification-custom-template.html', require('./view-models/shared/notification-custom-template.html'));
665     $templateCache.put('notification-custom-template.html', require('./view-models/shared/notification-custom-template.html'));
666
667     // Add hosted applications to sdcConfig
668     sdcConfig.hostedApplications = hostedApplications;
669
670     // handle http config
671     $http.defaults.withCredentials = true;
672     $http.defaults.headers.common[cookieService.getUserIdSuffix()] = cookieService.getUserId();
673
674     DataTypesService.loadDataTypesCache(null);
675
676     // handle stateChangeStart
677     const internalDeregisterStateChangeStartWatcher: Function = (): void => {
678       if (deregisterStateChangeStartWatcher) {
679         deregisterStateChangeStartWatcher();
680         deregisterStateChangeStartWatcher = null;
681       }
682       if (deregisterStateChangeSuccessWatcher) {
683         deregisterStateChangeSuccessWatcher();
684         deregisterStateChangeSuccessWatcher = null;
685       }
686     };
687
688     const removeLoader: Function = (): void => {
689       $('.sdc-loading-page .main-loader').addClass('animated fadeOut');
690       $('.sdc-loading-page .caption1').addClass('animated fadeOut');
691       $('.sdc-loading-page .caption2').addClass('animated fadeOut');
692       window.setTimeout((): void => {
693         $('.sdc-loading-page .main-loader').css('display', 'none');
694         $('.sdc-loading-page .caption1').css('display', 'none');
695         $('.sdc-loading-page .caption2').css('display', 'none');
696         $('.sdc-loading-page').addClass('animated fadeOut');
697       }, 1000);
698     };
699
700     const onNavigateOut: Function = (toState, toParams): void => {
701       const onOk: Function = (): void => {
702         $state.current.data.unsavedChanges = false;
703         $state.go(toState.name, toParams);
704       };
705
706       const data = sdcMenu.alertMessages.exitWithoutSaving;
707       const okButton = {
708         testId: 'OK',
709         text: sdcMenu.alertMessages.okButton,
710         type: SdcUiCommon.ButtonType.warning,
711         callback: onOk,
712         closeModal: true
713       } as SdcUiComponents.ModalButtonComponent;
714       // open notify to user if changes are not saved
715       ModalServiceSdcUI.openWarningModal(data.title,
716           data.message,
717           'navigate-modal',
718           [okButton]);
719     };
720
721     const onStateChangeStart: Function = (event, toState, toParams, fromState, fromParams): void => {
722       console.debug((new Date()).getTime());
723       console.debug('$stateChangeStart', toState.name);
724       if (toState.name !== 'error-403' && !authService.getLoggedinUser()) {
725
726         authService.authenticate().subscribe((userInfo: IUserProperties) => {
727           if (!doesUserHasAccess(toState, userInfo)) {
728             $state.go('error-403');
729             console.debug('User has no permissions');
730             return;
731           }
732           authService.setLoggedinUser(userInfo);
733           setTimeout(function() {
734
735             removeLoader();
736
737             if (authService.getLoggedinUser().role === 'ADMIN') {
738               $state.go('adminDashboard', toParams);
739               return;
740             }
741
742             // After user authorized init categories
743             window.setTimeout((): void => {
744               if ($state.current.name === '') {
745                 $state.go(toState.name, toParams);
746               }
747
748               console.log('------$state.current.name=' + $state.current.name);
749
750             }, 1000);
751
752           }, 0);
753
754         }, () => {
755           $state.go('error-403');
756         });
757       } else if (authService.getLoggedinUser()) {
758         const user: IUserProperties = authService.getLoggedinUser();
759         if (!cacheService.contains('user')) {
760           cacheService.set('user', user);
761         }
762
763         if (!doesUserHasAccess(toState, authService.getLoggedinUser())) {
764           event.preventDefault();
765           $state.go('error-403');
766           console.debug('User has no permissions');
767         }
768
769         if (authService.getLoggedinUser().role === 'ADMIN') {
770           $state.go('adminDashboard', toParams);
771           return;
772         }
773
774         // if form is dirty and not save  - notify to user
775         if (fromState.data && fromState.data.unsavedChanges && fromParams.id != toParams.id) {
776           event.preventDefault();
777           onNavigateOut(toState, toParams);
778         }
779       }
780
781       // if enetering workspace, set the previousState param
782       if (toState.name.indexOf('workspace') !== -1) {
783         if (!toParams.previousState) {
784           const tmpPreviousState1 = fromParams && fromParams.previousState;
785           const tmpPreviousState2 = (['dashboard', 'catalog'].indexOf(fromState.name) !== -1) ? fromState.name : 'catalog';
786           toParams.previousState = tmpPreviousState1 || tmpPreviousState2;
787         }
788       }
789
790     };
791
792     const onStateChangeSuccess: Function = (event, toState, toParams, fromState, fromParams): void => {
793       console.debug('$stateChangeSuccess', toState.name);
794
795       // Workaround in case we are entering other state then workspace (user move to catalog)
796       // remove the changeComponentCsarVersion, user should open again the VSP list and select one for update.
797       if (toState.name.indexOf('workspace') === -1) {
798         if (cacheService.contains(CHANGE_COMPONENT_CSAR_VERSION_FLAG)) {
799           cacheService.remove(CHANGE_COMPONENT_CSAR_VERSION_FLAG);
800         }
801         if (cacheService.contains(PREVIOUS_CSAR_COMPONENT)) {
802           cacheService.remove(PREVIOUS_CSAR_COMPONENT);
803         }
804       }
805
806       // set body class
807       $rootScope.bodyClass = 'default-class';
808       if (toState.data && toState.data.bodyClass) {
809         $rootScope.bodyClass = toState.data.bodyClass;
810       }
811     };
812
813     const doesUserHasAccess: Function = (toState, user): boolean => {
814
815       let isUserHasAccess = true;
816       if (toState.permissions && toState.permissions.length > 0) {
817         isUserHasAccess = _.includes(toState.permissions, user.role);
818       }
819       return isUserHasAccess;
820     };
821     let deregisterStateChangeStartWatcher: Function;
822     let deregisterStateChangeSuccessWatcher: Function;
823
824     const registerStateChangeStartWatcher: Function = (): void => {
825       internalDeregisterStateChangeStartWatcher();
826       console.debug('registerStateChangeStartWatcher $stateChangeStart');
827       deregisterStateChangeStartWatcher = $rootScope.$on('$stateChangeStart', (event, toState, toParams, fromState, fromParams): void => {
828         onStateChangeStart(event, toState, toParams, fromState, fromParams);
829       });
830       deregisterStateChangeSuccessWatcher = $rootScope.$on('$stateChangeSuccess', (event, toState, toParams, fromState, fromParams): void => {
831         onStateChangeSuccess(event, toState, toParams, fromState, fromParams);
832       });
833     };
834     registerStateChangeStartWatcher();
835   }]);