Merge "InvalidRoleException-junits"
authorLorraine Welch <lb2391@att.com>
Tue, 21 Jan 2020 23:24:07 +0000 (23:24 +0000)
committerGerrit Code Review <gerrit@onap.org>
Tue, 21 Jan 2020 23:24:07 +0000 (23:24 +0000)
343 files changed:
.gitignore
docs/tutorials/portal-BE/index.rst
docs/tutorials/portal-BE/request-flow.rst [new file with mode: 0644]
docs/tutorials/portal-BE/requestflow.jpeg [new file with mode: 0644]
ecomp-portal-BE-common/src/main/java/org/onap/portalapp/portal/scheduleraux/SchedulerAuxUtil.java
ecomp-portal-BE-common/src/main/java/org/onap/portalapp/portal/service/EPRoleServiceImpl.java
ecomp-portal-BE-common/src/test/java/org/onap/portalapp/portal/exceptions/ExternalAuthSystemExceptionTest.java [new file with mode: 0644]
ecomp-portal-BE-common/src/test/java/org/onap/portalapp/portal/exceptions/InactiveApplicationExceptionTest.java [new file with mode: 0644]
ecomp-portal-BE-common/src/test/java/org/onap/portalapp/portal/exceptions/InvalidUserExceptionTest.java [new file with mode: 0644]
ecomp-portal-BE-common/src/test/java/org/onap/portalapp/portal/exceptions/SyncUserRolesExceptionTest.java [new file with mode: 0644]
ecomp-portal-widget-ms/widget-ms/src/test/java/org/onap/portalapp/widget/exception/StorageFileNotFoundExceptionTest.java [new file with mode: 0644]
portal-BE/pom.xml
portal-BE/src/main/java/org/onap/portal/PortalApplication.java
portal-BE/src/main/java/org/onap/portal/aop/service/FnLanguageServiceAOP.java
portal-BE/src/main/java/org/onap/portal/aop/service/FnUserServiceAOP.java
portal-BE/src/main/java/org/onap/portal/aop/service/WidgetServiceAOP.java
portal-BE/src/main/java/org/onap/portal/configuration/DBInitializingBean.java
portal-BE/src/main/java/org/onap/portal/configuration/SecurityConfig.java
portal-BE/src/main/java/org/onap/portal/configuration/WebMvcConfiguration.java
portal-BE/src/main/java/org/onap/portal/controller/LanguageController.java
portal-BE/src/main/java/org/onap/portal/controller/UserController.java
portal-BE/src/main/java/org/onap/portal/controller/UserRolesController.java
portal-BE/src/main/java/org/onap/portal/controller/WidgetsCatalogController.java
portal-BE/src/main/java/org/onap/portal/controller/WidgetsController.java
portal-BE/src/main/java/org/onap/portal/domain/dto/transport/ProfileDetail.java
portal-BE/src/main/java/org/onap/portal/logging/aop/EPEELFLoggerAdvice.java
portal-BE/src/main/java/org/onap/portal/service/AdminRolesService.java
portal-BE/src/main/java/org/onap/portal/service/AppsCacheService.java
portal-BE/src/main/java/org/onap/portal/service/EPRoleFunctionService.java [moved from portal-BE/src/main/java/org/onap/portal/service/fn/old/EPRoleFunctionService.java with 98% similarity]
portal-BE/src/main/java/org/onap/portal/service/ExternalAccessRolesService.java
portal-BE/src/main/java/org/onap/portal/service/PersUserWidgetService.java
portal-BE/src/main/java/org/onap/portal/service/app/FnAppDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/fn/FnAppDao.java with 84% similarity]
portal-BE/src/main/java/org/onap/portal/service/app/FnAppService.java [moved from portal-BE/src/main/java/org/onap/portal/service/fn/FnAppService.java with 95% similarity]
portal-BE/src/main/java/org/onap/portal/service/appContactUs/FnAppContactUsDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/fn/FnAppContactUsDao.java with 94% similarity]
portal-BE/src/main/java/org/onap/portal/service/appContactUs/FnAppContactUsService.java [new file with mode: 0644]
portal-BE/src/main/java/org/onap/portal/service/appFunction/EpAppFunctionDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/ep/EpAppFunctionDao.java with 95% similarity]
portal-BE/src/main/java/org/onap/portal/service/appFunction/EpAppFunctionService.java [moved from portal-BE/src/main/java/org/onap/portal/service/ep/EpAppFunctionService.java with 94% similarity]
portal-BE/src/main/java/org/onap/portal/service/appRoleFunction/EpAppRoleFunctionDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/ep/EpAppRoleFunctionDao.java with 94% similarity]
portal-BE/src/main/java/org/onap/portal/service/appRoleFunction/EpAppRoleFunctionService.java [new file with mode: 0644]
portal-BE/src/main/java/org/onap/portal/service/auditLog/FnAuditLogDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/fn/FnAuditLogDao.java with 94% similarity]
portal-BE/src/main/java/org/onap/portal/service/auditLog/FnAuditLogService.java [new file with mode: 0644]
portal-BE/src/main/java/org/onap/portal/service/basicAuthAccount/EpBasicAuthAccountDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/ep/EpBasicAuthAccountDao.java with 94% similarity]
portal-BE/src/main/java/org/onap/portal/service/basicAuthAccount/EpBasicAuthAccountService.java [new file with mode: 0644]
portal-BE/src/main/java/org/onap/portal/service/commonWidgetData/FnCommonWidgetDataDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/fn/FnCommonWidgetDataDao.java with 94% similarity]
portal-BE/src/main/java/org/onap/portal/service/commonWidgetData/FnCommonWidgetDataService.java [new file with mode: 0644]
portal-BE/src/main/java/org/onap/portal/service/displayText/FnDisplayTextDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/fn/FnDisplayTextDao.java with 94% similarity]
portal-BE/src/main/java/org/onap/portal/service/displayText/FnDisplayTextService.java [new file with mode: 0644]
portal-BE/src/main/java/org/onap/portal/service/function/FnFunctionDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/fn/FnFunctionDao.java with 94% similarity]
portal-BE/src/main/java/org/onap/portal/service/function/FnFunctionService.java [new file with mode: 0644]
portal-BE/src/main/java/org/onap/portal/service/language/FnLanguageDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/fn/FnLanguageDao.java with 95% similarity]
portal-BE/src/main/java/org/onap/portal/service/language/FnLanguageService.java [moved from portal-BE/src/main/java/org/onap/portal/service/fn/FnLanguageService.java with 90% similarity]
portal-BE/src/main/java/org/onap/portal/service/luActivity/FnLuActivityDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/fn/FnLuActivityDao.java with 94% similarity]
portal-BE/src/main/java/org/onap/portal/service/luActivity/FnLuActivityService.java [new file with mode: 0644]
portal-BE/src/main/java/org/onap/portal/service/luAlertMethod/FnLuAlertMethodDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/fn/FnLuAlertMethodDao.java with 94% similarity]
portal-BE/src/main/java/org/onap/portal/service/luAlertMethod/FnLuAlertMethodService.java [new file with mode: 0644]
portal-BE/src/main/java/org/onap/portal/service/luMenuSet/FnLuMenuSetDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/fn/FnLuMenuSetDao.java with 94% similarity]
portal-BE/src/main/java/org/onap/portal/service/luMenuSet/FnLuMenuSetService.java [new file with mode: 0644]
portal-BE/src/main/java/org/onap/portal/service/luPriority/FnLuPriorityDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/fn/FnLuPriorityDao.java with 94% similarity]
portal-BE/src/main/java/org/onap/portal/service/luPriority/FnLuPriorityService.java [new file with mode: 0644]
portal-BE/src/main/java/org/onap/portal/service/luTabSet/FnLuTabSetDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/fn/FnLuTabSetDao.java with 94% similarity]
portal-BE/src/main/java/org/onap/portal/service/luTabSet/FnLuTabSetService.java [new file with mode: 0644]
portal-BE/src/main/java/org/onap/portal/service/luTimezone/FnLuTimezoneDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/fn/FnLuTimezoneDao.java with 94% similarity]
portal-BE/src/main/java/org/onap/portal/service/luTimezone/FnLuTimezoneService.java [moved from portal-BE/src/main/java/org/onap/portal/service/fn/FnLuTimezoneService.java with 92% similarity]
portal-BE/src/main/java/org/onap/portal/service/menu/FnMenuDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/fn/FnMenuDao.java with 95% similarity]
portal-BE/src/main/java/org/onap/portal/service/menu/FnMenuService.java [new file with mode: 0644]
portal-BE/src/main/java/org/onap/portal/service/menuFunctional/FnMenuFunctionalDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/fn/FnMenuFunctionalDao.java with 94% similarity]
portal-BE/src/main/java/org/onap/portal/service/menuFunctional/FnMenuFunctionalService.java [moved from portal-BE/src/main/java/org/onap/portal/service/fn/FnMenuFunctionalService.java with 92% similarity]
portal-BE/src/main/java/org/onap/portal/service/menuFunctionalAncestors/FnMenuFunctionalAncestorsDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/fn/FnMenuFunctionalAncestorsDao.java with 93% similarity]
portal-BE/src/main/java/org/onap/portal/service/menuFunctionalAncestors/FnMenuFunctionalAncestorsService.java [new file with mode: 0644]
portal-BE/src/main/java/org/onap/portal/service/menuFunctionalRoles/FnMenuFunctionalRolesDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/fn/FnMenuFunctionalRolesDao.java with 94% similarity]
portal-BE/src/main/java/org/onap/portal/service/menuFunctionalRoles/FnMenuFunctionalRolesService.java [moved from portal-BE/src/main/java/org/onap/portal/service/fn/FnMenuFunctionalRolesService.java with 93% similarity]
portal-BE/src/main/java/org/onap/portal/service/microservice/EpMicroserviceDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/ep/EpMicroserviceDao.java with 94% similarity]
portal-BE/src/main/java/org/onap/portal/service/microservice/EpMicroserviceService.java [new file with mode: 0644]
portal-BE/src/main/java/org/onap/portal/service/microserviceParameter/EpMicroserviceParameterDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/ep/EpMicroserviceParameterDao.java with 94% similarity]
portal-BE/src/main/java/org/onap/portal/service/microserviceParameter/EpMicroserviceParameterService.java [moved from portal-BE/src/main/java/org/onap/portal/service/ep/EpMicroserviceParameterService.java with 93% similarity]
portal-BE/src/main/java/org/onap/portal/service/persUserAppSel/FnPersUserAppSelDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/fn/FnPersUserAppSelDao.java with 94% similarity]
portal-BE/src/main/java/org/onap/portal/service/persUserAppSel/FnPersUserAppSelService.java [new file with mode: 0644]
portal-BE/src/main/java/org/onap/portal/service/persUserAppSort/EpPersUserAppSortDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/ep/EpPersUserAppSortDao.java with 94% similarity]
portal-BE/src/main/java/org/onap/portal/service/persUserAppSort/EpPersUserAppSortService.java [new file with mode: 0644]
portal-BE/src/main/java/org/onap/portal/service/persUserWidgetSel/EpPersUserWidgetSelDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/ep/EpPersUserWidgetSelDao.java with 94% similarity]
portal-BE/src/main/java/org/onap/portal/service/persUserWidgetSel/EpPersUserWidgetSelService.java [new file with mode: 0644]
portal-BE/src/main/java/org/onap/portal/service/qzCronTriggers/FnQzCronTriggersDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/fn/FnQzCronTriggersDao.java with 94% similarity]
portal-BE/src/main/java/org/onap/portal/service/qzCronTriggers/FnQzCronTriggersService.java [new file with mode: 0644]
portal-BE/src/main/java/org/onap/portal/service/qzJobDetails/FnQzJobDetailsDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/fn/FnQzJobDetailsDao.java with 94% similarity]
portal-BE/src/main/java/org/onap/portal/service/qzJobDetails/FnQzJobDetailsService.java [new file with mode: 0644]
portal-BE/src/main/java/org/onap/portal/service/qzLocks/FnQzLocksDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/fn/FnQzLocksDao.java with 94% similarity]
portal-BE/src/main/java/org/onap/portal/service/qzLocks/FnQzLocksService.java [new file with mode: 0644]
portal-BE/src/main/java/org/onap/portal/service/qzSchedulerState/FnQzSchedulerStateDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/fn/FnQzSchedulerStateDao.java with 93% similarity]
portal-BE/src/main/java/org/onap/portal/service/qzSchedulerState/FnQzSchedulerStateService.java [new file with mode: 0644]
portal-BE/src/main/java/org/onap/portal/service/qzTriggers/FnQzTriggersDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/fn/FnQzTriggersDao.java with 94% similarity]
portal-BE/src/main/java/org/onap/portal/service/qzTriggers/FnQzTriggersService.java [new file with mode: 0644]
portal-BE/src/main/java/org/onap/portal/service/restrictedUrl/FnRestrictedUrlDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/fn/FnRestrictedUrlDao.java with 94% similarity]
portal-BE/src/main/java/org/onap/portal/service/restrictedUrl/FnRestrictedUrlService.java [new file with mode: 0644]
portal-BE/src/main/java/org/onap/portal/service/role/FnRoleDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/fn/FnRoleDao.java with 96% similarity]
portal-BE/src/main/java/org/onap/portal/service/role/FnRoleService.java [moved from portal-BE/src/main/java/org/onap/portal/service/fn/FnRoleService.java with 97% similarity]
portal-BE/src/main/java/org/onap/portal/service/roleComposite/FnRoleCompositeDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/fn/FnRoleCompositeDao.java with 94% similarity]
portal-BE/src/main/java/org/onap/portal/service/roleComposite/FnRoleCompositeService.java [new file with mode: 0644]
portal-BE/src/main/java/org/onap/portal/service/roleFunction/FnRoleFunctionDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/fn/FnRoleFunctionDao.java with 94% similarity]
portal-BE/src/main/java/org/onap/portal/service/roleFunction/FnRoleFunctionService.java [new file with mode: 0644]
portal-BE/src/main/java/org/onap/portal/service/sharedContext/FnSharedContextDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/fn/FnSharedContextDao.java with 94% similarity]
portal-BE/src/main/java/org/onap/portal/service/sharedContext/FnSharedContextService.java [new file with mode: 0644]
portal-BE/src/main/java/org/onap/portal/service/tab/FnTabDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/fn/FnTabDao.java with 95% similarity]
portal-BE/src/main/java/org/onap/portal/service/tab/FnTabService.java [new file with mode: 0644]
portal-BE/src/main/java/org/onap/portal/service/tabSelected/FnTabSelectedDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/fn/FnTabSelectedDao.java with 94% similarity]
portal-BE/src/main/java/org/onap/portal/service/tabSelected/FnTabSelectedService.java [new file with mode: 0644]
portal-BE/src/main/java/org/onap/portal/service/user/FnUserDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/fn/FnUserDao.java with 96% similarity]
portal-BE/src/main/java/org/onap/portal/service/user/FnUserService.java [moved from portal-BE/src/main/java/org/onap/portal/service/fn/FnUserService.java with 89% similarity]
portal-BE/src/main/java/org/onap/portal/service/userRole/FnUserRoleDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/fn/FnUserRoleDao.java with 96% similarity]
portal-BE/src/main/java/org/onap/portal/service/userRole/FnUserRoleService.java [moved from portal-BE/src/main/java/org/onap/portal/service/fn/FnUserRoleService.java with 98% similarity]
portal-BE/src/main/java/org/onap/portal/service/userRolesRequest/EpUserRolesRequestDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/ep/EpUserRolesRequestDao.java with 94% similarity]
portal-BE/src/main/java/org/onap/portal/service/userRolesRequest/EpUserRolesRequestService.java [moved from portal-BE/src/main/java/org/onap/portal/service/ep/EpUserRolesRequestService.java with 96% similarity]
portal-BE/src/main/java/org/onap/portal/service/userRolesRequestDet/EpUserRolesRequestDetDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/ep/EpUserRolesRequestDetDao.java with 94% similarity]
portal-BE/src/main/java/org/onap/portal/service/userRolesRequestDet/EpUserRolesRequestDetService.java [moved from portal-BE/src/main/java/org/onap/portal/service/ep/EpUserRolesRequestDetService.java with 96% similarity]
portal-BE/src/main/java/org/onap/portal/service/widget/FnWidgetDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/fn/FnWidgetDao.java with 95% similarity]
portal-BE/src/main/java/org/onap/portal/service/widget/WidgetService.java [moved from portal-BE/src/main/java/org/onap/portal/service/WidgetService.java with 98% similarity]
portal-BE/src/main/java/org/onap/portal/service/widgetCatalog/EpWidgetCatalogDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/fn/EpWidgetCatalogDao.java with 94% similarity]
portal-BE/src/main/java/org/onap/portal/service/widgetCatalog/EpWidgetCatalogService.java [moved from portal-BE/src/main/java/org/onap/portal/service/ep/EpWidgetCatalogService.java with 59% similarity]
portal-BE/src/main/java/org/onap/portal/service/widgetCatalogParameter/EpWidgetCatalogParameterDao.java [moved from portal-BE/src/main/java/org/onap/portal/dao/ep/EpWidgetCatalogParameterDao.java with 85% similarity]
portal-BE/src/main/java/org/onap/portal/service/widgetCatalogParameter/EpWidgetCatalogParameterService.java [moved from portal-BE/src/main/java/org/onap/portal/service/ep/EpWidgetCatalogParameterService.java with 97% similarity]
portal-BE/src/main/java/org/onap/portal/utils/EPUserUtils.java
portal-BE/src/test/java/org/onap/portal/controller/LanguageControllerTest.java
portal-BE/src/test/java/org/onap/portal/controller/UserControllerTest.java
portal-BE/src/test/java/org/onap/portal/controller/UserRolesControllerTest.java
portal-BE/src/test/java/org/onap/portal/controller/WidgetsCatalogControllerTest.java
portal-BE/src/test/java/org/onap/portal/controller/WidgetsControllerTest.java
portal-BE/src/test/java/org/onap/portal/exception/NotValidDataExceptionTest.java [new file with mode: 0644]
portal-BE/src/test/java/org/onap/portal/framework/MockitoTestSuite.java
portal-BE/src/test/java/org/onap/portal/service/ep/EpMicroserviceParameterServiceTest.java
portal-BE/src/test/java/org/onap/portal/service/ep/EpWidgetCatalogParameterServiceTest.java
portal-BE/src/test/java/org/onap/portal/service/fn/FnUserRoleServiceTest.java
portal-BE/src/test/java/org/onap/portal/service/fn/FnUserServiceTest.java
portal-FE-common/.gitignore [new file with mode: 0644]
portal-FE-common/pom.xml [new file with mode: 0644]
portal-FE-common/src/app/modals/confirmation-modal/confirmation-modal.component.html [new file with mode: 0644]
portal-FE-common/src/app/modals/confirmation-modal/confirmation-modal.component.scss [new file with mode: 0644]
portal-FE-common/src/app/modals/confirmation-modal/confirmation-modal.component.spec.ts [new file with mode: 0644]
portal-FE-common/src/app/modals/confirmation-modal/confirmation-modal.component.ts [new file with mode: 0644]
portal-FE-common/src/app/modals/information-modal/information-modal.component.html [new file with mode: 0644]
portal-FE-common/src/app/modals/information-modal/information-modal.component.scss [new file with mode: 0644]
portal-FE-common/src/app/modals/information-modal/information-modal.component.spec.ts [new file with mode: 0644]
portal-FE-common/src/app/modals/information-modal/information-modal.component.ts [new file with mode: 0644]
portal-FE-common/src/app/ng-material-module.ts [new file with mode: 0644]
portal-FE-common/src/app/pages/account-onboarding/account-add-details/account-add-details.component.html [new file with mode: 0644]
portal-FE-common/src/app/pages/account-onboarding/account-add-details/account-add-details.component.scss [new file with mode: 0644]
portal-FE-common/src/app/pages/account-onboarding/account-add-details/account-add-details.component.spec.ts [new file with mode: 0644]
portal-FE-common/src/app/pages/account-onboarding/account-add-details/account-add-details.component.ts [new file with mode: 0644]
portal-FE-common/src/app/pages/account-onboarding/account-onboarding.component.html [new file with mode: 0644]
portal-FE-common/src/app/pages/account-onboarding/account-onboarding.component.scss [new file with mode: 0644]
portal-FE-common/src/app/pages/account-onboarding/account-onboarding.component.spec.ts [new file with mode: 0644]
portal-FE-common/src/app/pages/account-onboarding/account-onboarding.component.ts [new file with mode: 0644]
portal-FE-common/src/app/pages/application-catalog/application-catalog.component.html [new file with mode: 0644]
portal-FE-common/src/app/pages/application-catalog/application-catalog.component.scss [new file with mode: 0644]
portal-FE-common/src/app/pages/application-catalog/application-catalog.component.spec.ts [new file with mode: 0644]
portal-FE-common/src/app/pages/application-catalog/application-catalog.component.ts [new file with mode: 0644]
portal-FE-common/src/app/pages/contact-us/contact-us-manage/contact-us-manage.component.html [new file with mode: 0644]
portal-FE-common/src/app/pages/contact-us/contact-us-manage/contact-us-manage.component.scss [new file with mode: 0644]
portal-FE-common/src/app/pages/contact-us/contact-us-manage/contact-us-manage.component.spec.ts [new file with mode: 0644]
portal-FE-common/src/app/pages/contact-us/contact-us-manage/contact-us-manage.component.ts [new file with mode: 0644]
portal-FE-common/src/app/pages/contact-us/contact-us.component.html [new file with mode: 0644]
portal-FE-common/src/app/pages/contact-us/contact-us.component.scss [new file with mode: 0644]
portal-FE-common/src/app/pages/contact-us/contact-us.component.spec.ts [new file with mode: 0644]
portal-FE-common/src/app/pages/contact-us/contact-us.component.ts [new file with mode: 0644]
portal-FE-common/src/app/pages/microservice-onboarding/microservice-add-details/microservice-add-details.component.html [new file with mode: 0644]
portal-FE-common/src/app/pages/microservice-onboarding/microservice-add-details/microservice-add-details.component.scss [new file with mode: 0644]
portal-FE-common/src/app/pages/microservice-onboarding/microservice-add-details/microservice-add-details.component.spec.ts [new file with mode: 0644]
portal-FE-common/src/app/pages/microservice-onboarding/microservice-add-details/microservice-add-details.component.ts [new file with mode: 0644]
portal-FE-common/src/app/pages/microservice-onboarding/microservice-onboarding.component.html [new file with mode: 0644]
portal-FE-common/src/app/pages/microservice-onboarding/microservice-onboarding.component.scss [new file with mode: 0644]
portal-FE-common/src/app/pages/microservice-onboarding/microservice-onboarding.component.spec.ts [new file with mode: 0644]
portal-FE-common/src/app/pages/microservice-onboarding/microservice-onboarding.component.ts [new file with mode: 0644]
portal-FE-common/src/app/shared/model/account-onboarding/accountOnboarding.ts [new file with mode: 0644]
portal-FE-common/src/app/shared/model/microservice-onboarding/microservices.ts [new file with mode: 0644]
portal-FE-common/src/app/shared/services/basic-auth-account/basic-auth-account.service.spec.ts [new file with mode: 0644]
portal-FE-common/src/app/shared/services/basic-auth-account/basic-auth-account.service.ts [new file with mode: 0644]
portal-FE-common/src/app/shared/services/contact-us/contact-us.service.spec.ts [new file with mode: 0644]
portal-FE-common/src/app/shared/services/contact-us/contact-us.service.ts [new file with mode: 0644]
portal-FE-common/src/app/shared/services/microservice/microservice.service.spec.ts [new file with mode: 0644]
portal-FE-common/src/app/shared/services/microservice/microservice.service.ts [new file with mode: 0644]
portal-FE-common/src/assets/images/spinner.gif [new file with mode: 0644]
portal-FE-common/src/styles/_fonts.scss [new file with mode: 0644]
portal-FE-common/src/styles/_responsive.scss [new file with mode: 0644]
portal-FE-common/src/styles/_spinner.scss [new file with mode: 0644]
portal-FE-common/src/styles/_utils.scss [new file with mode: 0644]
portal-FE-common/src/styles/app.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/_alert.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/_badge.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/_breadcrumb.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/_button-group.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/_buttons.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/_card.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/_carousel.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/_close.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/_code.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/_custom-forms.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/_dropdown.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/_forms.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/_functions.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/_grid.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/_images.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/_input-group.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/_jumbotron.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/_list-group.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/_media.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/_mixins.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/_modal.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/_nav.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/_navbar.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/_pagination.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/_popover.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/_print.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/_progress.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/_reboot.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/_root.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/_tables.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/_tooltip.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/_transitions.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/_type.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/_utilities.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/_variables.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/bootstrap-grid.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/bootstrap-reboot.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/bootstrap.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/mixins/_alert.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/mixins/_background-variant.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/mixins/_badge.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/mixins/_border-radius.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/mixins/_box-shadow.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/mixins/_breakpoints.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/mixins/_buttons.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/mixins/_caret.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/mixins/_clearfix.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/mixins/_float.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/mixins/_forms.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/mixins/_gradients.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/mixins/_grid-framework.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/mixins/_grid.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/mixins/_hover.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/mixins/_image.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/mixins/_list-group.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/mixins/_lists.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/mixins/_nav-divider.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/mixins/_navbar-align.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/mixins/_pagination.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/mixins/_reset-text.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/mixins/_resize.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/mixins/_screen-reader.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/mixins/_size.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/mixins/_table-row.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/mixins/_text-emphasis.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/mixins/_text-hide.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/mixins/_text-truncate.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/mixins/_transition.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/mixins/_visibility.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/utilities/_align.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/utilities/_background.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/utilities/_borders.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/utilities/_clearfix.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/utilities/_display.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/utilities/_embed.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/utilities/_flex.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/utilities/_float.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/utilities/_position.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/utilities/_screenreaders.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/utilities/_sizing.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/utilities/_spacing.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/utilities/_text.scss [new file with mode: 0644]
portal-FE-common/src/styles/bootstrap/utilities/_visibility.scss [new file with mode: 0644]
portal-FE-os/.editorconfig [new file with mode: 0644]
portal-FE-os/.gitignore [new file with mode: 0644]
portal-FE-os/README.md [new file with mode: 0644]
portal-FE-os/angular.json [new file with mode: 0644]
portal-FE-os/e2e/protractor.conf.js [new file with mode: 0644]
portal-FE-os/e2e/src/app.e2e-spec.ts [new file with mode: 0644]
portal-FE-os/e2e/src/app.po.ts [new file with mode: 0644]
portal-FE-os/e2e/tsconfig.e2e.json [new file with mode: 0644]
portal-FE-os/package-lock.json [new file with mode: 0644]
portal-FE-os/package.json [new file with mode: 0644]
portal-FE-os/pom.xml [new file with mode: 0644]
portal-FE-os/src/.gitignore [new file with mode: 0644]
portal-FE-os/src/app/.gitignore [new file with mode: 0644]
portal-FE-os/src/app/app-routing.module.ts [new file with mode: 0644]
portal-FE-os/src/app/app.component.html [new file with mode: 0644]
portal-FE-os/src/app/app.component.scss [new file with mode: 0644]
portal-FE-os/src/app/app.component.spec.ts [new file with mode: 0644]
portal-FE-os/src/app/app.component.ts [new file with mode: 0644]
portal-FE-os/src/app/app.module.ts [new file with mode: 0644]
portal-FE-os/src/app/layout/components/footer/footer.component.html [new file with mode: 0644]
portal-FE-os/src/app/layout/components/footer/footer.component.scss [new file with mode: 0644]
portal-FE-os/src/app/layout/components/footer/footer.component.spec.ts [new file with mode: 0644]
portal-FE-os/src/app/layout/components/footer/footer.component.ts [new file with mode: 0644]
portal-FE-os/src/app/layout/components/global-search/global-search.component.html [new file with mode: 0644]
portal-FE-os/src/app/layout/components/global-search/global-search.component.scss [new file with mode: 0644]
portal-FE-os/src/app/layout/components/global-search/global-search.component.spec.ts [new file with mode: 0644]
portal-FE-os/src/app/layout/components/global-search/global-search.component.ts [new file with mode: 0644]
portal-FE-os/src/app/layout/components/header-menu/header-menu.component.html [new file with mode: 0644]
portal-FE-os/src/app/layout/components/header-menu/header-menu.component.scss [new file with mode: 0644]
portal-FE-os/src/app/layout/components/header-menu/header-menu.component.spec.ts [new file with mode: 0644]
portal-FE-os/src/app/layout/components/header-menu/header-menu.component.ts [new file with mode: 0644]
portal-FE-os/src/app/layout/components/header/header.component.html [new file with mode: 0644]
portal-FE-os/src/app/layout/components/header/header.component.scss [new file with mode: 0644]
portal-FE-os/src/app/layout/components/header/header.component.spec.ts [new file with mode: 0644]
portal-FE-os/src/app/layout/components/header/header.component.ts [new file with mode: 0644]
portal-FE-os/src/app/layout/components/search-users/search-users.component.html [new file with mode: 0644]
portal-FE-os/src/app/layout/components/search-users/search-users.component.scss [new file with mode: 0644]
portal-FE-os/src/app/layout/components/search-users/search-users.component.spec.ts [new file with mode: 0644]
portal-FE-os/src/app/layout/components/search-users/search-users.component.ts [new file with mode: 0644]
portal-FE-os/src/app/layout/components/sidebar/sidebar.component.html [new file with mode: 0644]
portal-FE-os/src/app/layout/components/sidebar/sidebar.component.scss [new file with mode: 0644]
portal-FE-os/src/app/layout/components/sidebar/sidebar.component.spec.ts [new file with mode: 0644]
portal-FE-os/src/app/layout/components/sidebar/sidebar.component.ts [new file with mode: 0644]
portal-FE-os/src/app/layout/components/tabbar/tab.ts [new file with mode: 0644]
portal-FE-os/src/app/layout/components/tabbar/tabbar.component.html [new file with mode: 0644]
portal-FE-os/src/app/layout/components/tabbar/tabbar.component.scss [new file with mode: 0644]
portal-FE-os/src/app/layout/components/tabbar/tabbar.component.spec.ts [new file with mode: 0644]
portal-FE-os/src/app/layout/components/tabbar/tabbar.component.ts [new file with mode: 0644]
portal-FE-os/src/app/layout/components/userbar/userbar.component.html [new file with mode: 0644]
portal-FE-os/src/app/layout/components/userbar/userbar.component.scss [new file with mode: 0644]
portal-FE-os/src/app/layout/components/userbar/userbar.component.spec.ts [new file with mode: 0644]
portal-FE-os/src/app/layout/components/userbar/userbar.component.ts [new file with mode: 0644]
portal-FE-os/src/app/layout/layout-routing.module.ts [new file with mode: 0644]
portal-FE-os/src/app/layout/layout.component.html [new file with mode: 0644]
portal-FE-os/src/app/layout/layout.component.scss [new file with mode: 0644]
portal-FE-os/src/app/layout/layout.component.spec.ts [new file with mode: 0644]
portal-FE-os/src/app/layout/layout.component.ts [new file with mode: 0644]
portal-FE-os/src/app/layout/layout.module.ts [new file with mode: 0644]
portal-FE-os/src/assets/images/default_app_image.gif [new file with mode: 0644]
portal-FE-os/src/assets/images/global.logo [new file with mode: 0644]
portal-FE-os/src/assets/images/spinner.gif [new file with mode: 0644]
portal-FE-os/src/browserslist [new file with mode: 0644]
portal-FE-os/src/environments/environment.prod.ts [new file with mode: 0644]
portal-FE-os/src/environments/environment.ts [new file with mode: 0644]
portal-FE-os/src/favicon.ico [new file with mode: 0644]
portal-FE-os/src/index.html [new file with mode: 0644]
portal-FE-os/src/karma.conf.js [new file with mode: 0644]
portal-FE-os/src/main.ts [new file with mode: 0644]
portal-FE-os/src/polyfills.ts [new file with mode: 0644]
portal-FE-os/src/styles.scss [new file with mode: 0644]
portal-FE-os/src/test.ts [new file with mode: 0644]
portal-FE-os/src/tsconfig.app.json [new file with mode: 0644]
portal-FE-os/src/tsconfig.spec.json [new file with mode: 0644]
portal-FE-os/src/tslint.json [new file with mode: 0644]
portal-FE-os/tsconfig.json [new file with mode: 0644]
portal-FE-os/tslint.json [new file with mode: 0644]

index 5c18f3b..eb6bfe1 100644 (file)
@@ -14,4 +14,5 @@ kubernetes/.classpath
 kubernetes/.settings
 kubernetes/.classpath/*
 kubernetes/.settings/*
-ecomp-portal-FE-att/client/bower*
\ No newline at end of file
+ecomp-portal-FE-att/client/bower*
+/.metadata/
index 9ab7c1a..b1b0be0 100644 (file)
@@ -11,4 +11,5 @@ Building ONAP Portal BE Applications
        :caption: Contents:
 
        setting-up
+       request-flow
 
diff --git a/docs/tutorials/portal-BE/request-flow.rst b/docs/tutorials/portal-BE/request-flow.rst
new file mode 100644 (file)
index 0000000..a186b01
--- /dev/null
@@ -0,0 +1,4 @@
+Request flow in Portal-BE project
+=================================
+
+.. image:: requestflow.jpeg
diff --git a/docs/tutorials/portal-BE/requestflow.jpeg b/docs/tutorials/portal-BE/requestflow.jpeg
new file mode 100644 (file)
index 0000000..10c2e12
Binary files /dev/null and b/docs/tutorials/portal-BE/requestflow.jpeg differ
index f0f0af5..4d81c6d 100644 (file)
@@ -43,38 +43,36 @@ import org.glassfish.jersey.client.ClientResponse;
 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
 
 public class SchedulerAuxUtil {
-       
-       private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(SchedulerAuxUtil.class);
 
-       public static SchedulerAuxResponseWrapper wrapResponse ( String body, int statusCode ) {
-               
-               SchedulerAuxResponseWrapper w = new SchedulerAuxResponseWrapper();
-               w.setStatus (statusCode);
-               w.setEntity(body);
-               
-               return w;
-       }
-       
-       public static SchedulerAuxResponseWrapper wrapResponse (ClientResponse cres) {  
-               String resp_str = "";
-               if ( cres != null ) {
-                       resp_str = cres.readEntity(String.class);
-               }
-               int statuscode = cres.getStatus();
-               SchedulerAuxResponseWrapper w = SchedulerAuxUtil.wrapResponse ( resp_str, statuscode );
-               return (w);
-       }
-       
-       public static SchedulerAuxResponseWrapper wrapResponse (RestObject<String> rs) {        
-               String resp_str = "";
-               int status = 0;
-               if ( rs != null ) {
-                       resp_str = rs.get();
-                       status = rs.getStatusCode();
-               }
-               SchedulerAuxResponseWrapper w = SchedulerAuxUtil.wrapResponse ( resp_str, status );
-               return (w);
-       }
-       
-       
+    public static SchedulerAuxResponseWrapper wrapResponse(String body, int statusCode) {
+
+        SchedulerAuxResponseWrapper w = new SchedulerAuxResponseWrapper();
+        w.setStatus(statusCode);
+        w.setEntity(body);
+
+        return w;
+    }
+
+    public static SchedulerAuxResponseWrapper wrapResponse(ClientResponse cres) {
+        String respStr = "";
+        int statuscode = 0;
+        if (cres != null) {
+            respStr = cres.readEntity(String.class);
+            statuscode = cres.getStatus();
+        }
+        SchedulerAuxResponseWrapper w = SchedulerAuxUtil.wrapResponse(respStr, statuscode);
+        return (w);
+    }
+
+    public static SchedulerAuxResponseWrapper wrapResponse(RestObject<String> rs) {
+        String respStr = "";
+        int status = 0;
+        if (rs != null) {
+            respStr = rs.get();
+            status = rs.getStatusCode();
+        }
+        SchedulerAuxResponseWrapper w = SchedulerAuxUtil.wrapResponse(respStr, status);
+        return (w);
+    }
+
 }
index 92cbe90..5d38317 100644 (file)
@@ -43,7 +43,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeSet;
-
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.EnableAspectJAutoProxy;
 import org.springframework.stereotype.Service;
@@ -61,146 +60,155 @@ import org.onap.portalsdk.core.service.DataAccessService;
 @EnableAspectJAutoProxy
 @EPMetricsLog
 public class EPRoleServiceImpl implements EPRoleService {
-       EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(EPRoleServiceImpl.class);
-
-       @Autowired
-       private DataAccessService dataAccessService;
-       
-       @Autowired
-       ExternalAccessRolesService externalAccessRolesService;
-
-       @SuppressWarnings("unchecked")
-       public List<RoleFunction> getRoleFunctions() {
-               // List msgDB = getDataAccessService().getList(Profile.class, null);
-               return getDataAccessService().getList(RoleFunction.class, null);
-       }
-
-       @SuppressWarnings("unchecked")
-       public List<EPRole> getAvailableChildRoles(Long roleId) {
-               List<EPRole> availableChildRoles = (List<EPRole>) getDataAccessService().getList(EPRole.class, null);
-               if (roleId == null || roleId == 0) {
-                       return availableChildRoles;
-               }
-
-               EPRole currentRole = (EPRole) getDataAccessService().getDomainObject(EPRole.class, roleId, null);
-               Set<EPRole> allParentRoles = new TreeSet<EPRole>();
-               allParentRoles = getAllParentRolesAsList(currentRole, allParentRoles);
-
-               Iterator<EPRole> availableChildRolesIterator = availableChildRoles.iterator();
-               while (availableChildRolesIterator.hasNext()) {
-                       EPRole role = availableChildRolesIterator.next();
-                       if (!role.getActive() || allParentRoles.contains(role) || role.getId().equals(roleId)) {
-                               availableChildRolesIterator.remove();
-                       }
-               }
-               return availableChildRoles;
-       }
-
-       private Set<EPRole> getAllParentRolesAsList(EPRole role, Set<EPRole> allParentRoles) {
-               Set<EPRole> parentRoles = role.getParentRoles();
-               allParentRoles.addAll(parentRoles);
-               Iterator<EPRole> parentRolesIterator = parentRoles.iterator();
-               while (parentRolesIterator.hasNext()) {
-                       getAllParentRolesAsList(parentRolesIterator.next(), allParentRoles);
-               }
-               return allParentRoles;
-       }
-
-       public RoleFunction getRoleFunction(String code) {
-               return (RoleFunction) getDataAccessService().getDomainObject(RoleFunction.class, code, null);
-       }
-
-       public void saveRoleFunction(RoleFunction domainRoleFunction) {
-               getDataAccessService().saveDomainObject(domainRoleFunction, null);
-       }
-
-       public void deleteRoleFunction(RoleFunction domainRoleFunction) {
-               getDataAccessService().deleteDomainObject(domainRoleFunction, null);
-       }
-
-       public EPRole getRole(Long id) {
-               return (EPRole) getDataAccessService().getDomainObject(EPRole.class, id, null);
-       }
-
-       // TODO: refactor
-       private static final String getAppRoleSqlFormat = "SELECT * FROM fn_role where APP_ID = %s AND APP_ROLE_ID = %s";
-
-       @SuppressWarnings("unchecked")
-       public EPRole getRole(Long appId, Long appRoleid) {
-               if (appId == null || appRoleid == null) {
-                       logger.error(EELFLoggerDelegate.errorLogger, String.format(
-                                       "getRole does not support null appId or roleId. appRoleid=%s, appRoleid=%s", appId, appRoleid));
-                       return null;
-               }
-
-               String sql = String.format(getAppRoleSqlFormat, appId, appRoleid);
-
-               List<EPRole> roles = (List<EPRole>) dataAccessService.executeSQLQuery(sql, EPRole.class, null);
-               int resultsCount = roles.size();
-               if (resultsCount > 1) {
-                       logger.error(EELFLoggerDelegate.errorLogger,
-                                       String.format(
-                                                       "search by appId=%s, appRoleid=%s should have returned 0 or 1 results. Got %d. This is an internal server error.",
-                                                       appId, appRoleid, resultsCount));
-                       logger.error(EELFLoggerDelegate.errorLogger,
-                                       "Trying to recover from duplicates by returning the first search result. This issue should be treated, it is probably not critical because duplicate roles should be similar.");
-                       return roles.get(0);
-               } else if (resultsCount == 1) {
-                       return roles.get(0);
-               }
-               return null;
-       }
-
-       @SuppressWarnings("unchecked")
-       public EPRole getAppRole(String roleName, Long appId) {
-
-               final Map<String, String> params = new HashMap<String, String>();
-               final Map<String, String> portalParams = new HashMap<String, String>();
-               List<EPRole> roles = null;
-               params.put("appId", appId.toString());
-               params.put("roleName", roleName);
-               portalParams.put("appRoleName", roleName);
-               
-               List<EPRole> roleList = externalAccessRolesService.getPortalAppRoleInfo(PortalConstants.ACCOUNT_ADMIN_ROLE_ID);
-               EPRole role = new EPRole();
-               if(roleList.size()>0){
-                role = roleList.get(0);}
-                logger.debug(EELFLoggerDelegate.debugLogger, "Requested RoleName is  "+role.getName());
-                
-               if (appId == 1 || roleName.equals(role.getName())) {
-                       roles = (List<EPRole>) dataAccessService.executeNamedQuery("getPortalAppRoles", portalParams, null);
-               } else if (appId != 1 && !roleName.equals(role.getName())) {
-                       roles = (List<EPRole>) dataAccessService.executeNamedQuery("getAppRoles", params, null);
-               }
-               int resultsCount = (roles == null ? 0 : roles.size());
-               if (resultsCount > 1) {
-                       logger.error(EELFLoggerDelegate.errorLogger,
-                                       "Trying to recover from duplicates by returning the first search result. This issue should be treated, it is probably not critical because duplicate roles should be similar.");
-                       return roles.get(0);
-               } else if (resultsCount == 1) {
-                       return roles.get(0);
-               }
-               return null;
-       }
-
-       public void saveRole(EPRole domainRole) {
-               getDataAccessService().saveDomainObject(domainRole, null);
-       }
-
-       public void deleteRole(EPRole domainRole) {
-               getDataAccessService().deleteDomainObject(domainRole, null);
-       }
-
-       @SuppressWarnings("unchecked")
-       public List<EPRole> getAvailableRoles() {
-               return getDataAccessService().getList(EPRole.class, null);
-       }
-
-       public DataAccessService getDataAccessService() {
-               return dataAccessService;
-       }
-
-       public void setDataAccessService(DataAccessService dataAccessService) {
-               this.dataAccessService = dataAccessService;
-       }
+    EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(EPRoleServiceImpl.class);
+
+    @Autowired
+    private DataAccessService dataAccessService;
+
+    @Autowired
+    ExternalAccessRolesService externalAccessRolesService;
+
+    @SuppressWarnings("unchecked")
+    public List<RoleFunction> getRoleFunctions() {
+        return getDataAccessService().getList(RoleFunction.class, null);
+    }
+
+    @SuppressWarnings("unchecked")
+    public List<EPRole> getAvailableChildRoles(Long roleId) {
+        List<EPRole> availableChildRoles =
+                (List<EPRole>) getDataAccessService().getList(EPRole.class, null);
+        if (roleId == null || roleId == 0) {
+            return availableChildRoles;
+        }
+
+        EPRole currentRole =
+                (EPRole) getDataAccessService().getDomainObject(EPRole.class, roleId, null);
+        Set<EPRole> allParentRoles = new TreeSet<>();
+        allParentRoles = getAllParentRolesAsList(currentRole, allParentRoles);
+
+        Iterator<EPRole> availableChildRolesIterator = availableChildRoles.iterator();
+        while (availableChildRolesIterator.hasNext()) {
+            EPRole role = availableChildRolesIterator.next();
+            if (!role.getActive() || allParentRoles.contains(role) || role.getId().equals(roleId)) {
+                availableChildRolesIterator.remove();
+            }
+        }
+        return availableChildRoles;
+    }
+
+    private Set<EPRole> getAllParentRolesAsList(EPRole role, Set<EPRole> allParentRoles) {
+        Set<EPRole> parentRoles = role.getParentRoles();
+        allParentRoles.addAll(parentRoles);
+        Iterator<EPRole> parentRolesIterator = parentRoles.iterator();
+        while (parentRolesIterator.hasNext()) {
+            getAllParentRolesAsList(parentRolesIterator.next(), allParentRoles);
+        }
+        return allParentRoles;
+    }
+
+    public RoleFunction getRoleFunction(String code) {
+        return (RoleFunction) getDataAccessService().getDomainObject(RoleFunction.class, code,
+                null);
+    }
+
+    public void saveRoleFunction(RoleFunction domainRoleFunction) {
+        getDataAccessService().saveDomainObject(domainRoleFunction, null);
+    }
+
+    public void deleteRoleFunction(RoleFunction domainRoleFunction) {
+        getDataAccessService().deleteDomainObject(domainRoleFunction, null);
+    }
+
+    public EPRole getRole(Long id) {
+        return (EPRole) getDataAccessService().getDomainObject(EPRole.class, id, null);
+    }
+
+    // TODO: refactor
+    private static final String GET_APP_ROLE_SQL_FORMAT =
+            "SELECT * FROM fn_role where APP_ID = %s AND APP_ROLE_ID = %s";
+
+    @SuppressWarnings("unchecked")
+    public EPRole getRole(Long appId, Long appRoleid) {
+        if (appId == null || appRoleid == null) {
+            logger.error(EELFLoggerDelegate.errorLogger, String.format(
+                    "getRole does not support null appId or roleId. appRoleid=%s, appRoleid=%s",
+                    appId, appRoleid));
+            return null;
+        }
+
+        String sql = String.format(GET_APP_ROLE_SQL_FORMAT, appId, appRoleid);
+
+        List<EPRole> roles =
+                (List<EPRole>) dataAccessService.executeSQLQuery(sql, EPRole.class, null);
+        int resultsCount = roles.size();
+        if (resultsCount > 1) {
+            logger.error(EELFLoggerDelegate.errorLogger, String.format(
+                    "search by appId=%s, appRoleid=%s should have returned 0 or 1 results. Got %d. This is an internal server error.",
+                    appId, appRoleid, resultsCount));
+            logger.error(EELFLoggerDelegate.errorLogger,
+                    "Trying to recover from duplicates by returning the first search result. This issue should be treated, it is probably not critical because duplicate roles should be similar.");
+            return roles.get(0);
+        } else if (resultsCount == 1) {
+            return roles.get(0);
+        }
+        return null;
+    }
+
+    @SuppressWarnings("unchecked")
+    public EPRole getAppRole(String roleName, Long appId) {
+
+        final Map<String, String> params = new HashMap<>();
+        final Map<String, String> portalParams = new HashMap<>();
+        List<EPRole> roles = null;
+        params.put("appId", appId.toString());
+        params.put("roleName", roleName);
+        portalParams.put("appRoleName", roleName);
+
+        List<EPRole> roleList = externalAccessRolesService
+                .getPortalAppRoleInfo(PortalConstants.ACCOUNT_ADMIN_ROLE_ID);
+        EPRole role = new EPRole();
+        if (!roleList.isEmpty()) {
+            role = roleList.get(0);
+        }
+        logger.debug(EELFLoggerDelegate.debugLogger, "Requested RoleName is  " + role.getName());
+
+        if (appId == 1 || roleName.equals(role.getName())) {
+            roles = (List<EPRole>) dataAccessService.executeNamedQuery("getPortalAppRoles",
+                    portalParams, null);
+        } else if (appId != 1 && !roleName.equals(role.getName())) {
+            roles = (List<EPRole>) dataAccessService.executeNamedQuery("getAppRoles", params, null);
+        }
+        int resultsCount = (roles == null ? 0 : roles.size());
+        if (resultsCount > 1) {
+            logger.error(EELFLoggerDelegate.errorLogger,
+                    "Trying to recover from duplicates by returning the first search result. This issue should be treated, it is probably not critical because duplicate roles should be similar.");
+            if (roles != null) {
+                return roles.get(0);
+            }
+        } else if (resultsCount == 1) {
+            return roles.get(0);
+        }
+        return null;
+    }
+
+    public void saveRole(EPRole domainRole) {
+        getDataAccessService().saveDomainObject(domainRole, null);
+    }
+
+    public void deleteRole(EPRole domainRole) {
+        getDataAccessService().deleteDomainObject(domainRole, null);
+    }
+
+    @SuppressWarnings("unchecked")
+    public List<EPRole> getAvailableRoles() {
+        return getDataAccessService().getList(EPRole.class, null);
+    }
+
+    public DataAccessService getDataAccessService() {
+        return dataAccessService;
+    }
+
+    public void setDataAccessService(DataAccessService dataAccessService) {
+        this.dataAccessService = dataAccessService;
+    }
 }
diff --git a/ecomp-portal-BE-common/src/test/java/org/onap/portalapp/portal/exceptions/ExternalAuthSystemExceptionTest.java b/ecomp-portal-BE-common/src/test/java/org/onap/portalapp/portal/exceptions/ExternalAuthSystemExceptionTest.java
new file mode 100644 (file)
index 0000000..e36e81f
--- /dev/null
@@ -0,0 +1,60 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 IBM Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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============================================
+ *
+ * 
+ */
+
+package org.onap.portalapp.portal.exceptions;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+public class ExternalAuthSystemExceptionTest {
+
+        @Test
+           public void TestException2() {
+               String s1 = "Value1";
+               String s2 = "value2";
+               try {
+                   if (!s1.equalsIgnoreCase(s2)) {
+                       throw new ExternalAuthSystemException("Exception occured..");
+                   }
+               } catch (ExternalAuthSystemException mde) {
+                   assertEquals(mde.getMessage(),"Exception occured..");
+               }
+
+           }
+}
diff --git a/ecomp-portal-BE-common/src/test/java/org/onap/portalapp/portal/exceptions/InactiveApplicationExceptionTest.java b/ecomp-portal-BE-common/src/test/java/org/onap/portalapp/portal/exceptions/InactiveApplicationExceptionTest.java
new file mode 100644 (file)
index 0000000..582a9db
--- /dev/null
@@ -0,0 +1,59 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 IBM Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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============================================
+ *
+ * 
+ */
+package org.onap.portalapp.portal.exceptions;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+public class InactiveApplicationExceptionTest {
+
+       @Test
+    public void TestException2() {
+        String s1 = "Value1";
+        String s2 = "value2";
+        try {
+            if (!s1.equalsIgnoreCase(s2)) {
+                throw new InactiveApplicationException("Exception occured..");
+            }
+        } catch (InactiveApplicationException mde) {
+            assertEquals(mde.getMessage(),"Exception occured..");
+        }
+
+    }
+}
diff --git a/ecomp-portal-BE-common/src/test/java/org/onap/portalapp/portal/exceptions/InvalidUserExceptionTest.java b/ecomp-portal-BE-common/src/test/java/org/onap/portalapp/portal/exceptions/InvalidUserExceptionTest.java
new file mode 100644 (file)
index 0000000..152093e
--- /dev/null
@@ -0,0 +1,59 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 IBM Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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============================================
+ *
+ * 
+ */
+package org.onap.portalapp.portal.exceptions;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+public class InvalidUserExceptionTest {
+
+       @Test
+    public void TestException2() {
+        String s1 = "Value1";
+        String s2 = "value2";
+        try {
+            if (!s1.equalsIgnoreCase(s2)) {
+                throw new InvalidUserException("Exception occured..");
+            }
+        } catch (InvalidUserException mde) {
+            assertEquals(mde.getMessage(),"Exception occured..");
+        }
+
+    }
+}
diff --git a/ecomp-portal-BE-common/src/test/java/org/onap/portalapp/portal/exceptions/SyncUserRolesExceptionTest.java b/ecomp-portal-BE-common/src/test/java/org/onap/portalapp/portal/exceptions/SyncUserRolesExceptionTest.java
new file mode 100644 (file)
index 0000000..84708cb
--- /dev/null
@@ -0,0 +1,61 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 IBM Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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============================================
+ *
+ * 
+ */
+package org.onap.portalapp.portal.exceptions;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+public class SyncUserRolesExceptionTest {
+
+        @Test
+           public void TestException2() {
+               String s1 = "Value1";
+               String s2 = "value2";
+               try {
+                   if (!s1.equalsIgnoreCase(s2)) {
+                       throw new SyncUserRolesException("Exception occured..");
+                   }
+               } catch (SyncUserRolesException mde) {
+                   assertEquals(mde.getMessage(),"Exception occured..");
+               }
+
+           }
+       
+       
+}
diff --git a/ecomp-portal-widget-ms/widget-ms/src/test/java/org/onap/portalapp/widget/exception/StorageFileNotFoundExceptionTest.java b/ecomp-portal-widget-ms/widget-ms/src/test/java/org/onap/portalapp/widget/exception/StorageFileNotFoundExceptionTest.java
new file mode 100644 (file)
index 0000000..d49d87d
--- /dev/null
@@ -0,0 +1,39 @@
+package org.onap.portalapp.widget.exception;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.onap.portalapp.widget.excetpion.StorageFileNotFoundException;
+
+public class StorageFileNotFoundExceptionTest {
+
+       @Test
+       public void Test1()
+       {
+                String s1 = "Value1";
+               String s2 = "value2";
+               try {
+                   if (!s1.equalsIgnoreCase(s2)) {
+                       throw new StorageFileNotFoundException("org.onap.portalapp.widget.excetpion.StorageFileNotFoundException");
+                   }
+               } catch (StorageFileNotFoundException mde) {
+                   assertEquals(mde.getMessage(),"org.onap.portalapp.widget.excetpion.StorageFileNotFoundException");
+               }
+       }
+       
+       @Test
+       public void Test2()
+       {
+                String message = "Exception occured";
+                String s1 = "Value1";
+            String s2 = "value2";
+               try {
+                   if (!s1.equalsIgnoreCase(s2)) {
+                       throw new StorageFileNotFoundException(message, new Throwable());
+                   }
+               } catch (StorageFileNotFoundException mde) {
+                   assertEquals("org.onap.portalapp.widget.excetpion.StorageFileNotFoundException", mde.getClass().getName());
+               }
+       }
+       
+}
index a882f75..9434097 100644 (file)
                   <scope>compile</scope>
             </dependency>
             <dependency>
-                  <groupId>io.swagger</groupId>
-                  <artifactId>swagger-annotations</artifactId>
-                  <version>2.0.0-rc2</version>
-                  <scope>compile</scope>
-            </dependency>
-            <dependency>
-                  <groupId>io.swagger</groupId>
-                  <artifactId>swagger-annotations</artifactId>
-                  <version>2.0.0-rc2</version>
-                  <scope>compile</scope>
-            </dependency>
-            <dependency>
-                  <groupId>io.swagger</groupId>
-                  <artifactId>swagger-annotations</artifactId>
-                  <version>1.5.20</version>
-            </dependency>
-            <dependency>
-                  <groupId>io.swagger</groupId>
-                  <artifactId>swagger-annotations</artifactId>
-                  <version>2.0.0-rc2</version>
-                  <scope>compile</scope>
-            </dependency>
-            <dependency>
-                  <groupId>io.swagger</groupId>
-                  <artifactId>swagger-annotations</artifactId>
-                  <version>1.5.20</version>
-            </dependency>
-            <dependency>
-                  <groupId>io.swagger</groupId>
-                  <artifactId>swagger-annotations</artifactId>
-                  <version>2.0.0-rc2</version>
-                  <scope>compile</scope>
-            </dependency>
-            <dependency>
-                  <groupId>io.swagger</groupId>
-                  <artifactId>swagger-annotations</artifactId>
-                  <version>2.0.0-rc2</version>
+                  <groupId>org.apache.cxf</groupId>
+                  <artifactId>cxf-rt-rs-client</artifactId>
+                  <version>3.3.4</version>
                   <scope>compile</scope>
             </dependency>
+          <dependency>
+              <groupId>org.hibernate.validator</groupId>
+              <artifactId>hibernate-validator</artifactId>
+              <version>6.0.18.Final</version>
+              <scope>compile</scope>
+          </dependency>
             <dependency>
                   <groupId>io.swagger</groupId>
                   <artifactId>swagger-annotations</artifactId>
-                  <version>1.5.20</version>
-            </dependency>
-            <dependency>
-                  <groupId>org.apache.cxf</groupId>
-                  <artifactId>cxf-rt-rs-client</artifactId>
-                  <version>3.3.4</version>
+                  <version>1.5.13</version>
                   <scope>compile</scope>
             </dependency>
       </dependencies>
index cf6f9d7..047880a 100644 (file)
@@ -48,7 +48,7 @@ import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
 
 @SpringBootApplication
 @EntityScan("org.onap.portal.domain")
-@EnableJpaRepositories("org.onap.portal.dao")
+@EnableJpaRepositories("org.onap.portal.service")
 public class PortalApplication {
 
        public static void main(String[] args) {
index 4b48ae4..b62e7f7 100644 (file)
@@ -60,7 +60,7 @@ public class FnLanguageServiceAOP {
        @Autowired
        private DataValidator dataValidator;
 
-       @Before("execution(* org.onap.portal.service.fn.FnLanguageService.save(..)) && args(fnLanguage)")
+       @Before("execution(* org.onap.portal.service.language.FnLanguageService.save(..)) && args(fnLanguage)")
        public void save(final FnLanguage fnLanguage) {
               if (fnLanguage == null) {
                      LOGGER.info("User " +  " try to save NULL fnLanguage");
@@ -75,7 +75,7 @@ public class FnLanguageServiceAOP {
               }
        }
 
-       @Before("execution(* org.onap.portal.service.fn.FnLanguageService.getLanguageList(..)) && args(principal)")
+       @Before("execution(* org.onap.portal.service.language.FnLanguageService.getLanguageList(..)) && args(principal)")
        public void getLanguageList(final Principal principal) {
               LOGGER.info("User " + principal.getName() + " try requested for all language list");
        }
index f891392..5cbec71 100644 (file)
@@ -68,7 +68,7 @@ public class FnUserServiceAOP {
               this.fnUserMapper = fnUserMapper;
        }
 
-       @Before("execution(* org.onap.portal.service.fn.FnUserService.saveFnUser(..)) && args(principal, fnUser)")
+       @Before("execution(* org.onap.portal.service.user.FnUserService.saveFnUser(..)) && args(principal, fnUser)")
        public void save(final Principal principal, final FnUser fnUser) {
               FnUser user;
               if (fnUser == null) {
index 1417293..c1357e2 100644 (file)
@@ -23,7 +23,7 @@ public class WidgetServiceAOP {
               this.dataValidator = dataValidator;
        }
 
-       @Before("execution(* org.onap.portal.service.WidgetService.setOnboardingWidget(..)) && args(userId, onboardingWidget)")
+       @Before("execution(* org.onap.portal.service.widget.WidgetService.setOnboardingWidget(..)) && args(userId, onboardingWidget)")
        public void setOnboardingWidget(final Long userId, OnboardingWidget onboardingWidget) {
               if (!dataValidator.isValid(onboardingWidget)) {
                      throw new IllegalArgumentException(dataValidator.getConstraintViolationsString(onboardingWidget));
index ebd23cd..3f5b388 100644 (file)
 
 package org.onap.portal.configuration;
 
+import org.onap.portal.domain.db.ep.*;
+import org.onap.portal.domain.db.fn.*;
+import org.onap.portal.service.app.FnAppService;
+import org.onap.portal.service.appContactUs.FnAppContactUsService;
+import org.onap.portal.service.appFunction.EpAppFunctionService;
+import org.onap.portal.service.appRoleFunction.EpAppRoleFunctionService;
+import org.onap.portal.service.auditLog.FnAuditLogService;
+import org.onap.portal.service.basicAuthAccount.EpBasicAuthAccountService;
+import org.onap.portal.service.commonWidgetData.FnCommonWidgetDataService;
+import org.onap.portal.service.displayText.FnDisplayTextService;
+import org.onap.portal.service.function.FnFunctionService;
+import org.onap.portal.service.language.FnLanguageService;
+import org.onap.portal.service.luActivity.FnLuActivityService;
+import org.onap.portal.service.luAlertMethod.FnLuAlertMethodService;
+import org.onap.portal.service.luMenuSet.FnLuMenuSetService;
+import org.onap.portal.service.luPriority.FnLuPriorityService;
+import org.onap.portal.service.luTabSet.FnLuTabSetService;
+import org.onap.portal.service.luTimezone.FnLuTimezoneService;
+import org.onap.portal.service.menu.FnMenuService;
+import org.onap.portal.service.menuFunctional.FnMenuFunctionalService;
+import org.onap.portal.service.menuFunctionalAncestors.FnMenuFunctionalAncestorsService;
+import org.onap.portal.service.menuFunctionalRoles.FnMenuFunctionalRolesService;
+import org.onap.portal.service.microservice.EpMicroserviceService;
+import org.onap.portal.service.microserviceParameter.EpMicroserviceParameterService;
+import org.onap.portal.service.persUserAppSel.FnPersUserAppSelService;
+import org.onap.portal.service.persUserAppSort.EpPersUserAppSortService;
+import org.onap.portal.service.qzCronTriggers.FnQzCronTriggersService;
+import org.onap.portal.service.qzJobDetails.FnQzJobDetailsService;
+import org.onap.portal.service.qzLocks.FnQzLocksService;
+import org.onap.portal.service.qzSchedulerState.FnQzSchedulerStateService;
+import org.onap.portal.service.qzTriggers.FnQzTriggersService;
+import org.onap.portal.service.restrictedUrl.FnRestrictedUrlService;
+import org.onap.portal.service.role.FnRoleService;
+import org.onap.portal.service.roleComposite.FnRoleCompositeService;
+import org.onap.portal.service.roleFunction.FnRoleFunctionService;
+import org.onap.portal.service.sharedContext.FnSharedContextService;
+import org.onap.portal.service.tab.FnTabService;
+import org.onap.portal.service.tabSelected.FnTabSelectedService;
+import org.onap.portal.service.user.FnUserService;
+import org.onap.portal.service.userRole.FnUserRoleService;
+import org.onap.portal.service.widgetCatalog.EpWidgetCatalogService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.stereotype.Component;
+
 import java.math.BigInteger;
 import java.time.LocalDateTime;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
-import org.onap.portal.dao.ep.EpAppFunctionDao;
-import org.onap.portal.dao.ep.EpAppRoleFunctionDao;
-import org.onap.portal.dao.ep.EpBasicAuthAccountDao;
-import org.onap.portal.dao.ep.EpMicroserviceDao;
-import org.onap.portal.dao.ep.EpMicroserviceParameterDao;
-import org.onap.portal.dao.ep.EpPersUserAppSortDao;
-import org.onap.portal.dao.fn.EpWidgetCatalogDao;
-import org.onap.portal.dao.fn.FnAppContactUsDao;
-import org.onap.portal.dao.fn.FnAppDao;
-import org.onap.portal.dao.fn.FnAuditLogDao;
-import org.onap.portal.dao.fn.FnCommonWidgetDataDao;
-import org.onap.portal.dao.fn.FnDisplayTextDao;
-import org.onap.portal.dao.fn.FnFunctionDao;
-import org.onap.portal.dao.fn.FnLanguageDao;
-import org.onap.portal.dao.fn.FnLuActivityDao;
-import org.onap.portal.dao.fn.FnLuAlertMethodDao;
-import org.onap.portal.dao.fn.FnLuMenuSetDao;
-import org.onap.portal.dao.fn.FnLuPriorityDao;
-import org.onap.portal.dao.fn.FnLuTabSetDao;
-import org.onap.portal.dao.fn.FnLuTimezoneDao;
-import org.onap.portal.dao.fn.FnMenuDao;
-import org.onap.portal.dao.fn.FnMenuFunctionalAncestorsDao;
-import org.onap.portal.dao.fn.FnMenuFunctionalDao;
-import org.onap.portal.dao.fn.FnMenuFunctionalRolesDao;
-import org.onap.portal.dao.fn.FnPersUserAppSelDao;
-import org.onap.portal.dao.fn.FnQzCronTriggersDao;
-import org.onap.portal.dao.fn.FnQzJobDetailsDao;
-import org.onap.portal.dao.fn.FnQzLocksDao;
-import org.onap.portal.dao.fn.FnQzSchedulerStateDao;
-import org.onap.portal.dao.fn.FnQzTriggersDao;
-import org.onap.portal.dao.fn.FnRestrictedUrlDao;
-import org.onap.portal.dao.fn.FnRoleCompositeDao;
-import org.onap.portal.dao.fn.FnRoleDao;
-import org.onap.portal.dao.fn.FnRoleFunctionDao;
-import org.onap.portal.dao.fn.FnSharedContextDao;
-import org.onap.portal.dao.fn.FnTabDao;
-import org.onap.portal.dao.fn.FnTabSelectedDao;
-import org.onap.portal.dao.fn.FnUserDao;
-import org.onap.portal.dao.fn.FnUserRoleDao;
-import org.onap.portal.domain.db.ep.EpAppFunction;
-import org.onap.portal.domain.db.ep.EpAppRoleFunction;
-import org.onap.portal.domain.db.ep.EpBasicAuthAccount;
-import org.onap.portal.domain.db.ep.EpMicroservice;
-import org.onap.portal.domain.db.ep.EpMicroserviceParameter;
-import org.onap.portal.domain.db.ep.EpPersUserAppSort;
-import org.onap.portal.domain.db.ep.EpWidgetCatalog;
-import org.onap.portal.domain.db.fn.FnApp;
-import org.onap.portal.domain.db.fn.FnAppContactUs;
-import org.onap.portal.domain.db.fn.FnAuditLog;
-import org.onap.portal.domain.db.fn.FnCommonWidgetData;
-import org.onap.portal.domain.db.fn.FnDisplayText;
-import org.onap.portal.domain.db.fn.FnFunction;
-import org.onap.portal.domain.db.fn.FnLanguage;
-import org.onap.portal.domain.db.fn.FnLuActivity;
-import org.onap.portal.domain.db.fn.FnLuAlertMethod;
-import org.onap.portal.domain.db.fn.FnLuMenuSet;
-import org.onap.portal.domain.db.fn.FnLuPriority;
-import org.onap.portal.domain.db.fn.FnLuTabSet;
-import org.onap.portal.domain.db.fn.FnLuTimezone;
-import org.onap.portal.domain.db.fn.FnMenu;
-import org.onap.portal.domain.db.fn.FnMenuFunctional;
-import org.onap.portal.domain.db.fn.FnMenuFunctionalAncestors;
-import org.onap.portal.domain.db.fn.FnMenuFunctionalRoles;
-import org.onap.portal.domain.db.fn.FnPersUserAppSel;
-import org.onap.portal.domain.db.fn.FnQzCronTriggers;
-import org.onap.portal.domain.db.fn.FnQzJobDetails;
-import org.onap.portal.domain.db.fn.FnQzLocks;
-import org.onap.portal.domain.db.fn.FnQzSchedulerState;
-import org.onap.portal.domain.db.fn.FnQzTriggers;
-import org.onap.portal.domain.db.fn.FnRestrictedUrl;
-import org.onap.portal.domain.db.fn.FnRole;
-import org.onap.portal.domain.db.fn.FnRoleComposite;
-import org.onap.portal.domain.db.fn.FnRoleFunction;
-import org.onap.portal.domain.db.fn.FnSharedContext;
-import org.onap.portal.domain.db.fn.FnTab;
-import org.onap.portal.domain.db.fn.FnTabSelected;
-import org.onap.portal.domain.db.fn.FnUser;
-import org.onap.portal.domain.db.fn.FnUserRole;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
 
 @Component
 public class DBInitializingBean implements org.springframework.beans.factory.InitializingBean {
 
-  private final FnAppDao fnAppDao;
-  private final EpAppFunctionDao epAppFunctionDao;
-  private final FnRoleDao fnRoleDao;
-  private final EpAppRoleFunctionDao epAppRoleFunctionDao;
-  private final EpBasicAuthAccountDao epBasicAuthAccountDao;
-  private final EpMicroserviceDao epMicroserviceDao;
-  private final EpMicroserviceParameterDao epMicroserviceParameterDao;
-  private final EpWidgetCatalogDao epWidgetCatalogDao;
-  private final FnAppContactUsDao fnAppContactUsDao;
-  private final FnCommonWidgetDataDao fnCommonWidgetDataDao;
-  private final FnLanguageDao fnLanguageDao;
-  private final FnDisplayTextDao fnDisplayTextDao;
-  private final FnFunctionDao fnFunctionDao;
-  private final FnLuActivityDao fnLuActivityDao;
-  private final FnLuAlertMethodDao fnLuAlertMethodDao;
-  private final FnLuMenuSetDao fnLuMenuSetDao;
-  private final FnLuPriorityDao fnLuPriorityDao;
-  private final FnLuTimezoneDao fnLuTimezoneDao;
-  private final FnMenuDao fnMenuDao;
-  private final FnMenuFunctionalDao fnMenuFunctionalDao;
-  private final FnMenuFunctionalAncestorsDao fnMenuFunctionalAncestorsDao;
-  private final FnMenuFunctionalRolesDao fnMenuFunctionalRolesDao;
-  private final FnQzJobDetailsDao fnQzJobDetailsDao;
-  private final FnQzLocksDao fnQzLocksDao;
-  private final FnQzSchedulerStateDao fnQzSchedulerStateDao;
-  private final FnQzTriggersDao fnQzTriggersDao;
-  private final FnQzCronTriggersDao fnQzCronTriggersDao;
-  private final FnRestrictedUrlDao fnRestrictedUrlDao;
-  private final FnRoleCompositeDao fnRoleCompositeDao;
-  private final FnRoleFunctionDao fnRoleFunctionDao;
-  private final FnSharedContextDao fnSharedContextDao;
-  private final FnLuTabSetDao fnLuTabSetDao;
-  private final FnTabDao fnTabDao;
-  private final FnTabSelectedDao fnTabSelectedDao;
-  private final FnUserDao fnUserDao;
-  private final EpPersUserAppSortDao epPersUserAppSortDao;
-  private final FnPersUserAppSelDao fnPersUserAppSelDao;
-  private final FnAuditLogDao fnAuditLogDao;
-  private final FnUserRoleDao fnUserRoleDao;
+  private final FnAppService fnAppService;
+  private final EpAppFunctionService epAppFunctionService;
+  private final FnRoleService fnRoleService;
+  private final EpAppRoleFunctionService epAppRoleFunctionService;
+  private final EpBasicAuthAccountService epBasicAuthAccountService;
+  private final EpMicroserviceService epMicroserviceService;
+  private final EpMicroserviceParameterService epMicroserviceParameterService;
+  private final EpWidgetCatalogService epWidgetCatalogService;
+  private final FnAppContactUsService fnAppContactUsService;
+  private final FnCommonWidgetDataService fnCommonWidgetDataService;
+  private final FnLanguageService fnLanguageService;
+  private final FnDisplayTextService fnDisplayTextService;
+  private final FnFunctionService fnFunctionService;
+  private final FnLuActivityService fnLuActivityService;
+  private final FnLuAlertMethodService fnLuAlertMethodService;
+  private final FnLuMenuSetService fnLuMenuSetService;
+  private final FnLuPriorityService fnLuPriorityService;
+  private final FnLuTimezoneService fnLuTimezoneService;
+  private final FnMenuService fnMenuService;
+  private final FnMenuFunctionalService fnMenuFunctionalService;
+  private final FnMenuFunctionalAncestorsService fnMenuFunctionalAncestorsService;
+  private final FnMenuFunctionalRolesService fnMenuFunctionalRolesService;
+  private final FnQzJobDetailsService fnQzJobDetailsService;
+  private final FnQzLocksService fnQzLocksService;
+  private final FnQzSchedulerStateService fnQzSchedulerStateService;
+  private final FnQzTriggersService fnQzTriggersService;
+  private final FnQzCronTriggersService fnQzCronTriggersService;
+  private final FnRestrictedUrlService fnRestrictedUrlService;
+  private final FnRoleCompositeService fnRoleCompositeService;
+  private final FnRoleFunctionService fnRoleFunctionService;
+  private final FnSharedContextService fnSharedContextService;
+  private final FnLuTabSetService fnLuTabSetService;
+  private final FnTabService fnTabService;
+  private final FnTabSelectedService fnTabSelectedService;
+  private final FnUserService fnUserService;
+  private final EpPersUserAppSortService epPersUserAppSortService;
+  private final FnPersUserAppSelService fnPersUserAppSelService;
+  private final FnAuditLogService fnAuditLogService;
+  private final FnUserRoleService fnUserRoleService;
 
   @Autowired
-  public DBInitializingBean(FnAppDao fnAppDao, EpAppFunctionDao epAppFunctionDao,
-      FnRoleDao fnRoleDao, EpAppRoleFunctionDao epAppRoleFunctionDao,
-      EpBasicAuthAccountDao epBasicAuthAccountDao, EpMicroserviceDao epMicroserviceDao,
-      EpMicroserviceParameterDao epMicroserviceParameterDao,
-      EpWidgetCatalogDao epWidgetCatalogDao, FnAppContactUsDao fnAppContactUsDao,
-      FnCommonWidgetDataDao fnCommonWidgetDataDao, FnLanguageDao fnLanguageDao,
-      FnDisplayTextDao fnDisplayTextDao, FnFunctionDao fnFunctionDao,
-      FnLuActivityDao fnLuActivityDao, FnLuAlertMethodDao fnLuAlertMethodDao,
-      FnLuMenuSetDao fnLuMenuSetDao, FnLuPriorityDao fnLuPriorityDao,
-      FnLuTimezoneDao fnLuTimezoneDao, FnMenuDao fnMenuDao,
-      FnMenuFunctionalDao fnMenuFunctionalDao,
-      FnMenuFunctionalAncestorsDao fnMenuFunctionalAncestorsDao,
-      FnMenuFunctionalRolesDao fnMenuFunctionalRolesDao, FnQzJobDetailsDao fnQzJobDetailsDao,
-      FnQzLocksDao fnQzLocksDao, FnQzSchedulerStateDao fnQzSchedulerStateDao,
-      FnQzTriggersDao fnQzTriggersDao, FnQzCronTriggersDao fnQzCronTriggersDao,
-      FnRestrictedUrlDao fnRestrictedUrlDao, FnRoleCompositeDao fnRoleCompositeDao,
-      FnRoleFunctionDao fnRoleFunctionDao, FnSharedContextDao fnSharedContextDao,
-      FnLuTabSetDao fnLuTabSetDao, FnTabDao fnTabDao, FnTabSelectedDao fnTabSelectedDao,
-      FnUserDao fnUserDao, EpPersUserAppSortDao epPersUserAppSortDao,
-      FnPersUserAppSelDao fnPersUserAppSelDao, FnAuditLogDao fnAuditLogDao,
-      FnUserRoleDao fnUserRoleDao) {
-    this.fnAppDao = fnAppDao;
-    this.epAppFunctionDao = epAppFunctionDao;
-    this.fnRoleDao = fnRoleDao;
-    this.epAppRoleFunctionDao = epAppRoleFunctionDao;
-    this.epBasicAuthAccountDao = epBasicAuthAccountDao;
-    this.epMicroserviceDao = epMicroserviceDao;
-    this.epMicroserviceParameterDao = epMicroserviceParameterDao;
-    this.epWidgetCatalogDao = epWidgetCatalogDao;
-    this.fnAppContactUsDao = fnAppContactUsDao;
-    this.fnCommonWidgetDataDao = fnCommonWidgetDataDao;
-    this.fnLanguageDao = fnLanguageDao;
-    this.fnDisplayTextDao = fnDisplayTextDao;
-    this.fnFunctionDao = fnFunctionDao;
-    this.fnLuActivityDao = fnLuActivityDao;
-    this.fnLuAlertMethodDao = fnLuAlertMethodDao;
-    this.fnLuMenuSetDao = fnLuMenuSetDao;
-    this.fnLuPriorityDao = fnLuPriorityDao;
-    this.fnLuTimezoneDao = fnLuTimezoneDao;
-    this.fnMenuDao = fnMenuDao;
-    this.fnMenuFunctionalDao = fnMenuFunctionalDao;
-    this.fnMenuFunctionalAncestorsDao = fnMenuFunctionalAncestorsDao;
-    this.fnMenuFunctionalRolesDao = fnMenuFunctionalRolesDao;
-    this.fnQzJobDetailsDao = fnQzJobDetailsDao;
-    this.fnQzLocksDao = fnQzLocksDao;
-    this.fnQzSchedulerStateDao = fnQzSchedulerStateDao;
-    this.fnQzTriggersDao = fnQzTriggersDao;
-    this.fnQzCronTriggersDao = fnQzCronTriggersDao;
-    this.fnRestrictedUrlDao = fnRestrictedUrlDao;
-    this.fnRoleCompositeDao = fnRoleCompositeDao;
-    this.fnRoleFunctionDao = fnRoleFunctionDao;
-    this.fnSharedContextDao = fnSharedContextDao;
-    this.fnLuTabSetDao = fnLuTabSetDao;
-    this.fnTabDao = fnTabDao;
-    this.fnTabSelectedDao = fnTabSelectedDao;
-    this.fnUserDao = fnUserDao;
-    this.epPersUserAppSortDao = epPersUserAppSortDao;
-    this.fnPersUserAppSelDao = fnPersUserAppSelDao;
-    this.fnAuditLogDao = fnAuditLogDao;
-    this.fnUserRoleDao = fnUserRoleDao;
+  public DBInitializingBean(FnAppService fnAppService, EpAppFunctionService epAppFunctionService, FnRoleService fnRoleService, EpAppRoleFunctionService epAppRoleFunctionService, EpBasicAuthAccountService epBasicAuthAccountService, EpMicroserviceService epMicroserviceService, EpMicroserviceParameterService epMicroserviceParameterService, EpWidgetCatalogService epWidgetCatalogService, FnAppContactUsService fnAppContactUsService, FnCommonWidgetDataService fnCommonWidgetDataService, FnLanguageService fnLanguageService, FnDisplayTextService fnDisplayTextService, FnFunctionService fnFunctionService, FnLuActivityService fnLuActivityService, FnLuAlertMethodService fnLuAlertMethodService, FnLuMenuSetService fnLuMenuSetService, FnLuPriorityService fnLuPriorityService, FnLuTimezoneService fnLuTimezoneService, FnMenuService fnMenuService, FnMenuFunctionalService fnMenuFunctionalService, FnMenuFunctionalAncestorsService fnMenuFunctionalAncestorsService, FnMenuFunctionalRolesService fnMenuFunctionalRolesService, FnQzJobDetailsService fnQzJobDetailsService, FnQzLocksService fnQzLocksService, FnQzSchedulerStateService fnQzSchedulerStateService, FnQzTriggersService fnQzTriggersService, FnQzCronTriggersService fnQzCronTriggersService, FnRestrictedUrlService fnRestrictedUrlService, FnRoleCompositeService fnRoleCompositeService, FnRoleFunctionService fnRoleFunctionService, FnSharedContextService fnSharedContextService, FnLuTabSetService fnLuTabSetService, FnTabService fnTabService, FnTabSelectedService fnTabSelectedService, FnUserService fnUserService, EpPersUserAppSortService epPersUserAppSortService, FnPersUserAppSelService fnPersUserAppSelService, FnAuditLogService fnAuditLogService, FnUserRoleService fnUserRoleService) {
+    this.fnAppService = fnAppService;
+    this.epAppFunctionService = epAppFunctionService;
+    this.fnRoleService = fnRoleService;
+    this.epAppRoleFunctionService = epAppRoleFunctionService;
+    this.epBasicAuthAccountService = epBasicAuthAccountService;
+    this.epMicroserviceService = epMicroserviceService;
+    this.epMicroserviceParameterService = epMicroserviceParameterService;
+    this.epWidgetCatalogService = epWidgetCatalogService;
+    this.fnAppContactUsService = fnAppContactUsService;
+    this.fnCommonWidgetDataService = fnCommonWidgetDataService;
+    this.fnLanguageService = fnLanguageService;
+    this.fnDisplayTextService = fnDisplayTextService;
+    this.fnFunctionService = fnFunctionService;
+    this.fnLuActivityService = fnLuActivityService;
+    this.fnLuAlertMethodService = fnLuAlertMethodService;
+    this.fnLuMenuSetService = fnLuMenuSetService;
+    this.fnLuPriorityService = fnLuPriorityService;
+    this.fnLuTimezoneService = fnLuTimezoneService;
+    this.fnMenuService = fnMenuService;
+    this.fnMenuFunctionalService = fnMenuFunctionalService;
+    this.fnMenuFunctionalAncestorsService = fnMenuFunctionalAncestorsService;
+    this.fnMenuFunctionalRolesService = fnMenuFunctionalRolesService;
+    this.fnQzJobDetailsService = fnQzJobDetailsService;
+    this.fnQzLocksService = fnQzLocksService;
+    this.fnQzSchedulerStateService = fnQzSchedulerStateService;
+    this.fnQzTriggersService = fnQzTriggersService;
+    this.fnQzCronTriggersService = fnQzCronTriggersService;
+    this.fnRestrictedUrlService = fnRestrictedUrlService;
+    this.fnRoleCompositeService = fnRoleCompositeService;
+    this.fnRoleFunctionService = fnRoleFunctionService;
+    this.fnSharedContextService = fnSharedContextService;
+    this.fnLuTabSetService = fnLuTabSetService;
+    this.fnTabService = fnTabService;
+    this.fnTabSelectedService = fnTabSelectedService;
+    this.fnUserService = fnUserService;
+    this.epPersUserAppSortService = epPersUserAppSortService;
+    this.fnPersUserAppSelService = fnPersUserAppSelService;
+    this.fnAuditLogService = fnAuditLogService;
+    this.fnUserRoleService = fnUserRoleService;
   }
 
   @Override
@@ -472,7 +418,7 @@ public class DBInitializingBean implements org.springframework.beans.factory.Ini
         .authNamespace(null)
         .build();
     List<FnApp> fnApps = new ArrayList<>(Arrays.asList(app, app2, app3, app4, app5, app6, app7, app8, app9, app10));
-    fnAppDao.saveAll(fnApps);
+    fnAppService.saveAll(fnApps);
 
     // EP_APP_FUNCTION TABLE
 
@@ -535,7 +481,7 @@ public class DBInitializingBean implements org.springframework.beans.factory.Ini
             function10, function11, function12, function13, function14, function15, function16, function17, function18,
             function19, function20, function21, function22, function23, function24, function25, function26,
             function27));
-    epAppFunctionDao.saveAll(epAppFunctions);
+    epAppFunctionService.saveAll(epAppFunctions);
 
     // FN_ROLE TABLE
 
@@ -565,7 +511,7 @@ public class DBInitializingBean implements org.springframework.beans.factory.Ini
     List<FnRole> fnRoles = new ArrayList<>(Arrays
         .asList(fnRole1, fnRole16, fnRole900, fnRole950, fnRole999, fnRole1000, fnRole1001, fnRole1002, fnRole1003, fnRole1004, fnRole1005,
             fnRole1006, fnRole1007, fnRole1008, fnRole1009, fnRole1010, fnRole1011, fnRole1012, fnRole2115));
-    fnRoleDao.saveAll(fnRoles);
+    fnRoleService.saveAll(fnRoles);
 
     // EP_APP_ROLE_FUNCTION TABLE
 
@@ -634,10 +580,10 @@ public class DBInitializingBean implements org.springframework.beans.factory.Ini
             epAppRoleFunction21, epAppRoleFunction22, epAppRoleFunction23, epAppRoleFunction24, epAppRoleFunction25,
             epAppRoleFunction26, epAppRoleFunction27, epAppRoleFunction28));
 
-    epAppRoleFunctionDao.saveAll(epAppRoleFunctions);
+    epAppRoleFunctionService.saveAll(epAppRoleFunctions);
 
     EpBasicAuthAccount epBasicAuthAccount = EpBasicAuthAccount.builder().extAppName("JIRA").username("jira").password("6APqvG4AU2rfLgCvMdySwQ==").activeYn(true).build();
-    epBasicAuthAccountDao.save(epBasicAuthAccount);
+    epBasicAuthAccountService.save(epBasicAuthAccount);
 
     // EP_MICROSERVICE TABLE
 
@@ -648,7 +594,7 @@ public class DBInitializingBean implements org.springframework.beans.factory.Ini
 
     List<EpMicroservice> epMicroservices = new ArrayList<>(Arrays.asList(epMicroservice1, epMicroservice2, epMicroservice3, epMicroservice4));
 
-    epMicroserviceDao.saveAll(epMicroservices);
+    epMicroserviceService.saveAll(epMicroservices);
 
     // ep_microservice_parameter table
 
@@ -659,7 +605,7 @@ public class DBInitializingBean implements org.springframework.beans.factory.Ini
 
     List<EpMicroserviceParameter> epMicroserviceParameters = new ArrayList<>(Arrays.asList(parameter1, parameter2, parameter3, parameter4));
 
-    epMicroserviceParameterDao.saveAll(epMicroserviceParameters);
+    epMicroserviceParameterService.saveAll(epMicroserviceParameters);
 
     // ep_widget_catalog table
     //TODO should we connect serviceId to EpMicroservice?
@@ -671,7 +617,7 @@ public class DBInitializingBean implements org.springframework.beans.factory.Ini
 
     List<EpWidgetCatalog> epWidgetCatalogs = new ArrayList<>(Arrays.asList(epWidgetCatalog1, epWidgetCatalog2, epWidgetCatalog3, epWidgetCatalog4));
 
-    epWidgetCatalogDao.saveAll(epWidgetCatalogs);
+    epWidgetCatalogService.saveAll(epWidgetCatalogs);
 
     // ep_widget_catalog_files table
     //TODO
@@ -691,7 +637,7 @@ public class DBInitializingBean implements org.springframework.beans.factory.Ini
 
     List<FnAppContactUs> fnAppContactUses = new ArrayList<>(Arrays.asList(fnAppContactUs1, fnAppContactUs2, fnAppContactUs3, fnAppContactUs4, fnAppContactUs5, fnAppContactUs6, fnAppContactUs7, fnAppContactUs8));
 
-    fnAppContactUsDao.saveAll(fnAppContactUses);
+    fnAppContactUsService.saveAll(fnAppContactUses);
 
     // fn_common_widget_data table
 
@@ -708,15 +654,15 @@ public class DBInitializingBean implements org.springframework.beans.factory.Ini
 
     List<FnCommonWidgetData> fnCommonWidgetDataList = new ArrayList<>(Arrays.asList(fnCommonWidgetData1, fnCommonWidgetData2, fnCommonWidgetData3, fnCommonWidgetData4, fnCommonWidgetData5, fnCommonWidgetData6, fnCommonWidgetData7, fnCommonWidgetData8, fnCommonWidgetData9, fnCommonWidgetData10));
 
-    fnCommonWidgetDataDao.saveAll(fnCommonWidgetDataList);
+    fnCommonWidgetDataService.saveAll(fnCommonWidgetDataList);
 
     // fn_language table
     //TODO fix china text
     FnLanguage language1 = new FnLanguage("English", "EN");
     FnLanguage language2 = new FnLanguage("简体ä¸\u00ADæ–‡", "CN");
 
-    fnLanguageDao.save(language1);
-    fnLanguageDao.save(language2);
+    fnLanguageService.save(language1);
+    fnLanguageService.save(language2);
 
     // fn_display_text table
     // TODO should we change languageId from long type to FnLanguage?
@@ -754,7 +700,7 @@ public class DBInitializingBean implements org.springframework.beans.factory.Ini
         fnDisplayText18, fnDisplayText19, fnDisplayText20, fnDisplayText21, fnDisplayText22, fnDisplayText23, fnDisplayText24,
         fnDisplayText25, fnDisplayText26));
 
-    fnDisplayTextDao.saveAll(fnDisplayTexts);
+    fnDisplayTextService.saveAll(fnDisplayTexts);
 
     // fn_function table
 
@@ -792,7 +738,7 @@ public class DBInitializingBean implements org.springframework.beans.factory.Ini
         menuJobDesigner, menuLogout, menuMap, menuNotes, menuProcess, menuProfile, menuProfileCreate, menuProfileImport,
         menuReports, menuSample, menuTab, menuTask, menuTaskSearch, menuWebAnalytics, saveNotification, viewReports));
 
-    fnFunctionDao.saveAll(fnFunctions);
+    fnFunctionService.saveAll(fnFunctions);
 
     // fn_lu_activity table
 
@@ -830,7 +776,7 @@ public class DBInitializingBean implements org.springframework.beans.factory.Ini
         activity16, activity17, activity18, activity19, activity20, activity21, activity22, activity23, activity24, activity25,
         tabAccess, activity27, activity28));
 
-    fnLuActivityDao.saveAll(luActivities);
+    fnLuActivityService.saveAll(luActivities);
 
     //fn_lu_alert_method table
 
@@ -842,19 +788,19 @@ public class DBInitializingBean implements org.springframework.beans.factory.Ini
 
     List<FnLuAlertMethod> alertMethods = new ArrayList<>(Arrays.asList(alertMethod1, alertMethod2, alertMethod3, alertMethod4, alertMethod5));
 
-    fnLuAlertMethodDao.saveAll(alertMethods);
+    fnLuAlertMethodService.saveAll(alertMethods);
 
     // fn_lu_menu_set table
 
     FnLuMenuSet menuSet = FnLuMenuSet.builder().menuSetCd("APP").menuSetName("Application Menu").build();
 
-    fnLuMenuSetDao.save(menuSet);
+    fnLuMenuSetService.save(menuSet);
 
     // fn_lu_tab_set table
 
     FnLuTabSet fnLuTabSet = FnLuTabSet.builder().tabSetCd("APP").tabSetName("Application Tabs").build();
 
-    fnLuTabSetDao.save(fnLuTabSet);
+    fnLuTabSetService.save(fnLuTabSet);
 
     // fn_lu_priority table
 
@@ -866,7 +812,7 @@ public class DBInitializingBean implements org.springframework.beans.factory.Ini
 
     List<FnLuPriority> priorities = new ArrayList<>(Arrays.asList(low, normal, high, urgent, fatal));
 
-    fnLuPriorityDao.saveAll(priorities);
+    fnLuPriorityService.saveAll(priorities);
 
     // fn_lu_timezone table
 
@@ -880,7 +826,7 @@ public class DBInitializingBean implements org.springframework.beans.factory.Ini
 
     List<FnLuTimezone> timezones = new ArrayList<>(Arrays.asList(USEastern, USCentral, USMountain, USArizona, USPacific, USAlaska, USHawaii));
 
-    fnLuTimezoneDao.saveAll(timezones);
+    fnLuTimezoneService.saveAll(timezones);
 
     // fn_menu table
 
@@ -901,7 +847,7 @@ public class DBInitializingBean implements org.springframework.beans.factory.Ini
 
     List<FnMenu> fnMenus = new ArrayList<>(Arrays.asList(menu1, menu2, menu3, menu4, menu5, menu6, menu7, menu8, menu9, menu10, menu11, menu12, menu13, menu14));
 
-    fnMenuDao.saveAll(fnMenus);
+    fnMenuService.saveAll(fnMenus);
 
     // fn_menu_functional table
 
@@ -953,7 +899,7 @@ public class DBInitializingBean implements org.springframework.beans.factory.Ini
         menuFunctional313, menuFunctional316, menuFunctional148, menuFunctional317, menuFunctional318, menuFunctional319));
 
 
-    fnMenuFunctionalDao.saveAll(menuFunctionals);
+    fnMenuFunctionalService.saveAll(menuFunctionals);
 
     // fn_menu_functional_ancestors table
 
@@ -1086,7 +1032,7 @@ public class DBInitializingBean implements org.springframework.beans.factory.Ini
         ancestors150, ancestors151, ancestors152, ancestors158, ancestors159, ancestors160, ancestors161, ancestors162,
         ancestors163, ancestors164, ancestors165, ancestors166, ancestors167, ancestors168, ancestors169));
 
-    fnMenuFunctionalAncestorsDao.saveAll(ancestors);
+    fnMenuFunctionalAncestorsService.saveAll(ancestors);
 
     // fn_menu_functional_roles table
 
@@ -1128,7 +1074,7 @@ public class DBInitializingBean implements org.springframework.beans.factory.Ini
         functionalRoles22, functionalRoles23, functionalRoles24, functionalRoles25, functionalRoles26, functionalRoles27,
         functionalRoles39, functionalRoles40, functionalRoles42, functionalRoles43));
 
-    fnMenuFunctionalRolesDao.saveAll(functionalRoles);
+    fnMenuFunctionalRolesService.saveAll(functionalRoles);
 
     // fn_qz_job_details table
 
@@ -1142,7 +1088,7 @@ public class DBInitializingBean implements org.springframework.beans.factory.Ini
 
     List<FnQzJobDetails> jobDetails = new ArrayList<>(Arrays.asList(fnQzJobDetails1, fnQzJobDetails2));
 
-    fnQzJobDetailsDao.saveAll(jobDetails);
+    fnQzJobDetailsService.saveAll(jobDetails);
 
     // fn_qz_locks table
 
@@ -1151,7 +1097,7 @@ public class DBInitializingBean implements org.springframework.beans.factory.Ini
 
     List<FnQzLocks> locks = new ArrayList<>(Arrays.asList(fnQzLocks1, fnQzLocks2));
 
-    fnQzLocksDao.saveAll(locks);
+    fnQzLocksService.saveAll(locks);
 
     // fn_qz_scheduler_state table
 
@@ -1159,7 +1105,7 @@ public class DBInitializingBean implements org.springframework.beans.factory.Ini
         .instanceName("portal-portal-app-76c9f7bfb5-s8rhd1565254283688").lastCheckinTime(BigInteger.valueOf(1565691615399L))
         .checkinInterval(BigInteger.valueOf(20000L)).build();
 
-    fnQzSchedulerStateDao.save(schedulerState);
+    fnQzSchedulerStateService.save(schedulerState);
 
     // fn_qz_triggers table
     //TODO
@@ -1168,7 +1114,7 @@ public class DBInitializingBean implements org.springframework.beans.factory.Ini
 
     List<FnQzTriggers> fnQzTriggers = new ArrayList<>(Arrays.asList(trigger1, trigger2));
 
-    // fnQzTriggersDao.saveAll(fnQzTriggers);
+    // fnQzTriggersService.saveAll(fnQzTriggers);
 
     // fn_qz_cron_triggers table
     //TODO
@@ -1178,7 +1124,7 @@ public class DBInitializingBean implements org.springframework.beans.factory.Ini
 
     List<FnQzCronTriggers> cronTriggers = new ArrayList<>(Arrays.asList(cronTrigger1, cronTrigger2));
 
-    //fnQzCronTriggersDao.saveAll(cronTriggers);
+    //fnQzCronTriggersService.saveAll(cronTriggers);
 
     // fn_restricted_url table
     //TODO
@@ -1231,13 +1177,13 @@ public class DBInitializingBean implements org.springframework.beans.factory.Ini
         url26, url27, url28, url29, url30, url31, url32, url33, url34, url35, url36, url37, url38, url39, url40, url41,
         url42, url43));
 
-    //fnRestrictedUrlDao.saveAll(urls);
+    //fnRestrictedUrlService.saveAll(urls);
 
     // fn_role_composite table
     //TODO
     FnRoleComposite roleComposite = FnRoleComposite.builder().parentRoles(fnRole1).childRoles(fnRole16).build();
 
-    //fnRoleCompositeDao.save(roleComposite);
+    //fnRoleCompositeService.save(roleComposite);
 
     // fn_role_function table
 
@@ -1283,7 +1229,7 @@ public class DBInitializingBean implements org.springframework.beans.factory.Ini
         roleFunction23, roleFunction24, roleFunction25, roleFunction26, roleFunction27, roleFunction28, roleFunction29,
         roleFunction30, roleFunction31, roleFunction32, roleFunction33, roleFunction34));
 
-    fnRoleFunctionDao.saveAll(roleFunctions);
+    fnRoleFunctionService.saveAll(roleFunctions);
 
 
     // fn_shared_context table
@@ -1304,7 +1250,7 @@ public class DBInitializingBean implements org.springframework.beans.factory.Ini
     List<FnSharedContext> sharedContexts = new ArrayList<>(Arrays.asList(sharedContext1, sharedContext2, sharedContext3,
         sharedContext4, sharedContext5, sharedContext6, sharedContext7, sharedContext8, sharedContext9, sharedContext10, sharedContext11, sharedContext12));
 
-    fnSharedContextDao.saveAll(sharedContexts);
+    fnSharedContextService.saveAll(sharedContexts);
 
     // fn_tab table
 
@@ -1319,7 +1265,7 @@ public class DBInitializingBean implements org.springframework.beans.factory.Ini
 
     List<FnTab> fnTabs = new ArrayList<>(Arrays.asList(TAB1, TAB2, TAB2_SUB1, TAB2_SUB1_S1, TAB2_SUB2, TAB2_SUB3, TAB3, TAB4));
 
-    fnTabDao.saveAll(fnTabs);
+    fnTabService.saveAll(fnTabs);
 
     // fn_tab_selected table
 
@@ -1337,7 +1283,7 @@ public class DBInitializingBean implements org.springframework.beans.factory.Ini
     List<FnTabSelected> tabSelecteds = new ArrayList<>(Arrays.asList(tabSelected1, tabSelected2, tabSelected3, tabSelected4,
         tabSelected5, tabSelected6, tabSelected7, tabSelected8, tabSelected9, tabSelected10));
 
-//    fnTabSelectedDao.saveAll(tabSelecteds);
+//    fnTabSelectedService.saveAll(tabSelecteds);
 
     // fn_user table
 
@@ -1356,13 +1302,13 @@ public class DBInitializingBean implements org.springframework.beans.factory.Ini
 
     List<FnUser> fnUsers = new ArrayList<>(Arrays.asList(fnUser1, fnUser2, fnUser3, fnUser4, fnUser5, fnUser6, fnUser7, fnUser8, fnUser9, fnUser10, fnUser11, fnUser12));
 
-    fnUserDao.saveAll(fnUsers);
+    fnUserService.saveAll(fnUsers);
 
     // ep_pers_user_app_sort table
 
     EpPersUserAppSort appSort = EpPersUserAppSort.builder().userID(fnUser1).sortPref(0).build();
 
-    epPersUserAppSortDao.save(appSort);
+    epPersUserAppSortService.save(appSort);
 
     // fn_pers_user_app_sel table
 
@@ -1373,7 +1319,7 @@ public class DBInitializingBean implements org.springframework.beans.factory.Ini
 
     List<FnPersUserAppSel> appSels = new ArrayList<>(Arrays.asList(appSel1, appSel2, appSel3, appSel4));
 
-    fnPersUserAppSelDao.saveAll(appSels);
+    fnPersUserAppSelService.saveAll(appSels);
 
     // fn_audit_log table
 
@@ -1387,7 +1333,7 @@ public class DBInitializingBean implements org.springframework.beans.factory.Ini
 
     List<FnAuditLog> auditLogs = new ArrayList<>(Arrays.asList(fnAuditLog1, fnAuditLog2, fnAuditLog3, fnAuditLog4, fnAuditLog5, fnAuditLog6, fnAuditLog7));
 
-    fnAuditLogDao.saveAll(auditLogs);
+    fnAuditLogService.saveAll(auditLogs);
 
     // fn_user_role table
 
@@ -1437,7 +1383,7 @@ public class DBInitializingBean implements org.springframework.beans.factory.Ini
         userRole25, userRole26, userRole27, userRole28, userRole29, userRole30, userRole31, userRole32, userRole33, userRole34,
         userRole35, userRole36, userRole37, userRole38, userRole39));
 
-    fnUserRoleDao.saveAll(userRoles);
+    fnUserRoleService.saveAll(userRoles);
 
 
   }
index a0542ec..5fd919b 100644 (file)
@@ -40,7 +40,7 @@
 
 package org.onap.portal.configuration;
 
-import org.onap.portal.service.fn.FnUserService;
+import org.onap.portal.service.user.FnUserService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
index f3b3818..9360984 100644 (file)
 
 package org.onap.portal.configuration;
 
-import org.onap.portal.dao.fn.FnFunctionDao;
+import org.onap.portal.service.function.FnFunctionService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
 import org.springframework.core.Ordered;
 import org.springframework.web.servlet.config.annotation.EnableWebMvc;
 import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
@@ -52,11 +53,11 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 @ComponentScan("org.springframework.security.samples.mvc")
 public class WebMvcConfiguration implements WebMvcConfigurer {
 
-       private final FnFunctionDao fnFunctionDao;
+       private final FnFunctionService fnFunctionService;
 
        @Autowired
-       public WebMvcConfiguration(FnFunctionDao fnFunctionDao) {
-              this.fnFunctionDao = fnFunctionDao;
+       public WebMvcConfiguration(FnFunctionService fnFunctionService) {
+              this.fnFunctionService = fnFunctionService;
        }
 
        @Override
index 4a25e61..28c21d3 100644 (file)
@@ -50,8 +50,8 @@ import org.onap.portal.domain.dto.PortalRestStatusEnum;
 import org.onap.portal.domain.dto.fn.FnLanguageDto;
 import org.onap.portal.domain.mapper.FnLanguageMapper;
 import org.onap.portal.domain.mapper.FnUserMapper;
-import org.onap.portal.service.fn.FnLanguageService;
-import org.onap.portal.service.fn.FnUserService;
+import org.onap.portal.service.language.FnLanguageService;
+import org.onap.portal.service.user.FnUserService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
index 571ab20..3f05b0a 100644 (file)
@@ -45,7 +45,7 @@ import org.onap.portal.domain.db.fn.FnUser;
 import org.onap.portal.domain.dto.PortalRestResponse;
 import org.onap.portal.domain.dto.PortalRestStatusEnum;
 import org.onap.portal.domain.dto.transport.ProfileDetail;
-import org.onap.portal.service.fn.FnUserService;
+import org.onap.portal.service.user.FnUserService;
 import org.onap.portal.validation.DataValidator;
 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
 import org.onap.portalsdk.core.onboarding.util.CipherUtil;
index dbba777..1a2cb5d 100644 (file)
@@ -66,8 +66,8 @@ import org.onap.portal.logging.aop.EPEELFLoggerAdvice;
 import org.onap.portal.logging.logic.EPLogUtil;
 import org.onap.portal.service.AdminRolesService;
 import org.onap.portal.service.ApplicationsRestClientService;
-import org.onap.portal.service.fn.FnUserRoleService;
-import org.onap.portal.service.fn.FnUserService;
+import org.onap.portal.service.userRole.FnUserRoleService;
+import org.onap.portal.service.user.FnUserService;
 import org.onap.portal.utils.EPCommonSystemProperties;
 import org.onap.portal.utils.EcompPortalUtils;
 import org.onap.portal.utils.PortalConstants;
index 5977944..93d6dd5 100644 (file)
@@ -59,9 +59,9 @@ import org.onap.portal.domain.dto.ecomp.WidgetParameterResult;
 import org.onap.portal.domain.dto.ecomp.WidgetServiceHeaders;
 import org.onap.portal.logging.aop.EPAuditLog;
 import org.onap.portal.service.WidgetMService;
-import org.onap.portal.service.ep.EpMicroserviceParameterService;
-import org.onap.portal.service.ep.EpWidgetCatalogParameterService;
-import org.onap.portal.service.fn.FnUserService;
+import org.onap.portal.service.microserviceParameter.EpMicroserviceParameterService;
+import org.onap.portal.service.widgetCatalogParameter.EpWidgetCatalogParameterService;
+import org.onap.portal.service.user.FnUserService;
 import org.onap.portal.utils.EPCommonSystemProperties;
 import org.onap.portal.utils.EcompPortalUtils;
 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
index 6a92fbc..db7039f 100644 (file)
@@ -50,12 +50,10 @@ import org.onap.portal.domain.dto.transport.FieldsValidator;
 import org.onap.portal.domain.dto.transport.OnboardingWidget;
 import org.onap.portal.domain.dto.transport.WidgetCatalogPersonalization;
 import org.onap.portal.logging.aop.EPAuditLog;
-import org.onap.portal.service.AdminRolesService;
 import org.onap.portal.service.PersUserWidgetService;
-import org.onap.portal.service.WidgetService;
-import org.onap.portal.service.fn.FnUserService;
+import org.onap.portal.service.widget.WidgetService;
+import org.onap.portal.service.user.FnUserService;
 import org.onap.portal.utils.EcompPortalUtils;
-import org.onap.portal.validation.DataValidator;
 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.EnableAspectJAutoProxy;
index 9024bdd..41e6a3e 100644 (file)
 
 package org.onap.portal.domain.dto.transport;
 
-
-import javax.validation.constraints.Email;
-import javax.validation.constraints.NotBlank;
 import lombok.AllArgsConstructor;
 import lombok.EqualsAndHashCode;
 import lombok.Getter;
 import lombok.NoArgsConstructor;
 import lombok.Setter;
 import lombok.ToString;
+import org.hibernate.validator.constraints.Email;
+import org.hibernate.validator.constraints.NotBlank;
 
 @Setter
 @Getter
index 2c7151a..9c00b7a 100644 (file)
@@ -50,7 +50,7 @@ import javax.servlet.http.HttpServletRequest;
 import org.onap.portal.domain.db.fn.FnApp;
 import org.onap.portal.domain.db.fn.FnUser;
 import org.onap.portal.service.AppsCacheService;
-import org.onap.portal.service.fn.FnUserService;
+import org.onap.portal.service.user.FnUserService;
 import org.onap.portal.utils.EPCommonSystemProperties;
 import org.onap.portal.utils.EcompPortalUtils;
 import org.onap.portalsdk.core.exception.SessionExpiredException;
index 8049cd6..187e175 100644 (file)
@@ -57,7 +57,6 @@ import java.util.Set;
 import java.util.SortedSet;
 import java.util.TreeSet;
 import java.util.stream.Collectors;
-import javax.annotation.PostConstruct;
 import javax.persistence.EntityManager;
 import javax.persistence.Query;
 import javax.persistence.Tuple;
@@ -96,15 +95,15 @@ import org.onap.portal.exception.DeleteDomainObjectFailedException;
 import org.onap.portal.exception.SyncUserRolesException;
 import org.onap.portal.logging.format.EPAppMessagesEnum;
 import org.onap.portal.logging.logic.EPLogUtil;
-import org.onap.portal.service.ep.EpAppFunctionService;
-import org.onap.portal.service.ep.EpUserRolesRequestDetService;
-import org.onap.portal.service.ep.EpUserRolesRequestService;
-import org.onap.portal.service.fn.FnAppService;
-import org.onap.portal.service.fn.FnMenuFunctionalRolesService;
-import org.onap.portal.service.fn.FnMenuFunctionalService;
-import org.onap.portal.service.fn.FnRoleService;
-import org.onap.portal.service.fn.FnUserRoleService;
-import org.onap.portal.service.fn.FnUserService;
+import org.onap.portal.service.appFunction.EpAppFunctionService;
+import org.onap.portal.service.userRolesRequestDet.EpUserRolesRequestDetService;
+import org.onap.portal.service.userRolesRequest.EpUserRolesRequestService;
+import org.onap.portal.service.app.FnAppService;
+import org.onap.portal.service.menuFunctionalRoles.FnMenuFunctionalRolesService;
+import org.onap.portal.service.menuFunctional.FnMenuFunctionalService;
+import org.onap.portal.service.role.FnRoleService;
+import org.onap.portal.service.userRole.FnUserRoleService;
+import org.onap.portal.service.user.FnUserService;
 import org.onap.portal.utils.EPCommonSystemProperties;
 import org.onap.portal.utils.EPUserUtils;
 import org.onap.portal.utils.EcompPortalUtils;
@@ -223,7 +222,7 @@ public class AdminRolesService {
     return false;
   }
 
-  boolean isUser(FnUser user) {
+  public boolean isUser(FnUser user) {
     try {
       FnUser currentUser = fnUserService.getUser(user.getId()).orElseThrow(Exception::new);
       if (currentUser != null && currentUser.getId() != null) {
index 83b5df9..b7dd4bf 100644 (file)
@@ -48,7 +48,7 @@ import java.util.stream.Collectors;
 import javax.annotation.PostConstruct;
 import org.onap.portal.domain.db.fn.FnApp;
 import org.onap.portal.domain.dto.transport.OnboardingApp;
-import org.onap.portal.service.fn.FnAppService;
+import org.onap.portal.service.app.FnAppService;
 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -35,7 +35,7 @@
  *
  * 
  */
-package org.onap.portal.service.fn.old;
+package org.onap.portal.service;
 
 import java.util.HashMap;
 import java.util.HashSet;
@@ -57,8 +57,6 @@ import org.springframework.transaction.annotation.Transactional;
 public class EPRoleFunctionService {
        @Autowired
        private DataAccessService dataAccessService;
-       
-       
 
        public DataAccessService getDataAccessService() {
                return dataAccessService;
index b673923..b9f161f 100644 (file)
@@ -59,9 +59,9 @@ import org.onap.portal.domain.dto.transport.CentralV2Role;
 import org.onap.portal.domain.dto.transport.GlobalRoleWithApplicationRoleFunction;
 import org.onap.portal.exception.RoleFunctionException;
 import org.onap.portal.logging.logic.EPLogUtil;
-import org.onap.portal.service.ep.EpAppFunctionService;
-import org.onap.portal.service.fn.FnAppService;
-import org.onap.portal.service.fn.FnRoleService;
+import org.onap.portal.service.appFunction.EpAppFunctionService;
+import org.onap.portal.service.app.FnAppService;
+import org.onap.portal.service.role.FnRoleService;
 import org.onap.portal.utils.EPCommonSystemProperties;
 import org.onap.portal.utils.EPUserUtils;
 import org.onap.portal.utils.EcompPortalUtils;
index 28d63eb..2a5d0ae 100644 (file)
@@ -43,13 +43,13 @@ package org.onap.portal.service;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.stream.Collectors;
-import org.onap.portal.dao.ep.EpPersUserWidgetSelDao;
-import org.onap.portal.dao.fn.EpWidgetCatalogDao;
 import org.onap.portal.domain.db.ep.EpPersUserWidgetSel;
 import org.onap.portal.domain.db.ep.EpWidgetCatalog;
 import org.onap.portal.domain.db.fn.FnUser;
 import org.onap.portal.domain.dto.ecomp.PersUserWidgetSelection;
 import org.onap.portal.domain.dto.transport.WidgetCatalogPersonalization;
+import org.onap.portal.service.persUserWidgetSel.EpPersUserWidgetSelService;
+import org.onap.portal.service.widgetCatalog.EpWidgetCatalogService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -61,14 +61,14 @@ import org.springframework.transaction.annotation.Transactional;
 public class PersUserWidgetService {
 
        private static final Logger LOGGER = LoggerFactory.getLogger(PersUserWidgetService.class);
-       private final EpPersUserWidgetSelDao epPersUserWidgetSelDao;
-       private final EpWidgetCatalogDao epWidgetCatalogDao;
+       private final EpPersUserWidgetSelService epPersUserWidgetSelService;
+       private final EpWidgetCatalogService epWidgetCatalogService;
 
        @Autowired
-       public PersUserWidgetService(final EpPersUserWidgetSelDao epPersUserWidgetSelDao,
-               final EpWidgetCatalogDao epWidgetCatalogDao) {
-              this.epPersUserWidgetSelDao = epPersUserWidgetSelDao;
-              this.epWidgetCatalogDao = epWidgetCatalogDao;
+       public PersUserWidgetService(final EpPersUserWidgetSelService epPersUserWidgetSelService,
+               final EpWidgetCatalogService epWidgetCatalogService) {
+              this.epPersUserWidgetSelService = epPersUserWidgetSelService;
+              this.epWidgetCatalogService = epWidgetCatalogService;
        }
 
        public void setPersUserAppValue(FnUser user, WidgetCatalogPersonalization personalization) {
@@ -83,19 +83,19 @@ public class PersUserWidgetService {
               }
 
               if (persRow.getId() != null) {
-                     epPersUserWidgetSelDao.deleteById(persRow.getId());
+                     epPersUserWidgetSelService.deleteById(persRow.getId());
               }
 
               persRow.setStatusCode(personalization.getSelect() ? "S" : "H"); // Show / Hide
               EpPersUserWidgetSel epPersUserWidgetSel = new EpPersUserWidgetSel();
               epPersUserWidgetSel.setUserId(user);
               epPersUserWidgetSel.setWidgetId(
-                      epWidgetCatalogDao.findById(personalization.getWidgetId()).orElse(new EpWidgetCatalog()));
-              epPersUserWidgetSelDao.saveAndFlush(epPersUserWidgetSel);
+                      epWidgetCatalogService.findById(personalization.getWidgetId()).orElse(new EpWidgetCatalog()));
+              epPersUserWidgetSelService.saveAndFlush(epPersUserWidgetSel);
        }
 
        private List<PersUserWidgetSelection> getUserWidgetSelction(FnUser user, Long widgetId) {
-              return epPersUserWidgetSelDao
+              return epPersUserWidgetSelService
                       .getEpPersUserWidgetSelForUserIdAndWidgetId(user.getId(), widgetId)
                       .orElse(new ArrayList<>())
                       .stream()
@@ -1,4 +1,4 @@
-package org.onap.portal.dao.fn;
+package org.onap.portal.service.app;
 
 import java.util.List;
 import org.onap.portal.domain.db.fn.FnApp;
@@ -10,7 +10,7 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Repository
 @Transactional
-public interface FnAppDao extends JpaRepository<FnApp, Long> {
+interface FnAppDao extends JpaRepository<FnApp, Long> {
 
   @Query
   List<FnApp> getByUebKey(final @Param("uebKey") String uebKey);
  *
  */
 
-package org.onap.portal.service.fn;
+package org.onap.portal.service.app;
 
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Optional;
 import javax.persistence.EntityExistsException;
 import javax.persistence.EntityManager;
-import org.onap.portal.dao.fn.FnAppDao;
+
 import org.onap.portal.domain.db.fn.FnApp;
 import org.onap.portal.domain.dto.transport.OnboardingApp;
 import org.onap.portal.utils.EPCommonSystemProperties;
@@ -66,7 +66,7 @@ public class FnAppService {
   private final EntityManager entityManager;
 
   @Autowired
-  public FnAppService(final FnAppDao fnAppDao, EntityManager entityManager) {
+  public FnAppService(FnAppDao fnAppDao, EntityManager entityManager) {
     this.fnAppDao = fnAppDao;
     this.entityManager = entityManager;
   }
@@ -123,7 +123,7 @@ public class FnAppService {
     return result;
   }
 
-  List<FnApp> getUserRemoteApps(String id) {
+  public List<FnApp> getUserRemoteApps(String id) {
 /*    StringBuilder sb = new StringBuilder();
     sb.append("SELECT * FROM FnApp join FN_USER_ROLE ON FN_USER_ROLE.APP_ID = FN_APP.APP_ID where ");
     sb.append("FN_USER_ROLE.USER_ID = ").append(id).append(" AND FN_USER_ROLE.ROLE_ID != ")
@@ -134,4 +134,8 @@ public class FnAppService {
     List<FnApp> adminApps = query.getResultList();*/
     return new ArrayList<>();
   }
+
+  public List<FnApp> saveAll(List<FnApp> fnApps) {
+    return fnAppDao.saveAll(fnApps);
+  }
 }
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.dao.fn;
+package org.onap.portal.service.appContactUs;
 
 import org.onap.portal.domain.db.fn.FnAppContactUs;
 import org.springframework.data.jpa.repository.JpaRepository;
@@ -47,6 +47,6 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Transactional
 @Repository
-public interface FnAppContactUsDao extends JpaRepository<FnAppContactUs, Long> {
+interface FnAppContactUsDao extends JpaRepository<FnAppContactUs, Long> {
 
 }
diff --git a/portal-BE/src/main/java/org/onap/portal/service/appContactUs/FnAppContactUsService.java b/portal-BE/src/main/java/org/onap/portal/service/appContactUs/FnAppContactUsService.java
new file mode 100644 (file)
index 0000000..600d832
--- /dev/null
@@ -0,0 +1,22 @@
+package org.onap.portal.service.appContactUs;
+
+import org.onap.portal.domain.db.fn.FnAppContactUs;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class FnAppContactUsService {
+
+    private final FnAppContactUsDao fnAppContactUsDao;
+
+    @Autowired
+    public FnAppContactUsService(FnAppContactUsDao fnAppContactUsDao) {
+        this.fnAppContactUsDao = fnAppContactUsDao;
+    }
+
+    public List<FnAppContactUs> saveAll(List<FnAppContactUs> fnAppContactUses) {
+        return fnAppContactUsDao.saveAll(fnAppContactUses);
+    }
+}
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.dao.ep;
+package org.onap.portal.service.appFunction;
 
 import java.util.List;
 import org.onap.portal.domain.db.ep.EpAppFunction;
@@ -50,7 +50,7 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Repository
 @Transactional
-public interface EpAppFunctionDao extends JpaRepository<EpAppFunction, Long> {
+interface EpAppFunctionDao extends JpaRepository<EpAppFunction, Long> {
 
   @Query
   List<EpAppFunction> getAppRoleFunctionList(final @Param("roleId") Long roleId, final @Param("appId") Long appId);
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.service.ep;
+package org.onap.portal.service.appFunction;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -46,7 +46,7 @@ import java.util.Optional;
 import java.util.function.Function;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
-import org.onap.portal.dao.ep.EpAppFunctionDao;
+
 import org.onap.portal.domain.db.ep.EpAppFunction;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -76,4 +76,8 @@ public class EpAppFunctionService {
     List<Object> seen = new ArrayList<>();
     return t -> seen.add(keyExtractor.apply(t));
   }
+
+  public List<EpAppFunction> saveAll(List<EpAppFunction> epAppFunctions) {
+    return epAppFunctionDao.saveAll(epAppFunctions);
+  }
 }
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.dao.ep;
+package org.onap.portal.service.appRoleFunction;
 
 import org.onap.portal.domain.db.ep.EpAppRoleFunction;
 import org.springframework.data.jpa.repository.JpaRepository;
@@ -47,6 +47,6 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Repository
 @Transactional
-public interface EpAppRoleFunctionDao extends JpaRepository<EpAppRoleFunction, Integer> {
+interface EpAppRoleFunctionDao extends JpaRepository<EpAppRoleFunction, Integer> {
 
 }
diff --git a/portal-BE/src/main/java/org/onap/portal/service/appRoleFunction/EpAppRoleFunctionService.java b/portal-BE/src/main/java/org/onap/portal/service/appRoleFunction/EpAppRoleFunctionService.java
new file mode 100644 (file)
index 0000000..cb5383b
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ * Modifications Copyright (c) 2019 Samsung
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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============================================
+ *
+ *
+ */
+
+package org.onap.portal.service.appRoleFunction;
+
+import org.onap.portal.domain.db.ep.EpAppRoleFunction;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class EpAppRoleFunctionService {
+
+    private final EpAppRoleFunctionDao epAppRoleFunctionDao;
+
+    @Autowired
+    public EpAppRoleFunctionService(EpAppRoleFunctionDao epAppRoleFunctionDao) {
+        this.epAppRoleFunctionDao = epAppRoleFunctionDao;
+    }
+
+    public List<EpAppRoleFunction> saveAll(List<EpAppRoleFunction> epAppRoleFunctions) {
+        return epAppRoleFunctionDao.saveAll(epAppRoleFunctions);
+    }
+}
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.dao.fn;
+package org.onap.portal.service.auditLog;
 
 import org.onap.portal.domain.db.fn.FnAuditLog;
 import org.springframework.data.jpa.repository.JpaRepository;
@@ -47,6 +47,6 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Repository
 @Transactional
-public interface FnAuditLogDao extends JpaRepository<FnAuditLog, Integer> {
+interface FnAuditLogDao extends JpaRepository<FnAuditLog, Integer> {
 
 }
diff --git a/portal-BE/src/main/java/org/onap/portal/service/auditLog/FnAuditLogService.java b/portal-BE/src/main/java/org/onap/portal/service/auditLog/FnAuditLogService.java
new file mode 100644 (file)
index 0000000..ef51aab
--- /dev/null
@@ -0,0 +1,22 @@
+package org.onap.portal.service.auditLog;
+
+import org.onap.portal.domain.db.fn.FnAuditLog;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class FnAuditLogService {
+
+    private final FnAuditLogDao fnAuditLogDao;
+
+    @Autowired
+    public FnAuditLogService(FnAuditLogDao fnAuditLogDao) {
+        this.fnAuditLogDao = fnAuditLogDao;
+    }
+
+    public List<FnAuditLog> saveAll(List<FnAuditLog> auditLogs) {
+        return fnAuditLogDao.saveAll(auditLogs);
+    }
+}
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.dao.ep;
+package org.onap.portal.service.basicAuthAccount;
 
 import org.onap.portal.domain.db.ep.EpBasicAuthAccount;
 import org.springframework.data.jpa.repository.JpaRepository;
@@ -47,6 +47,6 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Transactional
 @Repository
-public interface EpBasicAuthAccountDao extends JpaRepository<EpBasicAuthAccount, Long> {
+interface EpBasicAuthAccountDao extends JpaRepository<EpBasicAuthAccount, Long> {
 
 }
diff --git a/portal-BE/src/main/java/org/onap/portal/service/basicAuthAccount/EpBasicAuthAccountService.java b/portal-BE/src/main/java/org/onap/portal/service/basicAuthAccount/EpBasicAuthAccountService.java
new file mode 100644 (file)
index 0000000..3b23e91
--- /dev/null
@@ -0,0 +1,20 @@
+package org.onap.portal.service.basicAuthAccount;
+
+import org.onap.portal.domain.db.ep.EpBasicAuthAccount;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class EpBasicAuthAccountService {
+
+    private final EpBasicAuthAccountDao epBasicAuthAccountDao;
+
+    @Autowired
+    public EpBasicAuthAccountService(EpBasicAuthAccountDao epBasicAuthAccountDao) {
+        this.epBasicAuthAccountDao = epBasicAuthAccountDao;
+    }
+
+    public EpBasicAuthAccount save(EpBasicAuthAccount epBasicAuthAccount) {
+        return epBasicAuthAccountDao.save(epBasicAuthAccount);
+    }
+}
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.dao.fn;
+package org.onap.portal.service.commonWidgetData;
 
 import org.onap.portal.domain.db.fn.FnCommonWidgetData;
 import org.springframework.data.jpa.repository.JpaRepository;
@@ -47,6 +47,6 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Repository
 @Transactional
-public interface FnCommonWidgetDataDao extends JpaRepository<FnCommonWidgetData, Long> {
+interface FnCommonWidgetDataDao extends JpaRepository<FnCommonWidgetData, Long> {
 
 }
diff --git a/portal-BE/src/main/java/org/onap/portal/service/commonWidgetData/FnCommonWidgetDataService.java b/portal-BE/src/main/java/org/onap/portal/service/commonWidgetData/FnCommonWidgetDataService.java
new file mode 100644 (file)
index 0000000..940d3ad
--- /dev/null
@@ -0,0 +1,22 @@
+package org.onap.portal.service.commonWidgetData;
+
+import org.onap.portal.domain.db.fn.FnCommonWidgetData;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class FnCommonWidgetDataService {
+
+    private final FnCommonWidgetDataDao fnCommonWidgetDataDao;
+
+    @Autowired
+    public FnCommonWidgetDataService(FnCommonWidgetDataDao fnCommonWidgetDataDao) {
+        this.fnCommonWidgetDataDao = fnCommonWidgetDataDao;
+    }
+
+    public List<FnCommonWidgetData> saveAll(List<FnCommonWidgetData> fnCommonWidgetDataList) {
+        return fnCommonWidgetDataDao.saveAll(fnCommonWidgetDataList);
+    }
+}
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.dao.fn;
+package org.onap.portal.service.displayText;
 
 import org.onap.portal.domain.db.fn.FnDisplayText;
 import org.springframework.data.jpa.repository.JpaRepository;
@@ -47,6 +47,6 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Transactional
 @Repository
-public interface FnDisplayTextDao extends JpaRepository<FnDisplayText, Long> {
+interface FnDisplayTextDao extends JpaRepository<FnDisplayText, Long> {
 
 }
diff --git a/portal-BE/src/main/java/org/onap/portal/service/displayText/FnDisplayTextService.java b/portal-BE/src/main/java/org/onap/portal/service/displayText/FnDisplayTextService.java
new file mode 100644 (file)
index 0000000..45870ca
--- /dev/null
@@ -0,0 +1,22 @@
+package org.onap.portal.service.displayText;
+
+import org.onap.portal.domain.db.fn.FnDisplayText;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class FnDisplayTextService {
+
+    private final FnDisplayTextDao fnDisplayTextDao;
+
+    @Autowired
+    public FnDisplayTextService(FnDisplayTextDao fnDisplayTextDao) {
+        this.fnDisplayTextDao = fnDisplayTextDao;
+    }
+
+    public List<FnDisplayText> saveAll(List<FnDisplayText> fnDisplayTexts) {
+        return fnDisplayTextDao.saveAll(fnDisplayTexts);
+    }
+}
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.dao.fn;
+package org.onap.portal.service.function;
 
 import org.onap.portal.domain.db.fn.FnFunction;
 import org.springframework.data.jpa.repository.JpaRepository;
@@ -47,6 +47,6 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Transactional
 @Repository
-public interface FnFunctionDao extends JpaRepository<FnFunction, String> {
+interface FnFunctionDao extends JpaRepository<FnFunction, String> {
 
 }
diff --git a/portal-BE/src/main/java/org/onap/portal/service/function/FnFunctionService.java b/portal-BE/src/main/java/org/onap/portal/service/function/FnFunctionService.java
new file mode 100644 (file)
index 0000000..d2361be
--- /dev/null
@@ -0,0 +1,22 @@
+package org.onap.portal.service.function;
+
+import org.onap.portal.domain.db.fn.FnFunction;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class FnFunctionService {
+
+    private final FnFunctionDao fnFunctionDao;
+
+    @Autowired
+    public FnFunctionService(FnFunctionDao fnFunctionDao) {
+        this.fnFunctionDao = fnFunctionDao;
+    }
+
+    public List<FnFunction> saveAll(List<FnFunction> fnFunctions) {
+        return fnFunctionDao.saveAll(fnFunctions);
+    }
+}
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.dao.fn;
+package org.onap.portal.service.language;
 
 import org.onap.portal.domain.db.fn.FnLanguage;
 import org.springframework.data.jpa.repository.JpaRepository;
@@ -49,7 +49,7 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Repository
 @Transactional
-public interface FnLanguageDao extends JpaRepository<FnLanguage, Long> {
+interface FnLanguageDao extends JpaRepository<FnLanguage, Long> {
   @Query
   FnLanguage getByLanguageAlias(final @Param("alias") String alias);
 
  *
  */
 
-package org.onap.portal.service.fn;
+package org.onap.portal.service.language;
 
 import java.security.Principal;
 import java.util.List;
 import java.util.Optional;
-import org.onap.portal.dao.fn.FnLanguageDao;
+
 import org.onap.portal.domain.db.fn.FnLanguage;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.EnableAspectJAutoProxy;
@@ -70,4 +70,12 @@ public class FnLanguageService {
        public FnLanguage save(final FnLanguage fnLanguage){
               return fnLanguageDao.saveAndFlush(fnLanguage);
        }
+
+       public FnLanguage getByLanguageAlias(String language) {
+              return fnLanguageDao.getByLanguageAlias(language);
+       }
+
+       public void delete(FnLanguage fnLanguage) {
+              fnLanguageDao.delete(fnLanguage);
+       }
 }
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.dao.fn;
+package org.onap.portal.service.luActivity;
 
 import org.onap.portal.domain.db.fn.FnLuActivity;
 import org.springframework.data.jpa.repository.JpaRepository;
@@ -47,6 +47,6 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Transactional
 @Repository
-public interface FnLuActivityDao extends JpaRepository<FnLuActivity, String> {
+interface FnLuActivityDao extends JpaRepository<FnLuActivity, String> {
 
 }
diff --git a/portal-BE/src/main/java/org/onap/portal/service/luActivity/FnLuActivityService.java b/portal-BE/src/main/java/org/onap/portal/service/luActivity/FnLuActivityService.java
new file mode 100644 (file)
index 0000000..0ce6800
--- /dev/null
@@ -0,0 +1,22 @@
+package org.onap.portal.service.luActivity;
+
+import org.onap.portal.domain.db.fn.FnLuActivity;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class FnLuActivityService {
+
+    private final FnLuActivityDao fnLuActivityDao;
+
+    @Autowired
+    public FnLuActivityService(FnLuActivityDao fnLuActivityDao) {
+        this.fnLuActivityDao = fnLuActivityDao;
+    }
+
+    public List<FnLuActivity> saveAll(List<FnLuActivity> luActivities) {
+        return fnLuActivityDao.saveAll(luActivities);
+    }
+}
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.dao.fn;
+package org.onap.portal.service.luAlertMethod;
 
 import org.onap.portal.domain.db.fn.FnLuAlertMethod;
 import org.springframework.data.jpa.repository.JpaRepository;
@@ -47,6 +47,6 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Transactional
 @Repository
-public interface FnLuAlertMethodDao extends JpaRepository<FnLuAlertMethod, String> {
+interface FnLuAlertMethodDao extends JpaRepository<FnLuAlertMethod, String> {
 
 }
diff --git a/portal-BE/src/main/java/org/onap/portal/service/luAlertMethod/FnLuAlertMethodService.java b/portal-BE/src/main/java/org/onap/portal/service/luAlertMethod/FnLuAlertMethodService.java
new file mode 100644 (file)
index 0000000..649ea98
--- /dev/null
@@ -0,0 +1,22 @@
+package org.onap.portal.service.luAlertMethod;
+
+import org.onap.portal.domain.db.fn.FnLuAlertMethod;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class FnLuAlertMethodService {
+
+    private final FnLuAlertMethodDao fnLuAlertMethodDao;
+
+    @Autowired
+    public FnLuAlertMethodService(FnLuAlertMethodDao fnLuAlertMethodDao) {
+        this.fnLuAlertMethodDao = fnLuAlertMethodDao;
+    }
+
+    public List<FnLuAlertMethod> saveAll(List<FnLuAlertMethod> alertMethods) {
+        return fnLuAlertMethodDao.saveAll(alertMethods);
+    }
+}
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.dao.fn;
+package org.onap.portal.service.luMenuSet;
 
 import org.onap.portal.domain.db.fn.FnLuMenuSet;
 import org.springframework.data.jpa.repository.JpaRepository;
@@ -47,6 +47,6 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Repository
 @Transactional
-public interface FnLuMenuSetDao extends JpaRepository<FnLuMenuSet, String> {
+interface FnLuMenuSetDao extends JpaRepository<FnLuMenuSet, String> {
 
 }
diff --git a/portal-BE/src/main/java/org/onap/portal/service/luMenuSet/FnLuMenuSetService.java b/portal-BE/src/main/java/org/onap/portal/service/luMenuSet/FnLuMenuSetService.java
new file mode 100644 (file)
index 0000000..3433cde
--- /dev/null
@@ -0,0 +1,20 @@
+package org.onap.portal.service.luMenuSet;
+
+import org.onap.portal.domain.db.fn.FnLuMenuSet;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class FnLuMenuSetService {
+
+    private final FnLuMenuSetDao fnLuMenuSetDao;
+
+    @Autowired
+    public FnLuMenuSetService(FnLuMenuSetDao fnLuMenuSetDao) {
+        this.fnLuMenuSetDao = fnLuMenuSetDao;
+    }
+
+    public FnLuMenuSet save(FnLuMenuSet menuSet) {
+        return fnLuMenuSetDao.save(menuSet);
+    }
+}
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.dao.fn;
+package org.onap.portal.service.luPriority;
 
 import org.onap.portal.domain.db.fn.FnLuPriority;
 import org.springframework.data.jpa.repository.JpaRepository;
@@ -47,6 +47,6 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Repository
 @Transactional
-public interface FnLuPriorityDao extends JpaRepository<FnLuPriority, Long> {
+interface FnLuPriorityDao extends JpaRepository<FnLuPriority, Long> {
 
 }
diff --git a/portal-BE/src/main/java/org/onap/portal/service/luPriority/FnLuPriorityService.java b/portal-BE/src/main/java/org/onap/portal/service/luPriority/FnLuPriorityService.java
new file mode 100644 (file)
index 0000000..998589c
--- /dev/null
@@ -0,0 +1,22 @@
+package org.onap.portal.service.luPriority;
+
+import org.onap.portal.domain.db.fn.FnLuPriority;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class FnLuPriorityService {
+
+    private final FnLuPriorityDao fnLuPriorityDao;
+
+    @Autowired
+    public FnLuPriorityService(FnLuPriorityDao fnLuPriorityDao) {
+        this.fnLuPriorityDao = fnLuPriorityDao;
+    }
+
+    public List<FnLuPriority> saveAll(List<FnLuPriority> priorities) {
+        return fnLuPriorityDao.saveAll(priorities);
+    }
+}
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.dao.fn;
+package org.onap.portal.service.luTabSet;
 
 import org.onap.portal.domain.db.fn.FnLuTabSet;
 import org.springframework.data.jpa.repository.JpaRepository;
@@ -47,6 +47,6 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Repository
 @Transactional
-public interface FnLuTabSetDao extends JpaRepository<FnLuTabSet, String> {
+interface FnLuTabSetDao extends JpaRepository<FnLuTabSet, String> {
 
 }
diff --git a/portal-BE/src/main/java/org/onap/portal/service/luTabSet/FnLuTabSetService.java b/portal-BE/src/main/java/org/onap/portal/service/luTabSet/FnLuTabSetService.java
new file mode 100644 (file)
index 0000000..b9c131a
--- /dev/null
@@ -0,0 +1,20 @@
+package org.onap.portal.service.luTabSet;
+
+import org.onap.portal.domain.db.fn.FnLuTabSet;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class FnLuTabSetService {
+
+    private final FnLuTabSetDao fnLuTabSetDao;
+
+    @Autowired
+    public FnLuTabSetService(FnLuTabSetDao fnLuTabSetDao) {
+        this.fnLuTabSetDao = fnLuTabSetDao;
+    }
+
+    public FnLuTabSet save(FnLuTabSet fnLuTabSet) {
+        return fnLuTabSetDao.save(fnLuTabSet);
+    }
+}
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.dao.fn;
+package org.onap.portal.service.luTimezone;
 
 import org.onap.portal.domain.db.fn.FnLuTimezone;
 import org.springframework.data.jpa.repository.JpaRepository;
@@ -47,6 +47,6 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Repository
 @Transactional
-public interface FnLuTimezoneDao extends JpaRepository<FnLuTimezone, Long> {
+interface FnLuTimezoneDao extends JpaRepository<FnLuTimezone, Long> {
 
 }
  *
  */
 
-package org.onap.portal.service.fn;
+package org.onap.portal.service.luTimezone;
 
+import java.util.List;
 import java.util.Optional;
-import org.onap.portal.dao.fn.FnLuTimezoneDao;
+
 import org.onap.portal.domain.db.fn.FnLuTimezone;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -60,4 +61,8 @@ public class FnLuTimezoneService {
        public Optional<FnLuTimezone> getById(Long id){
               return fnLuTimezoneDao.findById(id);
        }
+
+       public List<FnLuTimezone> saveAll(List<FnLuTimezone> timezones) {
+              return fnLuTimezoneDao.saveAll(timezones);
+       }
 }
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.dao.fn;
+package org.onap.portal.service.menu;
 
 import org.onap.portal.domain.db.fn.FnMenu;
 import org.springframework.data.jpa.repository.JpaRepository;
@@ -47,6 +47,6 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Repository
 @Transactional
-public interface FnMenuDao extends JpaRepository<FnMenu, Integer> {
+interface FnMenuDao extends JpaRepository<FnMenu, Integer> {
 
 }
diff --git a/portal-BE/src/main/java/org/onap/portal/service/menu/FnMenuService.java b/portal-BE/src/main/java/org/onap/portal/service/menu/FnMenuService.java
new file mode 100644 (file)
index 0000000..ad7a34b
--- /dev/null
@@ -0,0 +1,22 @@
+package org.onap.portal.service.menu;
+
+import org.onap.portal.domain.db.fn.FnMenu;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class FnMenuService {
+
+    private final FnMenuDao fnMenuDao;
+
+    @Autowired
+    public FnMenuService(FnMenuDao fnMenuDao) {
+        this.fnMenuDao = fnMenuDao;
+    }
+
+    public List<FnMenu> saveAll(List<FnMenu> fnMenus) {
+        return fnMenuDao.saveAll(fnMenus);
+    }
+}
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.dao.fn;
+package org.onap.portal.service.menuFunctional;
 
 import java.util.List;
 import org.onap.portal.domain.db.fn.FnMenuFunctional;
@@ -50,7 +50,7 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Transactional
 @Repository
-public interface FnMenuFunctionalDao extends JpaRepository<FnMenuFunctional, Long> {
+interface FnMenuFunctionalDao extends JpaRepository<FnMenuFunctional, Long> {
   @Query
   List<FnMenuFunctional> retrieveByMenuId(final @Param("menuId") Long menuId);
 }
  *
  */
 
-package org.onap.portal.service.fn;
+package org.onap.portal.service.menuFunctional;
 
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Optional;
-import org.onap.portal.dao.fn.FnMenuFunctionalDao;
+
 import org.onap.portal.domain.db.fn.FnMenuFunctional;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -62,4 +62,7 @@ public class FnMenuFunctionalService {
     return Optional.of(fnMenuFunctionalDao.retrieveByMenuId(menuId)).orElse(new ArrayList<>());
   }
 
+  public List<FnMenuFunctional> saveAll(List<FnMenuFunctional> menuFunctionals) {
+    return fnMenuFunctionalDao.saveAll(menuFunctionals);
+  }
 }
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.dao.fn;
+package org.onap.portal.service.menuFunctionalAncestors;
 
 import org.onap.portal.domain.db.fn.FnMenuFunctionalAncestors;
 import org.springframework.data.jpa.repository.JpaRepository;
@@ -47,6 +47,6 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Transactional
 @Repository
-public interface FnMenuFunctionalAncestorsDao extends JpaRepository<FnMenuFunctionalAncestors, Integer> {
+interface FnMenuFunctionalAncestorsDao extends JpaRepository<FnMenuFunctionalAncestors, Integer> {
 
 }
diff --git a/portal-BE/src/main/java/org/onap/portal/service/menuFunctionalAncestors/FnMenuFunctionalAncestorsService.java b/portal-BE/src/main/java/org/onap/portal/service/menuFunctionalAncestors/FnMenuFunctionalAncestorsService.java
new file mode 100644 (file)
index 0000000..070169f
--- /dev/null
@@ -0,0 +1,22 @@
+package org.onap.portal.service.menuFunctionalAncestors;
+
+import org.onap.portal.domain.db.fn.FnMenuFunctionalAncestors;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class FnMenuFunctionalAncestorsService {
+
+    private final FnMenuFunctionalAncestorsDao fnMenuFunctionalAncestorsDao;
+
+    @Autowired
+    public FnMenuFunctionalAncestorsService(FnMenuFunctionalAncestorsDao fnMenuFunctionalAncestorsDao) {
+        this.fnMenuFunctionalAncestorsDao = fnMenuFunctionalAncestorsDao;
+    }
+
+    public List<FnMenuFunctionalAncestors> saveAll(List<FnMenuFunctionalAncestors> ancestors) {
+        return fnMenuFunctionalAncestorsDao.saveAll(ancestors);
+    }
+}
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.dao.fn;
+package org.onap.portal.service.menuFunctionalRoles;
 
 import java.util.List;
 import org.onap.portal.domain.db.fn.FnMenuFunctionalRoles;
@@ -50,7 +50,7 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Transactional
 @Repository
-public interface FnMenuFunctionalRolesDao extends JpaRepository<FnMenuFunctionalRoles, Long> {
+interface FnMenuFunctionalRolesDao extends JpaRepository<FnMenuFunctionalRoles, Long> {
 
   @Query
   List<FnMenuFunctionalRoles> retrieveByRoleId(final @Param("roleId") Long roleId);
  *
  */
 
-package org.onap.portal.service.fn;
+package org.onap.portal.service.menuFunctionalRoles;
 
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Optional;
-import org.onap.portal.dao.fn.FnMenuFunctionalRolesDao;
+
 import org.onap.portal.domain.db.fn.FnMenuFunctionalRoles;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -73,4 +73,7 @@ public class FnMenuFunctionalRolesService {
     return Optional.of(fnMenuFunctionalRolesDao.retrieveByMenuId(menuId)).orElse(new ArrayList<>());
   }
 
+  public List<FnMenuFunctionalRoles> saveAll(List<FnMenuFunctionalRoles> functionalRoles) {
+    return fnMenuFunctionalRolesDao.saveAll(functionalRoles);
+  }
 }
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.dao.ep;
+package org.onap.portal.service.microservice;
 
 import org.onap.portal.domain.db.ep.EpMicroservice;
 import org.springframework.data.jpa.repository.JpaRepository;
@@ -47,6 +47,6 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Transactional
 @Repository
-public interface EpMicroserviceDao extends JpaRepository<EpMicroservice, Long> {
+interface EpMicroserviceDao extends JpaRepository<EpMicroservice, Long> {
 
 }
diff --git a/portal-BE/src/main/java/org/onap/portal/service/microservice/EpMicroserviceService.java b/portal-BE/src/main/java/org/onap/portal/service/microservice/EpMicroserviceService.java
new file mode 100644 (file)
index 0000000..1b999f8
--- /dev/null
@@ -0,0 +1,22 @@
+package org.onap.portal.service.microservice;
+
+import org.onap.portal.domain.db.ep.EpMicroservice;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class EpMicroserviceService {
+
+    private final EpMicroserviceDao epMicroserviceDao;
+
+    @Autowired
+    public EpMicroserviceService(EpMicroserviceDao epMicroserviceDao) {
+        this.epMicroserviceDao = epMicroserviceDao;
+    }
+
+    public List<EpMicroservice> saveAll(List<EpMicroservice> epMicroservices) {
+        return epMicroserviceDao.saveAll(epMicroservices);
+    }
+}
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.dao.ep;
+package org.onap.portal.service.microserviceParameter;
 
 import java.util.List;
 import org.onap.portal.domain.db.ep.EpMicroserviceParameter;
@@ -50,7 +50,7 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Repository
 @Transactional
-public interface EpMicroserviceParameterDao extends JpaRepository<EpMicroserviceParameter, Long> {
+interface EpMicroserviceParameterDao extends JpaRepository<EpMicroserviceParameter, Long> {
 
        @Query
        void deleteByServiceId(@Param("SERVICEID") Long userId);
  *
  */
 
-package org.onap.portal.service.ep;
+package org.onap.portal.service.microserviceParameter;
 
 import java.util.ArrayList;
 import java.util.List;
 import java.util.stream.Collectors;
 import org.hibernate.criterion.Criterion;
 import org.hibernate.criterion.Restrictions;
-import org.onap.portal.dao.ep.EpMicroserviceParameterDao;
 import org.onap.portal.domain.db.ep.EpMicroserviceParameter;
 import org.onap.portal.domain.dto.ecomp.MicroserviceParameter;
+import org.onap.portal.service.widgetCatalogParameter.EpWidgetCatalogParameterService;
 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -101,4 +101,8 @@ public class EpMicroserviceParameterService {
                      return false;
               }
        }
+
+       public List<EpMicroserviceParameter> saveAll(List<EpMicroserviceParameter> epMicroserviceParameters) {
+              return epMicroserviceParameterDao.saveAll(epMicroserviceParameters);
+       }
 }
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.dao.fn;
+package org.onap.portal.service.persUserAppSel;
 
 import org.onap.portal.domain.db.fn.FnPersUserAppSel;
 import org.springframework.data.jpa.repository.JpaRepository;
@@ -47,6 +47,6 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Repository
 @Transactional
-public interface FnPersUserAppSelDao extends JpaRepository<FnPersUserAppSel, Long> {
+interface FnPersUserAppSelDao extends JpaRepository<FnPersUserAppSel, Long> {
 
 }
diff --git a/portal-BE/src/main/java/org/onap/portal/service/persUserAppSel/FnPersUserAppSelService.java b/portal-BE/src/main/java/org/onap/portal/service/persUserAppSel/FnPersUserAppSelService.java
new file mode 100644 (file)
index 0000000..41c281d
--- /dev/null
@@ -0,0 +1,22 @@
+package org.onap.portal.service.persUserAppSel;
+
+import org.onap.portal.domain.db.fn.FnPersUserAppSel;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class FnPersUserAppSelService {
+
+    private final FnPersUserAppSelDao fnPersUserAppSelDao;
+
+    @Autowired
+    public FnPersUserAppSelService(FnPersUserAppSelDao fnPersUserAppSelDao) {
+        this.fnPersUserAppSelDao = fnPersUserAppSelDao;
+    }
+
+    public List<FnPersUserAppSel> saveAll(List<FnPersUserAppSel> appSels) {
+        return fnPersUserAppSelDao.saveAll(appSels);
+    }
+}
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.dao.ep;
+package org.onap.portal.service.persUserAppSort;
 
 import org.onap.portal.domain.db.ep.EpPersUserAppSort;
 import org.springframework.data.jpa.repository.JpaRepository;
@@ -47,6 +47,6 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Repository
 @Transactional
-public interface EpPersUserAppSortDao extends JpaRepository<EpPersUserAppSort, Long> {
+interface EpPersUserAppSortDao extends JpaRepository<EpPersUserAppSort, Long> {
 
 }
diff --git a/portal-BE/src/main/java/org/onap/portal/service/persUserAppSort/EpPersUserAppSortService.java b/portal-BE/src/main/java/org/onap/portal/service/persUserAppSort/EpPersUserAppSortService.java
new file mode 100644 (file)
index 0000000..05d32e6
--- /dev/null
@@ -0,0 +1,20 @@
+package org.onap.portal.service.persUserAppSort;
+
+import org.onap.portal.domain.db.ep.EpPersUserAppSort;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class EpPersUserAppSortService {
+
+    private final EpPersUserAppSortDao epPersUserAppSortDao;
+
+    @Autowired
+    public EpPersUserAppSortService(EpPersUserAppSortDao epPersUserAppSortDao) {
+        this.epPersUserAppSortDao = epPersUserAppSortDao;
+    }
+
+    public EpPersUserAppSort save(EpPersUserAppSort appSort) {
+        return epPersUserAppSortDao.save(appSort);
+    }
+}
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.dao.ep;
+package org.onap.portal.service.persUserWidgetSel;
 
 import java.util.List;
 import java.util.Optional;
@@ -51,7 +51,7 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Repository
 @Transactional
-public interface EpPersUserWidgetSelDao extends JpaRepository<EpPersUserWidgetSel, Long> {
+interface EpPersUserWidgetSelDao extends JpaRepository<EpPersUserWidgetSel, Long> {
 
        @Query
        Optional<List<EpPersUserWidgetSel>> getEpPersUserWidgetSelForUserIdAndWidgetId(@Param("USERID") Long userId, @Param("WIDGETID") Long widgetId);
diff --git a/portal-BE/src/main/java/org/onap/portal/service/persUserWidgetSel/EpPersUserWidgetSelService.java b/portal-BE/src/main/java/org/onap/portal/service/persUserWidgetSel/EpPersUserWidgetSelService.java
new file mode 100644 (file)
index 0000000..cd940d1
--- /dev/null
@@ -0,0 +1,32 @@
+package org.onap.portal.service.persUserWidgetSel;
+
+import org.onap.portal.domain.db.ep.EpPersUserWidgetSel;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+@Service
+public class EpPersUserWidgetSelService {
+
+    private final EpPersUserWidgetSelDao epPersUserWidgetSelDao;
+
+    @Autowired
+    public EpPersUserWidgetSelService(EpPersUserWidgetSelDao epPersUserWidgetSelDao) {
+        this.epPersUserWidgetSelDao = epPersUserWidgetSelDao;
+    }
+
+    public void deleteById(Long id) {
+        epPersUserWidgetSelDao.deleteById(id);
+    }
+
+    public EpPersUserWidgetSel saveAndFlush(EpPersUserWidgetSel epPersUserWidgetSel) {
+        return epPersUserWidgetSelDao.saveAndFlush(epPersUserWidgetSel);
+    }
+
+    public Optional<List<EpPersUserWidgetSel>> getEpPersUserWidgetSelForUserIdAndWidgetId(Long id, Long widgetId) {
+        return epPersUserWidgetSelDao.getEpPersUserWidgetSelForUserIdAndWidgetId(id, widgetId);
+    }
+}
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.dao.fn;
+package org.onap.portal.service.qzCronTriggers;
 
 import org.onap.portal.domain.db.fn.FnQzCronTriggers;
 import org.onap.portal.domain.db.fn.compositePK.FnQzTriggersId;
@@ -48,6 +48,6 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Repository
 @Transactional
-public interface FnQzCronTriggersDao extends JpaRepository<FnQzCronTriggers, FnQzTriggersId> {
+interface FnQzCronTriggersDao extends JpaRepository<FnQzCronTriggers, FnQzTriggersId> {
 
 }
diff --git a/portal-BE/src/main/java/org/onap/portal/service/qzCronTriggers/FnQzCronTriggersService.java b/portal-BE/src/main/java/org/onap/portal/service/qzCronTriggers/FnQzCronTriggersService.java
new file mode 100644 (file)
index 0000000..8cfdef2
--- /dev/null
@@ -0,0 +1,15 @@
+package org.onap.portal.service.qzCronTriggers;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class FnQzCronTriggersService {
+
+    private final FnQzCronTriggersDao fnQzCronTriggersDao;
+
+    @Autowired
+    public FnQzCronTriggersService(FnQzCronTriggersDao fnQzCronTriggersDao) {
+        this.fnQzCronTriggersDao = fnQzCronTriggersDao;
+    }
+}
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.dao.fn;
+package org.onap.portal.service.qzJobDetails;
 
 import org.onap.portal.domain.db.fn.FnQzJobDetails;
 import org.onap.portal.domain.db.fn.FnQzJobDetails.FnQzJobDetailsID;
@@ -48,6 +48,6 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Repository
 @Transactional
-public interface FnQzJobDetailsDao extends JpaRepository<FnQzJobDetails, FnQzJobDetailsID> {
+interface FnQzJobDetailsDao extends JpaRepository<FnQzJobDetails, FnQzJobDetailsID> {
 
 }
diff --git a/portal-BE/src/main/java/org/onap/portal/service/qzJobDetails/FnQzJobDetailsService.java b/portal-BE/src/main/java/org/onap/portal/service/qzJobDetails/FnQzJobDetailsService.java
new file mode 100644 (file)
index 0000000..f83f8e7
--- /dev/null
@@ -0,0 +1,22 @@
+package org.onap.portal.service.qzJobDetails;
+
+import org.onap.portal.domain.db.fn.FnQzJobDetails;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class FnQzJobDetailsService {
+
+    private final FnQzJobDetailsDao fnQzJobDetailsDao;
+
+    @Autowired
+    public FnQzJobDetailsService(FnQzJobDetailsDao fnQzJobDetailsDao) {
+        this.fnQzJobDetailsDao = fnQzJobDetailsDao;
+    }
+
+    public List<FnQzJobDetails> saveAll(List<FnQzJobDetails> jobDetails) {
+        return fnQzJobDetailsDao.saveAll(jobDetails);
+    }
+}
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.dao.fn;
+package org.onap.portal.service.qzLocks;
 
 import org.onap.portal.domain.db.fn.FnQzLocks;
 import org.onap.portal.domain.db.fn.FnQzLocks.FnQzLocksID;
@@ -48,6 +48,6 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Repository
 @Transactional
-public interface FnQzLocksDao extends JpaRepository<FnQzLocks, FnQzLocksID> {
+interface FnQzLocksDao extends JpaRepository<FnQzLocks, FnQzLocksID> {
 
 }
diff --git a/portal-BE/src/main/java/org/onap/portal/service/qzLocks/FnQzLocksService.java b/portal-BE/src/main/java/org/onap/portal/service/qzLocks/FnQzLocksService.java
new file mode 100644 (file)
index 0000000..a582f6d
--- /dev/null
@@ -0,0 +1,22 @@
+package org.onap.portal.service.qzLocks;
+
+import org.onap.portal.domain.db.fn.FnQzLocks;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class FnQzLocksService {
+
+    private final FnQzLocksDao fnQzLocksDao;
+
+    @Autowired
+    public FnQzLocksService(FnQzLocksDao fnQzLocksDao) {
+        this.fnQzLocksDao = fnQzLocksDao;
+    }
+
+    public List<FnQzLocks> saveAll(List<FnQzLocks> locks) {
+        return fnQzLocksDao.saveAll(locks);
+    }
+}
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.dao.fn;
+package org.onap.portal.service.qzSchedulerState;
 
 import org.onap.portal.domain.db.fn.FnQzSchedulerState;
 import org.onap.portal.domain.db.fn.FnQzSchedulerState.FnQzSchedulerStateID;
@@ -48,6 +48,6 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Repository
 @Transactional
-public interface FnQzSchedulerStateDao extends JpaRepository<FnQzSchedulerState, FnQzSchedulerStateID> {
+interface FnQzSchedulerStateDao extends JpaRepository<FnQzSchedulerState, FnQzSchedulerStateID> {
 
 }
diff --git a/portal-BE/src/main/java/org/onap/portal/service/qzSchedulerState/FnQzSchedulerStateService.java b/portal-BE/src/main/java/org/onap/portal/service/qzSchedulerState/FnQzSchedulerStateService.java
new file mode 100644 (file)
index 0000000..5451979
--- /dev/null
@@ -0,0 +1,20 @@
+package org.onap.portal.service.qzSchedulerState;
+
+import org.onap.portal.domain.db.fn.FnQzSchedulerState;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class FnQzSchedulerStateService {
+
+    private final FnQzSchedulerStateDao fnQzSchedulerStateDao;
+
+    @Autowired
+    public FnQzSchedulerStateService(FnQzSchedulerStateDao fnQzSchedulerStateDao) {
+        this.fnQzSchedulerStateDao = fnQzSchedulerStateDao;
+    }
+
+    public FnQzSchedulerState save(FnQzSchedulerState schedulerState) {
+        return fnQzSchedulerStateDao.save(schedulerState);
+    }
+}
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.dao.fn;
+package org.onap.portal.service.qzTriggers;
 
 import org.onap.portal.domain.db.fn.FnQzTriggers;
 import org.onap.portal.domain.db.fn.compositePK.FnQzTriggersId;
@@ -48,6 +48,6 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Repository
 @Transactional
-public interface FnQzTriggersDao extends JpaRepository<FnQzTriggers, FnQzTriggersId> {
+interface FnQzTriggersDao extends JpaRepository<FnQzTriggers, FnQzTriggersId> {
 
 }
diff --git a/portal-BE/src/main/java/org/onap/portal/service/qzTriggers/FnQzTriggersService.java b/portal-BE/src/main/java/org/onap/portal/service/qzTriggers/FnQzTriggersService.java
new file mode 100644 (file)
index 0000000..4f175af
--- /dev/null
@@ -0,0 +1,15 @@
+package org.onap.portal.service.qzTriggers;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class FnQzTriggersService {
+
+    private final FnQzTriggersDao fnQzTriggersDao;
+
+    @Autowired
+    public FnQzTriggersService(FnQzTriggersDao fnQzTriggersDao) {
+        this.fnQzTriggersDao = fnQzTriggersDao;
+    }
+}
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.dao.fn;
+package org.onap.portal.service.restrictedUrl;
 
 import org.onap.portal.domain.db.fn.FnRestrictedUrl;
 import org.onap.portal.domain.db.fn.FnRestrictedUrl.FnRestrictedUrlId;
@@ -48,6 +48,5 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Repository
 @Transactional
-public interface FnRestrictedUrlDao extends JpaRepository<FnRestrictedUrl, FnRestrictedUrlId> {
-
+interface FnRestrictedUrlDao extends JpaRepository<FnRestrictedUrl, FnRestrictedUrlId> {
 }
diff --git a/portal-BE/src/main/java/org/onap/portal/service/restrictedUrl/FnRestrictedUrlService.java b/portal-BE/src/main/java/org/onap/portal/service/restrictedUrl/FnRestrictedUrlService.java
new file mode 100644 (file)
index 0000000..8f04dbf
--- /dev/null
@@ -0,0 +1,15 @@
+package org.onap.portal.service.restrictedUrl;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class FnRestrictedUrlService {
+
+    private final FnRestrictedUrlDao fnRestrictedUrlDao;
+
+    @Autowired
+    public FnRestrictedUrlService(FnRestrictedUrlDao fnRestrictedUrlDao) {
+        this.fnRestrictedUrlDao = fnRestrictedUrlDao;
+    }
+}
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.dao.fn;
+package org.onap.portal.service.role;
 
 import java.util.List;
 import org.onap.portal.domain.db.fn.FnRole;
@@ -50,7 +50,7 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Repository
 @Transactional
-public interface FnRoleDao extends JpaRepository<FnRole, Long> {
+interface FnRoleDao extends JpaRepository<FnRole, Long> {
 
   @Query
   List<FnRole> retrieveAppRoleByAppRoleIdAndByAppId(final @Param("appId") Long appId,
  *
  */
 
-package org.onap.portal.service.fn;
+package org.onap.portal.service.role;
 
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Optional;
 import javax.persistence.EntityExistsException;
-import org.onap.portal.dao.fn.FnRoleDao;
+
 import org.onap.portal.domain.db.fn.FnRole;
 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -57,7 +57,6 @@ public class FnRoleService {
 
   private final EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(FnRoleService.class);
 
-
   private final FnRoleDao fnRoleDao;
 
   @Autowired
@@ -149,4 +148,8 @@ public class FnRoleService {
   public FnRole saveOne(final FnRole role){
     return fnRoleDao.save(role);
   }
+
+  public List<FnRole> saveAll(List<FnRole> fnRoles) {
+    return fnRoleDao.saveAll(fnRoles);
+  }
 }
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.dao.fn;
+package org.onap.portal.service.roleComposite;
 
 import org.onap.portal.domain.db.fn.FnRoleComposite;
 import org.onap.portal.domain.db.fn.compositePK.FnRoleCompositeId;
@@ -48,6 +48,6 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Repository
 @Transactional
-public interface FnRoleCompositeDao extends JpaRepository<FnRoleComposite, FnRoleCompositeId> {
+interface FnRoleCompositeDao extends JpaRepository<FnRoleComposite, FnRoleCompositeId> {
 
 }
diff --git a/portal-BE/src/main/java/org/onap/portal/service/roleComposite/FnRoleCompositeService.java b/portal-BE/src/main/java/org/onap/portal/service/roleComposite/FnRoleCompositeService.java
new file mode 100644 (file)
index 0000000..ed15259
--- /dev/null
@@ -0,0 +1,15 @@
+package org.onap.portal.service.roleComposite;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class FnRoleCompositeService {
+
+    private final FnRoleCompositeDao fnRoleCompositeDao;
+
+    @Autowired
+    public FnRoleCompositeService(FnRoleCompositeDao fnRoleCompositeDao) {
+        this.fnRoleCompositeDao = fnRoleCompositeDao;
+    }
+}
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.dao.fn;
+package org.onap.portal.service.roleFunction;
 
 import org.onap.portal.domain.db.fn.FnRoleFunction;
 import org.springframework.data.jpa.repository.JpaRepository;
@@ -47,6 +47,6 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Transactional
 @Repository
-public interface FnRoleFunctionDao extends JpaRepository<FnRoleFunction, Long> {
+interface FnRoleFunctionDao extends JpaRepository<FnRoleFunction, Long> {
 
 }
diff --git a/portal-BE/src/main/java/org/onap/portal/service/roleFunction/FnRoleFunctionService.java b/portal-BE/src/main/java/org/onap/portal/service/roleFunction/FnRoleFunctionService.java
new file mode 100644 (file)
index 0000000..a91dee8
--- /dev/null
@@ -0,0 +1,22 @@
+package org.onap.portal.service.roleFunction;
+
+import org.onap.portal.domain.db.fn.FnRoleFunction;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class FnRoleFunctionService {
+
+    private final FnRoleFunctionDao fnRoleFunctionDao;
+
+    @Autowired
+    public FnRoleFunctionService(FnRoleFunctionDao fnRoleFunctionDao) {
+        this.fnRoleFunctionDao = fnRoleFunctionDao;
+    }
+
+    public List<FnRoleFunction> saveAll(List<FnRoleFunction> roleFunctions) {
+        return fnRoleFunctionDao.saveAll(roleFunctions);
+    }
+}
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.dao.fn;
+package org.onap.portal.service.sharedContext;
 
 import org.onap.portal.domain.db.fn.FnSharedContext;
 import org.springframework.data.jpa.repository.JpaRepository;
@@ -47,6 +47,6 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Repository
 @Transactional
-public interface FnSharedContextDao extends JpaRepository<FnSharedContext, Long> {
+interface FnSharedContextDao extends JpaRepository<FnSharedContext, Long> {
 
 }
diff --git a/portal-BE/src/main/java/org/onap/portal/service/sharedContext/FnSharedContextService.java b/portal-BE/src/main/java/org/onap/portal/service/sharedContext/FnSharedContextService.java
new file mode 100644 (file)
index 0000000..7a427ae
--- /dev/null
@@ -0,0 +1,22 @@
+package org.onap.portal.service.sharedContext;
+
+import org.onap.portal.domain.db.fn.FnSharedContext;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class FnSharedContextService {
+
+    private final FnSharedContextDao fnSharedContextDao;
+
+    @Autowired
+    public FnSharedContextService(FnSharedContextDao fnSharedContextDao) {
+        this.fnSharedContextDao = fnSharedContextDao;
+    }
+
+    public List<FnSharedContext> saveAll(List<FnSharedContext> sharedContexts) {
+        return fnSharedContextDao.saveAll(sharedContexts);
+    }
+}
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.dao.fn;
+package org.onap.portal.service.tab;
 
 import org.onap.portal.domain.db.fn.FnTab;
 import org.springframework.data.jpa.repository.JpaRepository;
@@ -47,6 +47,6 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Repository
 @Transactional
-public interface FnTabDao extends JpaRepository<FnTab, String> {
+interface FnTabDao extends JpaRepository<FnTab, String> {
 
 }
diff --git a/portal-BE/src/main/java/org/onap/portal/service/tab/FnTabService.java b/portal-BE/src/main/java/org/onap/portal/service/tab/FnTabService.java
new file mode 100644 (file)
index 0000000..ed90831
--- /dev/null
@@ -0,0 +1,22 @@
+package org.onap.portal.service.tab;
+
+import org.onap.portal.domain.db.fn.FnTab;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class FnTabService {
+
+    private final FnTabDao fnTabDao;
+
+    @Autowired
+    public FnTabService(FnTabDao fnTabDao) {
+        this.fnTabDao = fnTabDao;
+    }
+
+    public List<FnTab> saveAll(List<FnTab> fnTabs) {
+        return fnTabDao.saveAll(fnTabs);
+    }
+}
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.dao.fn;
+package org.onap.portal.service.tabSelected;
 
 import org.onap.portal.domain.db.fn.FnTabSelected;
 import org.onap.portal.domain.db.fn.FnTabSelected.FnTabSelectedId;
@@ -48,6 +48,6 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Repository
 @Transactional
-public interface FnTabSelectedDao extends JpaRepository<FnTabSelected, FnTabSelectedId> {
+interface FnTabSelectedDao extends JpaRepository<FnTabSelected, FnTabSelectedId> {
 
 }
diff --git a/portal-BE/src/main/java/org/onap/portal/service/tabSelected/FnTabSelectedService.java b/portal-BE/src/main/java/org/onap/portal/service/tabSelected/FnTabSelectedService.java
new file mode 100644 (file)
index 0000000..92c6f56
--- /dev/null
@@ -0,0 +1,15 @@
+package org.onap.portal.service.tabSelected;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class FnTabSelectedService {
+
+    private final FnTabSelectedDao fnTabSelectedDao;
+
+    @Autowired
+    public FnTabSelectedService(FnTabSelectedDao fnTabSelectedDao) {
+        this.fnTabSelectedDao = fnTabSelectedDao;
+    }
+}
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.dao.fn;
+package org.onap.portal.service.user;
 
 import java.util.List;
 import java.util.Optional;
@@ -51,7 +51,7 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Repository
 @Transactional
-public interface FnUserDao extends JpaRepository<FnUser, Long> {
+interface FnUserDao extends JpaRepository<FnUser, Long> {
 
        @Query
        Optional<FnUser> findByLoginId(final @Param("loginId") String username);
  *
  */
 
-package org.onap.portal.service.fn;
+package org.onap.portal.service.user;
 
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Optional;
-import org.onap.portal.dao.fn.FnUserDao;
+
 import org.onap.portal.domain.db.fn.FnUser;
 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -89,12 +89,12 @@ public class FnUserService implements UserDetailsService {
               return fnUserDao.getUserWithOrgUserId(orgUserIdValue).orElse(new ArrayList<>());
        }
 
-       List<FnUser> getUsersByOrgIds(final List<String> orgIds) {
+       public List<FnUser> getUsersByOrgIds(final List<String> orgIds) {
               return fnUserDao.getUsersByOrgIds(orgIds).orElse(new ArrayList<>());
        }
 
 
-       List<FnUser> getActiveUsers() {
+       public List<FnUser> getActiveUsers() {
               return fnUserDao.getActiveUsers().orElse(new ArrayList<>());
        }
 
@@ -109,4 +109,16 @@ public class FnUserService implements UserDetailsService {
        public List<FnUser> findAll() {
               return fnUserDao.findAll();
        }
-       }
\ No newline at end of file
+
+       public List<FnUser> saveAll(List<FnUser> fnUsers) {
+              return fnUserDao.saveAll(fnUsers);
+       }
+
+       public FnUser save(FnUser user) {
+              return fnUserDao.save(user);
+       }
+
+       public void delete(FnUser user) {
+              fnUserDao.delete(user);
+       }
+}
\ No newline at end of file
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.dao.fn;
+package org.onap.portal.service.userRole;
 
 import java.util.List;
 import java.util.Optional;
@@ -52,7 +52,7 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Repository
 @Transactional
-public interface FnUserRoleDao extends JpaRepository<FnUserRole, Long> {
+interface FnUserRoleDao extends JpaRepository<FnUserRole, Long> {
 
        @Query
        Optional<List<FnUserRole>> getAdminUserRoles(final @Param("userId") Long userId, final @Param("roleId") Long roleId, final @Param("appId") Long appId);
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.service.fn;
+package org.onap.portal.service.userRole;
 
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.DeserializationFeature;
@@ -58,7 +58,6 @@ import javax.persistence.EntityManager;
 import javax.persistence.Tuple;
 import javax.servlet.http.HttpServletResponse;
 import org.apache.cxf.transport.http.HTTPException;
-import org.onap.portal.dao.fn.FnUserRoleDao;
 import org.onap.portal.domain.db.ep.EpUserRolesRequest;
 import org.onap.portal.domain.db.ep.EpUserRolesRequestDet;
 import org.onap.portal.domain.db.fn.FnApp;
@@ -75,9 +74,11 @@ import org.onap.portal.domain.dto.transport.Role;
 import org.onap.portal.domain.dto.transport.RoleInAppForUser;
 import org.onap.portal.domain.dto.transport.UserApplicationRoles;
 import org.onap.portal.service.ApplicationsRestClientService;
-import org.onap.portal.service.ep.EpAppFunctionService;
-import org.onap.portal.service.ep.EpUserRolesRequestDetService;
-import org.onap.portal.service.ep.EpUserRolesRequestService;
+import org.onap.portal.service.userRolesRequestDet.EpUserRolesRequestDetService;
+import org.onap.portal.service.userRolesRequest.EpUserRolesRequestService;
+import org.onap.portal.service.app.FnAppService;
+import org.onap.portal.service.role.FnRoleService;
+import org.onap.portal.service.user.FnUserService;
 import org.onap.portal.utils.EPCommonSystemProperties;
 import org.onap.portal.utils.PortalConstants;
 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
@@ -536,4 +537,8 @@ public class FnUserRoleService {
     }
     return rolesInAppForUser;
   }
+
+  public List<FnUserRole> saveAll(List<FnUserRole> userRoles) {
+    return fnUserRoleDao.saveAll(userRoles);
+  }
 }
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.dao.ep;
+package org.onap.portal.service.userRolesRequest;
 
 import java.util.List;
 import org.onap.portal.domain.db.ep.EpUserRolesRequest;
@@ -50,7 +50,7 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Repository
 @Transactional
-public interface EpUserRolesRequestDao extends JpaRepository<EpUserRolesRequest, Long> {
+interface EpUserRolesRequestDao extends JpaRepository<EpUserRolesRequest, Long> {
   @Query
   List<EpUserRolesRequest> userAppRolesRequestList(final @Param("userId") Long userId, final @Param("appId") Long appId);
 }
  *
  */
 
-package org.onap.portal.service.ep;
+package org.onap.portal.service.userRolesRequest;
 
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Optional;
-import org.onap.portal.dao.ep.EpUserRolesRequestDao;
+
 import org.onap.portal.domain.db.ep.EpUserRolesRequest;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.dao.ep;
+package org.onap.portal.service.userRolesRequestDet;
 
 import java.util.List;
 import org.onap.portal.domain.db.ep.EpUserRolesRequestDet;
@@ -50,7 +50,7 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Repository
 @Transactional
-public interface EpUserRolesRequestDetDao extends JpaRepository<EpUserRolesRequestDet, Long> {
+interface EpUserRolesRequestDetDao extends JpaRepository<EpUserRolesRequestDet, Long> {
 
   @Query
   List<EpUserRolesRequestDet> appRolesRequestDetailList(final @Param("reqId") Long reqId);
  *
  */
 
-package org.onap.portal.service.ep;
+package org.onap.portal.service.userRolesRequestDet;
 
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Optional;
-import org.onap.portal.dao.ep.EpUserRolesRequestDetDao;
 import org.onap.portal.domain.db.ep.EpUserRolesRequestDet;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -38,7 +38,7 @@
  *
  */
 
-package org.onap.portal.dao.fn;
+package org.onap.portal.service.widget;
 
 import java.util.List;
 import java.util.Optional;
@@ -51,7 +51,7 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Repository
 @Transactional
-public interface FnWidgetDao extends JpaRepository<FnWidget, Long> {
+interface FnWidgetDao extends JpaRepository<FnWidget, Long> {
 
        @Query
        Optional<List<FnWidget>> getForUrlNameAndAppId(final @Param("URL") String url, final @Param("NAME") String name, final @Param("APPID") Long appId);
  *
  */
 
-package org.onap.portal.service;
+package org.onap.portal.service.widget;
 
 import java.util.ArrayList;
 import java.util.List;
 import javax.persistence.EntityManager;
 import javax.servlet.http.HttpServletResponse;
-import org.onap.portal.dao.fn.FnWidgetDao;
+
 import org.onap.portal.domain.db.fn.FnUser;
 import org.onap.portal.domain.db.fn.FnUserRole;
 import org.onap.portal.domain.db.fn.FnWidget;
 import org.onap.portal.domain.dto.transport.FieldsValidator;
 import org.onap.portal.domain.dto.transport.OnboardingWidget;
-import org.onap.portal.service.fn.FnUserRoleService;
+import org.onap.portal.service.AdminRolesService;
+import org.onap.portal.service.userRole.FnUserRoleService;
 import org.onap.portal.utils.EPCommonSystemProperties;
 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
 import org.springframework.beans.factory.annotation.Autowired;
  *
  */
 
-package org.onap.portal.dao.fn;
+package org.onap.portal.service.widgetCatalog;
 
 import org.onap.portal.domain.db.ep.EpWidgetCatalog;
 import org.springframework.data.jpa.repository.JpaRepository;
 
-public interface EpWidgetCatalogDao extends JpaRepository<EpWidgetCatalog, Long> {
+interface EpWidgetCatalogDao extends JpaRepository<EpWidgetCatalog, Long> {
 
 }
@@ -1,10 +1,12 @@
-package org.onap.portal.service.ep;
+package org.onap.portal.service.widgetCatalog;
 
-import org.onap.portal.dao.fn.EpWidgetCatalogDao;
 import org.onap.portal.domain.db.ep.EpWidgetCatalog;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.util.List;
+import java.util.Optional;
+
 @Service
 public class EpWidgetCatalogService {
 
@@ -18,4 +20,12 @@ public class EpWidgetCatalogService {
        public EpWidgetCatalog save(final EpWidgetCatalog epWidgetCatalog){
               return epWidgetCatalogDao.save(epWidgetCatalog);
        }
+
+       public Optional<EpWidgetCatalog> findById(Long widgetId) {
+              return epWidgetCatalogDao.findById(widgetId);
+       }
+
+       public List<EpWidgetCatalog> saveAll(List<EpWidgetCatalog> epWidgetCatalogs) {
+              return epWidgetCatalogDao.saveAll(epWidgetCatalogs);
+       }
 }
@@ -1,4 +1,4 @@
-package org.onap.portal.dao.ep;
+package org.onap.portal.service.widgetCatalogParameter;
 
 import java.util.List;
 import java.util.Optional;
@@ -12,7 +12,7 @@ import org.springframework.transaction.annotation.Transactional;
 
 @Repository
 @Transactional
-public interface EpWidgetCatalogParameterDao extends JpaRepository<EpWidgetCatalogParameter, Long> {
+interface EpWidgetCatalogParameterDao extends JpaRepository<EpWidgetCatalogParameter, Long> {
 
        @Query
        Optional<List<EpWidgetCatalogParameter>> retrieveByParamId(@Param("PARAMID") Long paramId);
  *
  */
 
-package org.onap.portal.service.ep;
+package org.onap.portal.service.widgetCatalogParameter;
 
 import java.util.ArrayList;
 import java.util.List;
-import org.onap.portal.dao.ep.EpWidgetCatalogParameterDao;
 import org.onap.portal.domain.db.ep.EpWidgetCatalogParameter;
+import org.onap.portal.service.microserviceParameter.EpMicroserviceParameterService;
 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
index fea7133..027cebe 100644 (file)
@@ -63,7 +63,7 @@ import org.onap.portal.domain.db.fn.FnUser;
 import org.onap.portal.domain.db.fn.FnUserRole;
 import org.onap.portal.domain.dto.transport.Role;
 import org.onap.portal.exception.RoleFunctionException;
-import org.onap.portal.service.fn.old.EPRoleFunctionService;
+import org.onap.portal.service.EPRoleFunctionService;
 import org.onap.portalsdk.core.domain.RoleFunction;
 import org.onap.portalsdk.core.exception.SessionExpiredException;
 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
index e00dc5c..ca0cf92 100644 (file)
@@ -45,13 +45,13 @@ import static org.junit.jupiter.api.Assertions.assertNull;
 
 import org.junit.jupiter.api.Test;
 import org.junit.runner.RunWith;
-import org.onap.portal.dao.fn.FnLanguageDao;
 import org.onap.portal.domain.db.fn.FnLanguage;
 import org.onap.portal.domain.db.fn.FnUser;
 import org.onap.portal.domain.dto.PortalRestResponse;
 import org.onap.portal.domain.dto.PortalRestStatusEnum;
 import org.onap.portal.domain.dto.fn.FnLanguageDto;
-import org.onap.portal.service.fn.FnUserService;
+import org.onap.portal.service.language.FnLanguageService;
+import org.onap.portal.service.user.FnUserService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
@@ -69,7 +69,7 @@ class LanguageControllerTest {
        @Autowired
        private LanguageController languageController;
        @Autowired
-       private FnLanguageDao fnLanguageDao;
+       private FnLanguageService fnLanguageService;
        @Autowired
        private FnUserService fnUserService;
 
@@ -89,7 +89,7 @@ class LanguageControllerTest {
               assertEquals(expected.getMessage(), actual.getMessage());
               assertEquals(expected.getStatus(), actual.getStatus());
               //Clean up
-              fnLanguageDao.delete(fnLanguage);
+              fnLanguageService.delete(fnLanguage);
        }
 
        @Test
@@ -109,7 +109,7 @@ class LanguageControllerTest {
               assertEquals(expected.getMessage(), actual.getMessage());
               assertEquals(expected.getStatus(), actual.getStatus());
               //Clean up
-              fnLanguageDao.delete(fnLanguage);
+              fnLanguageService.delete(fnLanguage);
        }
 
        @Test
@@ -138,7 +138,7 @@ class LanguageControllerTest {
 
 
               //Clean up
-              fnLanguageDao.delete(fnLanguage);
+              fnLanguageService.delete(fnLanguage);
        }
 
        @Test
@@ -162,7 +162,7 @@ class LanguageControllerTest {
 
 
               //Clean up
-              fnLanguageDao.delete(fnLanguage);
+              fnLanguageService.delete(fnLanguage);
        }
 
 
index 0316683..7c654ad 100644 (file)
@@ -47,7 +47,7 @@ import org.onap.portal.domain.db.fn.FnUser;
 import org.onap.portal.domain.dto.PortalRestResponse;
 import org.onap.portal.domain.dto.PortalRestStatusEnum;
 import org.onap.portal.domain.dto.transport.ProfileDetail;
-import org.onap.portal.service.fn.FnUserService;
+import org.onap.portal.service.user.FnUserService;
 import org.onap.portalsdk.core.onboarding.exception.CipherUtilException;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
index e83c247..e9f9627 100644 (file)
@@ -45,11 +45,11 @@ import static org.junit.jupiter.api.Assertions.*;
 import org.junit.jupiter.api.Test;
 import org.junit.runner.RunWith;
 import org.onap.portal.domain.dto.ecomp.ExternalSystemAccess;
-import org.onap.portal.service.fn.FnAppService;
-import org.onap.portal.service.fn.FnLanguageService;
-import org.onap.portal.service.fn.FnRoleService;
-import org.onap.portal.service.fn.FnUserRoleService;
-import org.onap.portal.service.fn.FnUserService;
+import org.onap.portal.service.app.FnAppService;
+import org.onap.portal.service.language.FnLanguageService;
+import org.onap.portal.service.role.FnRoleService;
+import org.onap.portal.service.userRole.FnUserRoleService;
+import org.onap.portal.service.user.FnUserService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
index 27ce348..65525db 100644 (file)
@@ -51,18 +51,17 @@ import java.util.List;
 import javax.transaction.Transactional;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.onap.portal.dao.fn.FnLanguageDao;
 import org.onap.portal.domain.db.ep.EpMicroserviceParameter;
 import org.onap.portal.domain.db.ep.EpWidgetCatalog;
 import org.onap.portal.domain.db.ep.EpWidgetCatalogParameter;
 import org.onap.portal.domain.db.fn.FnLanguage;
 import org.onap.portal.domain.db.fn.FnUser;
 import org.onap.portal.domain.dto.ecomp.WidgetCatalog;
-import org.onap.portal.service.ep.EpMicroserviceParameterService;
-import org.onap.portal.service.ep.EpWidgetCatalogParameterService;
-import org.onap.portal.service.ep.EpWidgetCatalogService;
-import org.onap.portal.service.fn.FnLanguageService;
-import org.onap.portal.service.fn.FnUserService;
+import org.onap.portal.service.microserviceParameter.EpMicroserviceParameterService;
+import org.onap.portal.service.widgetCatalogParameter.EpWidgetCatalogParameterService;
+import org.onap.portal.service.widgetCatalog.EpWidgetCatalogService;
+import org.onap.portal.service.language.FnLanguageService;
+import org.onap.portal.service.user.FnUserService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
@@ -88,8 +87,6 @@ public class WidgetsCatalogControllerTest {
        private EpMicroserviceParameterService epMicroserviceParameterService;
        @Autowired
        private EpWidgetCatalogService epWidgetCatalogService;
-       @Autowired
-       private FnLanguageDao fnLanguageDao;
 
        @Test
        public void getUserWidgetCatalog() {
@@ -172,7 +169,7 @@ public class WidgetsCatalogControllerTest {
               EpMicroserviceParameter parameter = new EpMicroserviceParameter();
               epMicroserviceParameterService.save(parameter);
               FnUser user = buildFnUser();
-              FnLanguage language = fnLanguageDao.getByLanguageAlias("EN");
+              FnLanguage language = fnLanguageService.getByLanguageAlias("EN");
               user.setLanguageId(language);
               fnUserService.saveFnUser(user);
               EpWidgetCatalogParameter data =  EpWidgetCatalogParameter.builder()
index 168fcc7..9da6e73 100644 (file)
@@ -53,8 +53,6 @@ import javax.servlet.http.HttpServletResponse;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.onap.portal.dao.fn.FnLanguageDao;
-import org.onap.portal.dao.fn.FnUserDao;
 import org.onap.portal.domain.db.fn.FnLanguage;
 import org.onap.portal.domain.db.fn.FnUser;
 import org.onap.portal.domain.db.fn.FnWidget;
@@ -62,8 +60,9 @@ import org.onap.portal.domain.dto.transport.FieldsValidator;
 import org.onap.portal.domain.dto.transport.OnboardingWidget;
 import org.onap.portal.domain.dto.transport.WidgetCatalogPersonalization;
 import org.onap.portal.framework.MockitoTestSuite;
-import org.onap.portal.service.WidgetService;
-import org.onap.portal.service.fn.FnLanguageService;
+import org.onap.portal.service.user.FnUserService;
+import org.onap.portal.service.widget.WidgetService;
+import org.onap.portal.service.language.FnLanguageService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
@@ -89,14 +88,11 @@ public class WidgetsControllerTest {
        @Autowired
        private WidgetsController widgetsController;
        @Autowired
-       private FnUserDao fnUserDao;
-       @Autowired
-       private FnLanguageDao fnLanguageDao;
-       @Autowired
        private WidgetService widgetService;
        @Autowired
        private  FnLanguageService fnLanguageService;
-
+       @Autowired
+       FnUserService fnUserService;
        private FnLanguage language;
        private FnUser questUser;
        private FnUser notQuestUser;
@@ -120,14 +116,14 @@ public class WidgetsControllerTest {
        public void getOnboardingWidgetsQuestUserTest() {
               UsernamePasswordAuthenticationToken questPrincipal = new UsernamePasswordAuthenticationToken("questUser",
                       "demo123");
-              fnUserDao.save(questUser);
+              fnUserService.save(questUser);
               List<OnboardingWidget> onboardingWidgets = widgetsController
                       .getOnboardingWidgets(questPrincipal, request, response);
               assertNull(onboardingWidgets);
 
               //Clean up
-              fnUserDao.delete(questUser);
-              fnLanguageDao.delete(language);
+              fnUserService.delete(questUser);
+              fnLanguageService.delete(language);
        }
 
        @Test
@@ -135,7 +131,7 @@ public class WidgetsControllerTest {
               UsernamePasswordAuthenticationToken notQuestprincipal = new UsernamePasswordAuthenticationToken(
                       "notQuestUser",
                       "demo123");
-              fnUserDao.save(notQuestUser);
+              fnUserService.save(notQuestUser);
               List<OnboardingWidget> expected = new ArrayList<>();
               when(request.getHeader("X-Widgets-Type")).thenReturn("managed");
 
@@ -143,7 +139,7 @@ public class WidgetsControllerTest {
                       .getOnboardingWidgets(notQuestprincipal, request, response);
 
               assertEquals(expected, actual);
-              fnUserDao.delete(notQuestUser);
+              fnUserService.delete(notQuestUser);
        }
 
        @Test
@@ -151,19 +147,19 @@ public class WidgetsControllerTest {
               UsernamePasswordAuthenticationToken notQuestprincipal = new UsernamePasswordAuthenticationToken(
                       "notQuestUser",
                       "demo123");
-              fnUserDao.save(notQuestUser);
+              fnUserService.save(notQuestUser);
               when(request.getHeader("X-Widgets-Type")).thenReturn("test");
               List<OnboardingWidget> actual = widgetsController
                       .getOnboardingWidgets(notQuestprincipal, request, response);
 
               assertNull(actual);
-              fnUserDao.delete(notQuestUser);
+              fnUserService.delete(notQuestUser);
        }
 
        @Test
        public void putOnboardingWidgetSameWidget() {
               //Given
-              fnUserDao.save(notQuestUser);
+              fnUserService.save(notQuestUser);
               when(request.getHeader("X-Widgets-Type")).thenReturn("managed");
 
               OnboardingWidget onboardingWidget = OnboardingWidget.builder()
@@ -199,7 +195,7 @@ public class WidgetsControllerTest {
        @Test
        public void putOnboardingWidgetAOP() {
               //Given
-              fnUserDao.save(notQuestUser);
+              fnUserService.save(notQuestUser);
               when(request.getHeader("X-Widgets-Type")).thenReturn("managed");
 
               OnboardingWidget onboardingWidget = OnboardingWidget.builder()
@@ -236,7 +232,7 @@ public class WidgetsControllerTest {
        @Test
        public void putOnboardingWidgetAOPXSSTest() {
               //Given
-              fnUserDao.save(notQuestUser);
+              fnUserService.save(notQuestUser);
               when(request.getHeader("X-Widgets-Type")).thenReturn("managed");
 
               OnboardingWidget onboardingWidget = OnboardingWidget.builder()
@@ -264,7 +260,7 @@ public class WidgetsControllerTest {
        @Test
        public void postOnboardingWidgetXSS() {
               //Given
-              fnUserDao.save(notQuestUser);
+              fnUserService.save(notQuestUser);
               when(request.getHeader("X-Widgets-Type")).thenReturn("managed");
 
               OnboardingWidget onboardingWidget = OnboardingWidget.builder()
@@ -290,7 +286,7 @@ public class WidgetsControllerTest {
        @Test
        public void postOnboardingWidget() {
               //Given
-              fnUserDao.save(notQuestUser);
+              fnUserService.save(notQuestUser);
               when(request.getHeader("X-Widgets-Type")).thenReturn("managed");
 
               OnboardingWidget onboardingWidget = OnboardingWidget.builder()
@@ -315,7 +311,7 @@ public class WidgetsControllerTest {
        @Test
        public void deleteOnboardingWidgetSCFORBIDDEN() {
               //Given
-              fnUserDao.save(notQuestUser);
+              fnUserService.save(notQuestUser);
               when(request.getHeader("X-Widgets-Type")).thenReturn("managed");
 
               OnboardingWidget onboardingWidget = OnboardingWidget.builder()
diff --git a/portal-BE/src/test/java/org/onap/portal/exception/NotValidDataExceptionTest.java b/portal-BE/src/test/java/org/onap/portal/exception/NotValidDataExceptionTest.java
new file mode 100644 (file)
index 0000000..df898f1
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ * Modifications Copyright (c) 2019 IBM
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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============================================
+ *
+ *
+ */
+package org.onap.portal.exception;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+public class NotValidDataExceptionTest {
+
+
+    @Test
+    public void TestException2() {
+        String s1 = "Value1";
+        String s2 = "value2";
+        try {
+            if (!s1.equalsIgnoreCase(s2)) {
+                throw new NotValidDataException("Exception occured..");
+            }
+        } catch (NotValidDataException mde) {
+            assertEquals(mde.getMessage(),"Exception occured..");
+        }
+
+    }
+}
index 1825e40..49c4829 100644 (file)
  */
 package org.onap.portal.framework;
 
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.springframework.test.context.junit4.SpringRunner;
+
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletRequestWrapper;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mockito;
-import org.mockito.runners.MockitoJUnitRunner;
 
-@RunWith(MockitoJUnitRunner.class)
+@RunWith(SpringRunner.class)
 public class MockitoTestSuite {
 
 
index b4427ef..e11a696 100644 (file)
@@ -45,6 +45,7 @@ import static org.junit.jupiter.api.Assertions.*;
 import org.junit.jupiter.api.Test;
 import org.junit.runner.RunWith;
 import org.onap.portal.domain.db.ep.EpMicroserviceParameter;
+import org.onap.portal.service.microserviceParameter.EpMicroserviceParameterService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.test.context.TestPropertySource;
index ad1ee60..7c7b0b7 100644 (file)
@@ -43,19 +43,20 @@ package org.onap.portal.service.ep;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
 import java.time.LocalDateTime;
-import java.util.Collections;
-import java.util.HashSet;
+
 import org.junit.jupiter.api.Test;
 import org.junit.runner.RunWith;
 import org.onap.portal.controller.WidgetsCatalogController;
-import org.onap.portal.dao.fn.FnLanguageDao;
 import org.onap.portal.domain.db.ep.EpMicroserviceParameter;
 import org.onap.portal.domain.db.ep.EpWidgetCatalog;
 import org.onap.portal.domain.db.ep.EpWidgetCatalogParameter;
 import org.onap.portal.domain.db.fn.FnLanguage;
 import org.onap.portal.domain.db.fn.FnUser;
-import org.onap.portal.service.fn.FnLanguageService;
-import org.onap.portal.service.fn.FnUserService;
+import org.onap.portal.service.language.FnLanguageService;
+import org.onap.portal.service.microserviceParameter.EpMicroserviceParameterService;
+import org.onap.portal.service.user.FnUserService;
+import org.onap.portal.service.widgetCatalog.EpWidgetCatalogService;
+import org.onap.portal.service.widgetCatalogParameter.EpWidgetCatalogParameterService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
@@ -77,7 +78,7 @@ class EpWidgetCatalogParameterServiceTest {
        private final FnUserService fnUserService;
        private final EpMicroserviceParameterService epMicroserviceParameterService;
        private final EpWidgetCatalogService epWidgetCatalogService;
-       private final FnLanguageDao fnLanguageDao;
+       private final FnLanguageService fnLanguageService;
 
        @Autowired
        public EpWidgetCatalogParameterServiceTest(
@@ -85,13 +86,13 @@ class EpWidgetCatalogParameterServiceTest {
            WidgetsCatalogController widgetsCatalogController,
            FnUserService fnUserService,
            EpMicroserviceParameterService epMicroserviceParameterService,
-           EpWidgetCatalogService epWidgetCatalogService, FnLanguageDao fnLanguageDao) {
+           EpWidgetCatalogService epWidgetCatalogService, FnLanguageService fnLanguageService) {
               this.epWidgetCatalogParameterService = epWidgetCatalogParameterService;
               this.widgetsCatalogController = widgetsCatalogController;
               this.fnUserService = fnUserService;
               this.epMicroserviceParameterService = epMicroserviceParameterService;
               this.epWidgetCatalogService = epWidgetCatalogService;
-              this.fnLanguageDao = fnLanguageDao;
+              this.fnLanguageService = fnLanguageService;
        }
 
        @Test
@@ -154,7 +155,7 @@ class EpWidgetCatalogParameterServiceTest {
        }
 
        private FnUser buildFnUser() {
-              FnLanguage language = fnLanguageDao.getByLanguageAlias("EN");
+              FnLanguage language = fnLanguageService.getByLanguageAlias("EN");
               return FnUser.builder()
                       .lastLoginDate(LocalDateTime.now())
                       .activeYn(true)
index fbb09e1..68b1a80 100644 (file)
@@ -49,6 +49,8 @@ import org.junit.jupiter.api.Test;
 import org.junit.runner.RunWith;
 import org.onap.portal.domain.db.fn.FnUser;
 import org.onap.portal.domain.dto.ecomp.EPUserAppCatalogRoles;
+import org.onap.portal.service.user.FnUserService;
+import org.onap.portal.service.userRole.FnUserRoleService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.test.context.TestPropertySource;
index 56cbe81..49c018e 100644 (file)
@@ -48,10 +48,12 @@ import java.util.Arrays;
 import java.util.List;
 import org.junit.jupiter.api.Test;
 import org.junit.runner.RunWith;
-import org.onap.portal.dao.fn.FnLanguageDao;
+import org.onap.portal.service.language.FnLanguageService;
 import org.onap.portal.domain.db.fn.FnLanguage;
 import org.onap.portal.domain.db.fn.FnLuTimezone;
 import org.onap.portal.domain.db.fn.FnUser;
+import org.onap.portal.service.luTimezone.FnLuTimezoneService;
+import org.onap.portal.service.user.FnUserService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
@@ -71,8 +73,6 @@ class FnUserServiceTest {
        private FnLuTimezoneService fnLuTimezoneService;
        @Autowired
        private FnLanguageService fnLanguageService;
-       @Autowired
-       private FnLanguageDao fnLanguageDao;
 
        @Test
        void saveUser(){
@@ -96,7 +96,7 @@ class FnUserServiceTest {
               expected.setCountryCd("US");
               expected.setLanguageId(fnLanguageService.findById(1L).orElse(new FnLanguage()));
               expected.setGuest(false);
-              FnLanguage language = fnLanguageDao.getByLanguageAlias("EN");
+              FnLanguage language = fnLanguageService.getByLanguageAlias("EN");
               expected.setLanguageId(language);
 
               //When
diff --git a/portal-FE-common/.gitignore b/portal-FE-common/.gitignore
new file mode 100644 (file)
index 0000000..72d97b7
--- /dev/null
@@ -0,0 +1,4 @@
+/target/
+/.classpath
+/.settings
+/.history
\ No newline at end of file
diff --git a/portal-FE-common/pom.xml b/portal-FE-common/pom.xml
new file mode 100644 (file)
index 0000000..79aad95
--- /dev/null
@@ -0,0 +1,7 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.onap.portal</groupId>
+  <artifactId>portal-FE-common</artifactId>
+  <version>0</version>
+  <!-- This file exists only to allow easy import of this project into Eclipse. -->
+</project>
diff --git a/portal-FE-common/src/app/modals/confirmation-modal/confirmation-modal.component.html b/portal-FE-common/src/app/modals/confirmation-modal/confirmation-modal.component.html
new file mode 100644 (file)
index 0000000..64b6bbd
--- /dev/null
@@ -0,0 +1,52 @@
+<!--
+  ============LICENSE_START==========================================
+  ONAP Portal
+  ===================================================================
+  Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+  ===================================================================
+  Unless otherwise specified, all software contained herein is licensed
+  under the Apache License, Version 2.0 (the "License");
+  you may not use this software except in compliance with the License.
+  You may obtain a copy of the License at
+              http://www.apache.org/licenses/LICENSE-2.0
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  Unless otherwise specified, all documentation contained herein is licensed
+  under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+  you may not use this documentation except in compliance with the License.
+  You may obtain a copy of the License at
+              https://creativecommons.org/licenses/by/4.0/
+  Unless required by applicable law or agreed to in writing, documentation
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  ============LICENSE_END============================================
+  
+  -->
+
+<div class="container">
+    <div class="modal-header">
+        <h4 class="modal-title">{{title}}</h4>
+        <button type="button" class="close" aria-label="Close" (click)="activeModal.dismiss('Cross click')">
+            <span aria-hidden="true">&times;</span>
+        </button>
+    </div>
+    <div class="modal-body">
+        <p>{{message}}</p>
+    </div>
+    <div class="modal-footer">
+        <button type="button" class="btn btn-primary" (click)="activeModal.close('Close')">Close</button>
+    </div>
+</div>
\ No newline at end of file
diff --git a/portal-FE-common/src/app/modals/confirmation-modal/confirmation-modal.component.scss b/portal-FE-common/src/app/modals/confirmation-modal/confirmation-modal.component.scss
new file mode 100644 (file)
index 0000000..3c1a547
--- /dev/null
@@ -0,0 +1,38 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+@import '../../pages/pages.component';
\ No newline at end of file
diff --git a/portal-FE-common/src/app/modals/confirmation-modal/confirmation-modal.component.spec.ts b/portal-FE-common/src/app/modals/confirmation-modal/confirmation-modal.component.spec.ts
new file mode 100644 (file)
index 0000000..bc3516e
--- /dev/null
@@ -0,0 +1,62 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { ConfirmationModalComponent } from './confirmation-modal.component';
+
+describe('ConfirmationModalComponent', () => {
+  let component: ConfirmationModalComponent;
+  let fixture: ComponentFixture<ConfirmationModalComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ ConfirmationModalComponent ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(ConfirmationModalComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/portal-FE-common/src/app/modals/confirmation-modal/confirmation-modal.component.ts b/portal-FE-common/src/app/modals/confirmation-modal/confirmation-modal.component.ts
new file mode 100644 (file)
index 0000000..774cff2
--- /dev/null
@@ -0,0 +1,55 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+import { Component, OnInit, Input } from '@angular/core';
+import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
+
+@Component({
+    selector: 'app-confirmation-modal',
+    templateUrl: './confirmation-modal.component.html',
+    styleUrls: ['./confirmation-modal.component.scss']
+})
+export class ConfirmationModalComponent implements OnInit {
+
+    @Input() title: string;
+    @Input() message: string;
+    constructor(public activeModal: NgbActiveModal) { }
+
+    ngOnInit() {
+    }
+
+}
\ No newline at end of file
diff --git a/portal-FE-common/src/app/modals/information-modal/information-modal.component.html b/portal-FE-common/src/app/modals/information-modal/information-modal.component.html
new file mode 100644 (file)
index 0000000..77312cf
--- /dev/null
@@ -0,0 +1,52 @@
+<!--
+  ============LICENSE_START==========================================
+  ONAP Portal
+  ===================================================================
+  Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+  ===================================================================
+  Unless otherwise specified, all software contained herein is licensed
+  under the Apache License, Version 2.0 (the "License");
+  you may not use this software except in compliance with the License.
+  You may obtain a copy of the License at
+              http://www.apache.org/licenses/LICENSE-2.0
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  Unless otherwise specified, all documentation contained herein is licensed
+  under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+  you may not use this documentation except in compliance with the License.
+  You may obtain a copy of the License at
+              https://creativecommons.org/licenses/by/4.0/
+  Unless required by applicable law or agreed to in writing, documentation
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  ============LICENSE_END============================================
+  
+  -->
+<div class="container">
+    <div class="modal-header">
+        <h4 class="modal-title">{{title}}</h4>
+        <button type="button" class="close" aria-label="Close" (click)="activeModal.dismiss('Cross')">
+            <span aria-hidden="true">&times;</span>
+        </button>
+    </div>
+    <div class="modal-body">
+        <p>{{message}}</p>
+    </div>
+    <div class="modal-footer">
+        <button type="button" class="btn btn-primary" (click)="activeModal.close('Ok')">Ok</button>
+        <button type="button" class="btn btn-primary" (click)="activeModal.close('Close')">Close</button>
+    </div>
+</div>
\ No newline at end of file
diff --git a/portal-FE-common/src/app/modals/information-modal/information-modal.component.scss b/portal-FE-common/src/app/modals/information-modal/information-modal.component.scss
new file mode 100644 (file)
index 0000000..3c1a547
--- /dev/null
@@ -0,0 +1,38 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+@import '../../pages/pages.component';
\ No newline at end of file
diff --git a/portal-FE-common/src/app/modals/information-modal/information-modal.component.spec.ts b/portal-FE-common/src/app/modals/information-modal/information-modal.component.spec.ts
new file mode 100644 (file)
index 0000000..fa3596f
--- /dev/null
@@ -0,0 +1,62 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { InformationModalComponent } from './information-modal.component';
+
+describe('InformationModalComponent', () => {
+  let component: InformationModalComponent;
+  let fixture: ComponentFixture<InformationModalComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ InformationModalComponent ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(InformationModalComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/portal-FE-common/src/app/modals/information-modal/information-modal.component.ts b/portal-FE-common/src/app/modals/information-modal/information-modal.component.ts
new file mode 100644 (file)
index 0000000..54e120d
--- /dev/null
@@ -0,0 +1,56 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+import { Component, OnInit, Input } from '@angular/core';
+import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
+
+@Component({
+    selector: 'app-information-modal',
+    templateUrl: './information-modal.component.html',
+    styleUrls: ['./information-modal.component.scss']
+})
+export class InformationModalComponent implements OnInit {
+
+    @Input() title: string;
+    @Input() message: string;
+
+    constructor(public activeModal: NgbActiveModal) { }
+
+    ngOnInit() {
+    }
+
+}
\ No newline at end of file
diff --git a/portal-FE-common/src/app/ng-material-module.ts b/portal-FE-common/src/app/ng-material-module.ts
new file mode 100644 (file)
index 0000000..0385598
--- /dev/null
@@ -0,0 +1,96 @@
+/**  Copyright 2019 Google Inc. All Rights Reserved.
+    Use of this source code is governed by an MIT-style license that
+    can be found in the LICENSE file at http://angular.io/license */
+import {NgModule} from '@angular/core';
+import {A11yModule} from '@angular/cdk/a11y';
+import {DragDropModule} from '@angular/cdk/drag-drop';
+import {PortalModule} from '@angular/cdk/portal';
+import {ScrollingModule} from '@angular/cdk/scrolling';
+import {CdkStepperModule} from '@angular/cdk/stepper';
+import {CdkTableModule} from '@angular/cdk/table';
+import {CdkTreeModule} from '@angular/cdk/tree';
+import {MatAutocompleteModule} from '@angular/material/autocomplete';
+import {MatBadgeModule} from '@angular/material/badge';
+import {MatBottomSheetModule} from '@angular/material/bottom-sheet';
+import {MatButtonModule} from '@angular/material/button';
+import {MatButtonToggleModule} from '@angular/material/button-toggle';
+import {MatCardModule} from '@angular/material/card';
+import {MatCheckboxModule} from '@angular/material/checkbox';
+import {MatChipsModule} from '@angular/material/chips';
+import {MatStepperModule} from '@angular/material/stepper';
+import {MatDatepickerModule} from '@angular/material/datepicker';
+import {MatDialogModule} from '@angular/material/dialog';
+import {MatDividerModule} from '@angular/material/divider';
+import {MatExpansionModule} from '@angular/material/expansion';
+import {MatFormFieldModule} from '@angular/material';
+import {MatGridListModule} from '@angular/material/grid-list';
+import {MatIconModule} from '@angular/material/icon';
+import {MatInputModule} from '@angular/material/input';
+import {MatListModule} from '@angular/material/list';
+import {MatMenuModule} from '@angular/material/menu';
+import {MatNativeDateModule, MatRippleModule} from '@angular/material/core';
+import {MatPaginatorModule} from '@angular/material/paginator';
+import {MatProgressBarModule} from '@angular/material/progress-bar';
+import {MatProgressSpinnerModule} from '@angular/material/progress-spinner';
+import {MatRadioModule} from '@angular/material/radio';
+import {MatSelectModule} from '@angular/material/select';
+import {MatSidenavModule} from '@angular/material/sidenav';
+import {MatSliderModule} from '@angular/material/slider';
+import {MatSlideToggleModule} from '@angular/material/slide-toggle';
+import {MatSnackBarModule} from '@angular/material/snack-bar';
+import {MatSortModule} from '@angular/material/sort';
+import {MatTableModule} from '@angular/material/table';
+import {MatTabsModule} from '@angular/material/tabs';
+import {MatToolbarModule} from '@angular/material/toolbar';
+import {MatTooltipModule} from '@angular/material/tooltip';
+import {MatTreeModule} from '@angular/material/tree';
+
+
+@NgModule({
+  exports: [
+    A11yModule,
+    CdkStepperModule,
+    CdkTableModule,
+    CdkTreeModule,
+    DragDropModule,
+    MatAutocompleteModule,
+    MatBadgeModule,
+    MatBottomSheetModule,
+    MatButtonModule,
+    MatButtonToggleModule,
+    MatCardModule,
+    MatCheckboxModule,
+    MatChipsModule,
+    MatStepperModule,
+    MatDatepickerModule,
+    MatDialogModule,
+    MatDividerModule,
+    MatExpansionModule,
+    MatFormFieldModule,
+    MatGridListModule,
+    MatIconModule,
+    MatInputModule,
+    MatListModule,
+    MatMenuModule,
+    MatNativeDateModule,
+    MatPaginatorModule,
+    MatProgressBarModule,
+    MatProgressSpinnerModule,
+    MatRadioModule,
+    MatRippleModule,
+    MatSelectModule,
+    MatSidenavModule,
+    MatSliderModule,
+    MatSlideToggleModule,
+    MatSnackBarModule,
+    MatSortModule,
+    MatTableModule,
+    MatTabsModule,
+    MatToolbarModule,
+    MatTooltipModule,
+    MatTreeModule,
+    PortalModule,
+    ScrollingModule,
+  ]
+})
+export class NgMaterialModule {}
\ No newline at end of file
diff --git a/portal-FE-common/src/app/pages/account-onboarding/account-add-details/account-add-details.component.html b/portal-FE-common/src/app/pages/account-onboarding/account-add-details/account-add-details.component.html
new file mode 100644 (file)
index 0000000..31f2861
--- /dev/null
@@ -0,0 +1,132 @@
+<!--
+  ============LICENSE_START==========================================
+  ONAP Portal
+  ===================================================================
+  Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+  ===================================================================
+  Unless otherwise specified, all software contained herein is licensed
+  under the Apache License, Version 2.0 (the "License");
+  you may not use this software except in compliance with the License.
+  You may obtain a copy of the License at
+              http://www.apache.org/licenses/LICENSE-2.0
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  Unless otherwise specified, all documentation contained herein is licensed
+  under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+  you may not use this documentation except in compliance with the License.
+  You may obtain a copy of the License at
+              https://creativecommons.org/licenses/by/4.0/
+  Unless required by applicable law or agreed to in writing, documentation
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  ============LICENSE_END============================================
+  
+  -->
+  
+  <div class="container">
+    <!--Modal Headers-->
+    <div class="modal-header">
+      <h4 class="modal-title">Account Details</h4>
+      <button type="button" class="close" aria-label="Close" (click)="activeModal.dismiss('Cross')">
+        <span aria-hidden="true">&times;</span>
+      </button>
+    </div>
+  
+    <!--Modal Body goes here-->
+    <div class="modal-body">
+      <!-- Add Account Popup code goes here-->
+      <div class="account-properties-main">
+        <form id="account-details-form" name="accountDetailsForm" novalidate  autocomplete="off" method="post">  
+          <div class="item required">         
+            <div class="item-label">Account Name</div>
+            <input id="account-onboarding-details-input-name" class="table-search-field"
+                type="text" ng-change="accountAddDetails.updateAccountName()" name="accountname"
+                [(ngModel)]="accountOnboarding.applicationName"
+                ng-pattern="/^[\w -]*$/" maxlength="100" required />
+          </div>
+
+          <div class="item required">  
+            <div class="item-label">Username</div>
+            <input id="account-onboarding-details-input-username" class="table-search-field"
+                type="text"
+                ng-change="accountAddDetails.updateUsername()" name="username"
+                [(ngModel)]="accountOnboarding.username"/>
+          </div>      
+
+          <div class="item">
+            <div class="item-label">Password</div>
+            <input id="account-onboarding-details-input-password" class="table-search-field"
+                type="password" name="password" [(ngModel)]="accountOnboarding.password" 
+                maxlength="100" autocomplete="off"/>
+          </div>
+
+          <div class="item">
+            <div class="item-label">Retype Password</div>
+            <input id="account-onboarding-details-input-repassword" class="table-search-field"
+                type="password" name="repassword"
+                [(ngModel)]="accountOnboarding.repassword" maxlength="100"/>
+          </div>
+
+          <div class="add-endpoint-item">
+            <div class="item-label add-label-left">Add Endpoint</div>
+            <div class="add-label-right" id="accountAddDetails-button-accordion"
+              (click)="addEndpoint()"><i class="icon ion-ios-add-circle-outline"></i>
+            </div>
+          </div>
+          
+          <div class="item">
+              <div class="item-label" *ngIf="accountOnboarding.endpointList && accountOnboarding.endpointList.length > 0">
+                Account endpoint
+              </div>
+    
+              <div id="account-details-user-paramters"  *ngFor="let endpoint of accountOnboarding.endpointList">
+                <div class="endpoint-item-left">
+                  <input id="account-details-input-endpoint-name"
+                    type="text" name="endpointName"
+                    maxlength="200" ng-model="endpoint.name" 
+                    ng-change="accountAddDetails.updateAccountEndpoint(endpoint)"/>
+                </div>
+    
+                <div class="icon-circle-action-remove endpoint-item-middle"
+                  (click)="removeEndpointItem(endpoint)"><span><i class="icon ion-ios-remove-circle-outline"></i></span>
+                </div>
+                  
+                <div class="error-container endpoint-item-right"
+                    *ngIf="endpoint.valid == false">
+                    <small id="accounts-details-input-invalid-endpoint"
+                      class="err-message">Invalid end point format
+                    </small>
+                </div>     
+              </div>
+
+              <div class="account-property">
+                <div class="property-label checkbox-label">
+                  <mat-checkbox name="isActive" type="checkbox" [(ngModel)]="accountOnboarding.isActive"
+                      id="accounts-checkbox-app-is-enabled" [checked]="accountOnboarding.isActive">
+                      Active
+                  </mat-checkbox> 
+                </div> 
+            </div>
+          </div>
+        </form>
+        </div>
+    </div>
+    <!--Modal Footer goes Here-->
+    <div class="modal-footer">
+      <button type="button" class="btn btn-primary" (click)="saveChanges()">Save</button> &nbsp;
+      <button type="button" class="btn btn-primary" (click)="activeModal.close('Close')">Cancel</button>
+    </div>
+  </div>
\ No newline at end of file
diff --git a/portal-FE-common/src/app/pages/account-onboarding/account-add-details/account-add-details.component.scss b/portal-FE-common/src/app/pages/account-onboarding/account-add-details/account-add-details.component.scss
new file mode 100644 (file)
index 0000000..4a490b1
--- /dev/null
@@ -0,0 +1,77 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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============================================
+ *
+ * 
+ */
+
+.account-properties-main {
+    padding-left: 20px;
+    padding-right: 20px;
+    margin-bottom: 50px;
+    height: 320px;
+    width: 100%;
+    overflow-x: auto;
+}
+
+.required:before {
+    color: #cf2a2a;
+    margin-right: 2px;
+    content: "* ";
+    position: absolute;
+    top: 45px;
+    left: 28px;
+}
+
+.account-properties-main input[type="text"] {
+    width: 20em;
+    margin-bottom: 10px;
+}
+
+.account-properties-main input[type="password"] {
+    width: 20em;
+    margin-bottom: 10px;
+}
+
+.add-endpoint-item .add-label-right{
+    margin-left: 13em;
+}
+
+.add-endpoint-item{
+    display: inline-flex;
+}
+
+.account-property{
+    margin-top: 8px;
+}
\ No newline at end of file
diff --git a/portal-FE-common/src/app/pages/account-onboarding/account-add-details/account-add-details.component.spec.ts b/portal-FE-common/src/app/pages/account-onboarding/account-add-details/account-add-details.component.spec.ts
new file mode 100644 (file)
index 0000000..fd56819
--- /dev/null
@@ -0,0 +1,62 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { AccountAddDetailsComponent } from './account-add-details.component';
+
+describe('AccountAddDetailsComponent', () => {
+  let component: AccountAddDetailsComponent;
+  let fixture: ComponentFixture<AccountAddDetailsComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ AccountAddDetailsComponent ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(AccountAddDetailsComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/portal-FE-common/src/app/pages/account-onboarding/account-add-details/account-add-details.component.ts b/portal-FE-common/src/app/pages/account-onboarding/account-add-details/account-add-details.component.ts
new file mode 100644 (file)
index 0000000..e2c408a
--- /dev/null
@@ -0,0 +1,159 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+
+import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
+import { NgbActiveModal, NgbModal } from '@ng-bootstrap/ng-bootstrap';
+import { BasicAuthAccountService } from 'src/app/shared/services';
+import { ConfirmationModalComponent } from 'src/app/modals/confirmation-modal/confirmation-modal.component';
+
+@Component({
+  selector: 'app-account-add-details',
+  templateUrl: './account-add-details.component.html',
+  styleUrls: ['./account-add-details.component.scss']
+})
+export class AccountAddDetailsComponent implements OnInit {
+
+  result: any;
+  isEditMode: boolean = false;
+  dupliateName: boolean = false;
+  emptyAccountName: boolean = false;
+  emptyAccountUsername: boolean = false;
+  passwordMatched: boolean = false;
+
+  @Input() accountOnboarding: any;
+  @Output() passEntry: EventEmitter<any> = new EventEmitter();
+
+  constructor(public basicAuthAccountService: BasicAuthAccountService, public activeModal: NgbActiveModal, public ngbModal: NgbModal) { }
+
+  ngOnInit() {
+    this.passwordMatched = true;
+    this.dupliateName = false;
+    this.emptyAccountName = false;
+    this.emptyAccountUsername = false;
+  
+    if(this.accountOnboarding.applicationName){
+      this.isEditMode = true;
+    }else{
+      this.isEditMode = false;
+      this.accountOnboarding.isActive = true;
+      this.accountOnboarding.endpointList = [];
+    }
+    //console.log("IsEditMode in Add account Dialog :: ",this.isEditMode)
+
+  }
+
+  addEndpoint(){
+    const modalRef = this.ngbModal.open(ConfirmationModalComponent);
+    modalRef.componentInstance.title = "";
+    modalRef.componentInstance.message = 'Please add the roles to this Username/MechId through AAF Screen';
+    modalRef.result.then((result) => { }, (resut) => {return;});
+
+    /*this.accountOnboarding.endpointList.push({
+      valid: true
+    });*/
+  }
+
+  //Add Or Update Account.
+  saveChanges(){
+    var isValid = true;
+    //console.log("saveChanges called Account Onboarding");
+
+    if(this.accountOnboarding.applicationName == ''
+      || this.accountOnboarding.applicationName == undefined){
+      this.emptyAccountName = true;
+        isValid = false;
+      }
+    
+    if(this.accountOnboarding.username == ''
+      || this.accountOnboarding.username == undefined){
+      this.emptyAccountUsername = true;
+          isValid = false;
+    }
+    
+    if(this.dupliateName == true){
+          isValid = false;
+    }
+
+    if(this.dupliateName == true){
+      isValid = false;
+    }
+    if(this.accountOnboarding.password != this.accountOnboarding.repassword){
+        this.passwordMatched =  false;
+        isValid = false;
+    }
+    //console.log("isValid....",isValid)
+    if(!isValid)
+      return;
+    
+    var active = 'N';
+    if(this.accountOnboarding.isActive == true)
+      active = 'Y';
+
+    var newAccount = {
+      applicationName: this.accountOnboarding.applicationName,
+      username: this.accountOnboarding.username,
+      password: this.accountOnboarding.password,
+      endpoints: this.accountOnboarding.endpoints,
+      isActive: active
+    };
+
+    if(this.isEditMode){
+      var message = "Are you sure you want to change '" + this.accountOnboarding.applicationName + "'?"
+      this.basicAuthAccountService.updateAccount(this.accountOnboarding.id, newAccount)
+        .subscribe( _data => {
+          this.result = _data;
+          //console.log("updateAccount response :: ",this.result);
+          this.passEntry.emit(this.result);
+          this.ngbModal.dismissAll();
+        }, error => {
+          console.log(error);
+      });
+    }else{
+      this.basicAuthAccountService.createAccount(newAccount)
+        .subscribe( _data => {
+          this.result = _data;
+          //console.log("createAccount response :: ",this.result);
+          this.passEntry.emit(this.result);
+          this.ngbModal.dismissAll();
+        }, error => {
+          console.log(error);
+      });
+    }
+  }
+}
diff --git a/portal-FE-common/src/app/pages/account-onboarding/account-onboarding.component.html b/portal-FE-common/src/app/pages/account-onboarding/account-onboarding.component.html
new file mode 100644 (file)
index 0000000..31f631e
--- /dev/null
@@ -0,0 +1,78 @@
+<!--
+  ============LICENSE_START==========================================
+  ONAP Portal
+  ===================================================================
+  Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+  ===================================================================
+  Unless otherwise specified, all software contained herein is licensed
+  under the Apache License, Version 2.0 (the "License");
+  you may not use this software except in compliance with the License.
+  You may obtain a copy of the License at
+              http://www.apache.org/licenses/LICENSE-2.0
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  Unless otherwise specified, all documentation contained herein is licensed
+  under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+  you may not use this documentation except in compliance with the License.
+  You may obtain a copy of the License at
+              https://creativecommons.org/licenses/by/4.0/
+  Unless required by applicable law or agreed to in writing, documentation
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  ============LICENSE_END============================================
+  
+  -->
+
+<div class="container">
+  <div class="ecomp-main-view-title">
+      <h1 class="heading-page">App Account Management</h1>
+  </div>
+  <button type="button" style="float: right;" class="btn btn-primary" (click)="openAddNewAccountModal('')">
+      <i class="icon ion-md-person-add"></i>Add Account
+  </button>
+  <div>
+    <table mat-table [dataSource]="dataSource" matSort>
+        <!-- Account Name Column -->
+        <ng-container matColumnDef="accountName">
+          <th id="col1" mat-header-cell *matHeaderCellDef> Account Name  </th>
+          <td (click)="openAddNewAccountModal(element)" id="rowheader_t1_{{i}}-accountName" 
+            mat-cell *matCellDef="let element; let i = index;"> {{element.applicationName}}
+          </td>
+        </ng-container>
+    
+        <!--   Username  Column -->
+        <ng-container matColumnDef="userName">
+          <th id="col2" mat-header-cell *matHeaderCellDef> Username </th>
+          <td (click)="openAddNewAccountModal(element)" id="rowheader_t1_{{i}}-userName" 
+            mat-cell *matCellDef="let element; let i=index;"> {{element.username}} </td>
+        </ng-container>
+
+        <!-- Delete Column -->
+        <ng-container matColumnDef="delete">
+          <th id="col4" mat-header-cell *matHeaderCellDef> Delete </th>
+          <td id="rowheader_t1_{{i}}" mat-cell *matCellDef="let element; let i=index;">
+            <span class="icon-trash" id="{{i}}-button-portal-admin-remove" (click)="deleteAccount(element)">
+              <i class="icon ion-md-trash"></i>
+            </span>
+          </td>
+        </ng-container>
+    
+        <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
+        <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
+    </table>
+    <mat-paginator [pageSizeOptions]="[10, 20]" showFirstLastButtons></mat-paginator>
+  </div>
+</div>
diff --git a/portal-FE-common/src/app/pages/account-onboarding/account-onboarding.component.scss b/portal-FE-common/src/app/pages/account-onboarding/account-onboarding.component.scss
new file mode 100644 (file)
index 0000000..05d0cd2
--- /dev/null
@@ -0,0 +1,46 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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============================================
+ *
+ * 
+ */
+
+ .container th{
+    padding-bottom: 15px;
+    font-weight: bold;
+}
+
+.ion-md-trash{
+    cursor: pointer;
+}
\ No newline at end of file
diff --git a/portal-FE-common/src/app/pages/account-onboarding/account-onboarding.component.spec.ts b/portal-FE-common/src/app/pages/account-onboarding/account-onboarding.component.spec.ts
new file mode 100644 (file)
index 0000000..8e6e79e
--- /dev/null
@@ -0,0 +1,63 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { AccountOnboardingComponent } from './account-onboarding.component';
+
+describe('AccountOnboardingComponent', () => {
+  let component: AccountOnboardingComponent;
+  let fixture: ComponentFixture<AccountOnboardingComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ AccountOnboardingComponent ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(AccountOnboardingComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/portal-FE-common/src/app/pages/account-onboarding/account-onboarding.component.ts b/portal-FE-common/src/app/pages/account-onboarding/account-onboarding.component.ts
new file mode 100644 (file)
index 0000000..9ed4f9d
--- /dev/null
@@ -0,0 +1,153 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+
+import { Component, OnInit, ViewChild, Input} from '@angular/core';
+import { MatTableDataSource } from '@angular/material';
+import { MatSort, MatPaginator } from '@angular/material';
+import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
+import { BasicAuthAccountService } from '../../shared/services/index';
+import { IAccountOnboarding } from 'src/app/shared/model/account-onboarding/accountOnboarding';
+import { AccountAddDetailsComponent } from './account-add-details/account-add-details.component';
+import { ConfirmationModalComponent } from 'src/app/modals/confirmation-modal/confirmation-modal.component';
+import { InformationModalComponent } from 'src/app/modals/information-modal/information-modal.component';
+
+@Component({
+  selector: 'app-account-onboarding',
+  templateUrl: './account-onboarding.component.html',
+  styleUrls: ['./account-onboarding.component.scss']
+})
+export class AccountOnboardingComponent implements OnInit {
+
+  accountList: Array<IAccountOnboarding> = [];
+  result: any;
+  isEditMode: boolean = false;
+  displayedColumns: string[] = ['accountName', 'userName','delete'];
+  dataSource = new MatTableDataSource(this.accountList);
+  @ViewChild(MatSort) sort: MatSort;
+  @ViewChild(MatPaginator) paginator: MatPaginator;
+
+  constructor(public basicAuthAccountService: BasicAuthAccountService, public ngbModal: NgbModal) { }
+
+  ngOnInit() {
+    this.getOnboardingAccounts();
+  }
+
+  populateTableData(wigetList: Array<IAccountOnboarding>){
+    this.dataSource = new MatTableDataSource(wigetList);
+    this.dataSource.sort = this.sort;
+    this.dataSource.paginator = this.paginator;
+  };
+
+  getOnboardingAccounts(){
+    //console.log("getOnboardingAccounts called");
+    this.basicAuthAccountService.getAccountList()
+      .subscribe(_data => {
+          this.result = _data;
+          //console.log("getOnboardingAccounts Data :: ", _data);
+          if (this.result == null || this.result == 'undefined') {
+              //console.log('BasicAuthAccountService::getOnboardingAccounts Failed: Result or result.data is null');
+          }else {
+            this.accountList = this.result.response;
+            this.populateTableData(this.accountList);
+          }
+      }, error =>{
+        console.log(error);
+      });
+
+  };
+
+  openAddNewAccountModal(rowData: any){
+    //console.log("openAddNewAccountModal getting called...");
+    const modalRef = this.ngbModal.open(AccountAddDetailsComponent, { size: 'lg' });
+    modalRef.componentInstance.title = 'Account Details';
+    if(rowData != 'undefined' && rowData){
+      rowData.repassword = rowData.password;
+      modalRef.componentInstance.accountOnboarding = rowData;
+      this.isEditMode = true;
+    }else{
+      modalRef.componentInstance.accountOnboarding  = {};
+      this.isEditMode = false;
+    }
+    modalRef.componentInstance.passEntry.subscribe((receivedEntry: any) => {
+      //console.log("receivedEntry >>> ",receivedEntry);
+      if(receivedEntry){
+        this.accountList = [];
+        this.getOnboardingAccounts();
+      }
+    });
+  }
+
+  deleteAccount(selectedAccount : any){
+    let confirmationMsg = 'You are about to delete this account : ' + selectedAccount.applicationName + '. Click OK to continue.';
+    this.openInformationModal("Confirmation",confirmationMsg).result.then((result) => {
+      if (result === 'Ok') {
+        //console.log("deleteAccount called Account Onboarding");
+        if(!selectedAccount || selectedAccount == null || selectedAccount =='undefined'){
+          console.log('AccountOnboardingCtrl::deleteAccount: No Account or ID... cannot delete');
+          return;
+        }
+        //console.log("deleteAccount>>id",selectedAccount.id)
+        this.basicAuthAccountService.deleteAccount(selectedAccount.id)
+          .subscribe( _data => {
+            this.result = _data;
+            //console.log("deleteAccount response :: ",this.result);
+            this.accountList.splice(this.accountList.indexOf(selectedAccount), 1);
+            this.getOnboardingAccounts();
+          }, error => {
+            console.log(error);
+        });
+      }
+    }, (resut) => {
+      return;
+    })
+  }
+
+  openConfirmationModal(_title: string, _message: string) {
+    const modalInfoRef = this.ngbModal.open(ConfirmationModalComponent);
+    modalInfoRef.componentInstance.title = _title;
+    modalInfoRef.componentInstance.message = _message;
+  }
+
+  openInformationModal(_title: string, _message: string){
+    const modalInfoRef = this.ngbModal.open(InformationModalComponent);
+    modalInfoRef.componentInstance.title = _title;
+    modalInfoRef.componentInstance.message = _message;
+    return modalInfoRef;
+  }
+
+}
diff --git a/portal-FE-common/src/app/pages/application-catalog/application-catalog.component.html b/portal-FE-common/src/app/pages/application-catalog/application-catalog.component.html
new file mode 100644 (file)
index 0000000..af54d27
--- /dev/null
@@ -0,0 +1,143 @@
+<!--
+  ============LICENSE_START==========================================
+  ONAP Portal
+  ===================================================================
+  Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+  ===================================================================
+  Unless otherwise specified, all software contained herein is licensed
+  under the Apache License, Version 2.0 (the "License");
+  you may not use this software except in compliance with the License.
+  You may obtain a copy of the License at
+              http://www.apache.org/licenses/LICENSE-2.0
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  Unless otherwise specified, all documentation contained herein is licensed
+  under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+  you may not use this documentation except in compliance with the License.
+  You may obtain a copy of the License at
+              https://creativecommons.org/licenses/by/4.0/
+  Unless required by applicable law or agreed to in writing, documentation
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  ============LICENSE_END============================================
+  
+  -->
+<div>
+  <div id="page-content">
+    <div id="title">
+      <h1>{{'Application Catalog'}}</h1>
+    </div>
+    <div>
+      <div>
+        <div id="container" class="simulateCatGridHeader">
+          <span class="simulateCatGridHeaderDetails"> Click the check
+            boxes below to choose which applications are shown on the <a [routerLink]="['/applicationsHome']">home
+              page</a>.
+          </span> <br> <br>
+          <div>
+            <div class="catalog-radio-div">
+              <label class="radio">
+                <span>{{'Filter'}}: </span>
+              </label>
+            </div>
+            <div class="catalog-radio-div">
+              <label class="radio">
+                <input type="radio" [(ngModel)]="radioValue" id="radio-button-all" name="All" value="All">
+                <i class="skin"></i>
+                <span>{{'All'}}</span>
+              </label>
+            </div>
+            <div class="catalog-radio-div">
+              <label class="radio">
+                <input type="radio" [(ngModel)]="radioValue" id="radio-button-accessible" name="Accessible"
+                  value="Accessible">
+                <i class="skin"></i>
+                <span>{{'Accessible'}}</span>
+              </label>
+            </div>
+            <div class="catalog-radio-div">
+              <label class="radio">
+                <input type="radio" [(ngModel)]="radioValue" id="radio-button-homepage" name="Selected"
+                  value="Selected">
+                <i class="skin"></i>
+                <span>{{'On Home Page'}}</span>
+              </label>
+            </div>
+
+          </div>
+        </div>
+        <div>
+          <div>
+            <gridster [options]="options" class="appCatalogue-boarder">
+
+
+              <div *ngFor="let item of layout">
+              <gridster-item [item]="item" *ngIf="(item.select && radioValue=='Selected') || (item.access && radioValue=='Accessible') || (radioValue == 'All')">
+                <div class="gridster-box" [ngStyle]="{'color': !item.access ? 'lightgray':''}">
+                  <div class="gridster-box-header">
+
+                    <mat-icon class="icon-content-gridguide">drag_handle</mat-icon>
+                    <h3>{{ item.name | elipsis: 13}}</h3>
+                    <span style="position: absolute;right:1em" *ngIf="item.access || isUserSuperAdmin">
+                      <label id="widget-checkbox-label" class="checkbox">
+
+                        <input type="checkbox" id="{{item.name.split(' ').join('-')}}-checkbox"
+                          [(ngModel)]="item.select" (ngModelChange)="storeSelection(item)" />
+
+
+                        <i class="skin"></i>
+                      </label>
+                    </span>
+
+
+                  </div>
+                  <div class="gridster-box-content" [ngStyle]="{'cursor':'pointer',
+                                                                               'background-image': 'url('+(item.imageLink)+')',
+                                                                               'order': item.order, 
+                                                                               'background-color':'white',
+                                                                               'background-repeat': 'no-repeat',
+                    'background-size': '168px 118px',
+                     'height': '80%'}" (click)="openAddRoleModal(item)">
+                  </div>
+
+                </div>
+              </gridster-item>
+            </div>
+
+
+
+            </gridster>
+          </div>
+        </div>
+
+      </div>
+
+      <div id="widgets-disclaimer" class="w-ecomp-main-disclaimer">
+        To request access to an application widget, please visit the <a>Get Access</a> page.
+      </div>
+    </div>
+  </div>
+</div>
+
+<div>
+  <div>
+
+  </div>
+  <div>
+    <div></div>
+    <div></div>
+  </div>
+</div>
\ No newline at end of file
diff --git a/portal-FE-common/src/app/pages/application-catalog/application-catalog.component.scss b/portal-FE-common/src/app/pages/application-catalog/application-catalog.component.scss
new file mode 100644 (file)
index 0000000..29198a5
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * ============LICENSE_START==========================================
+ * ONAP Portal SDK
+ * ===================================================================
+ * Copyright Â© 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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============================================
+ *
+ * 
+ */
+
+
+
+ :host {  .toolbar {
+  height: 100px;
+  display: flex;
+}  gridster {
+  display: flex;
+  height: calc(100vh - 115px);
+  flex-direction: column;
+}}
+.icon-content-gridguide{
+  cursor:move;
+  font-size: 14px; 
+  }
+  .form-row {
+    margin-top: -14px;
+}
+.griditem-header{
+  
+  
+    border-bottom: 1px;
+    border-bottom-color: solid gray;
+    
+  
+  
+}
+
+.checkbox, .radio {
+min-height: 10px; 
+padding-left: 0px; 
+}
+
+.simulateCatGridHeader{
+       position: relative;
+    height: 70px !important;
+    border: 1px solid #d3d3d3;
+    border-bottom: 0;
+    background-color: #E5E5E5;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+    z-index: 1;
+}
+
+.simulateCatGridHeaderTitle{
+       line-height: 20px;
+       margin-top: 10px;
+        margin-left: 26px;
+    font-family: "Omnes-ECOMP-W02", Arial;
+    font-size: 18px; 
+    color: #444444;
+    float: left;
+}
+
+.simulateCatGridHeaderRadio{
+    line-height: 20px;
+    margin-top: 10px; 
+    margin-left: 10px;
+    font-family: "Omnes-ECOMP-W02", Arial;
+    font-size: 12px;
+    color: #444444;
+    float: left; 
+}
+
+.simulateCatGridHeaderDetails{
+       line-height: 20px;
+    margin-left: 10px;
+    font-family: "Omnes-ECOMP-W02", Arial;
+    font-size: 12px; 
+    color: #444444;
+    float: left;
+}
+
+.simulateGridHeaderHandle{
+       cursor: move;
+    margin: 12px;
+    position: absolute;
+    top: 0;
+    left: 0;
+    border: 0;
+    vertical-align: middle;
+    -ms-interpolation-mode: bicubic;
+    display: block;
+}
+
+.catalog-radio-div{ 
+       display:inline-block; 
+       margin-right:5px; 
+} 
+
+.appCatalogue-boarder{
+  background-color: #eee;
+  border: 1px dashed white;
+  
+  overflow-y: auto;
+  overflow-x: hidden;
+  }
+
+  .gridster-box {
+    height: 100%;
+    border: 1px solid #ccc;
+    background-color: #fff;
+       transition: transform 0.5s ease-out;
+}
+.gridster-box-header {
+    background-color: #fff;
+    padding: 0 0px 0 10px;
+    border-bottom: 1px solid #ccc;
+    position: relative;
+    height: 50px !important;
+}
+.gridster-box-header h3 {
+    margin-top: 15px;
+    display: inline-block;
+    font-size: 70%;
+    font-family: "Omnes-ECOMP-W02", Arial;
+}
+.gridster-box-content {
+    padding: 59px;
+}
+.gridster-box:hover{
+    transform: scale(1.1);
+}
+.gridster-box-header-btns {
+    top: 15px;
+    right: 10px;
+    position: absolute;
+}
+.checkbox input{
+ margin: 6px;
+    left: 112px;
+    top: -20px;
+    }
+.checkbox .skin {
+    left: 125px;
+    top: -18px;
+}
diff --git a/portal-FE-common/src/app/pages/application-catalog/application-catalog.component.spec.ts b/portal-FE-common/src/app/pages/application-catalog/application-catalog.component.spec.ts
new file mode 100644 (file)
index 0000000..1967d25
--- /dev/null
@@ -0,0 +1,62 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { ApplicationCatalogComponent } from './application-catalog.component';
+
+describe('ApplicationCatalogComponent', () => {
+  let component: ApplicationCatalogComponent;
+  let fixture: ComponentFixture<ApplicationCatalogComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ ApplicationCatalogComponent ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(ApplicationCatalogComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/portal-FE-common/src/app/pages/application-catalog/application-catalog.component.ts b/portal-FE-common/src/app/pages/application-catalog/application-catalog.component.ts
new file mode 100644 (file)
index 0000000..f571dca
--- /dev/null
@@ -0,0 +1,179 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+import { Component, OnInit } from '@angular/core';
+import { GridsterConfig, GridsterItem } from 'angular-gridster2';
+import { ApplicationCatalogService } from '../../shared/services/application-catalog/application-catalog.service';
+import { IApplicationCatalog } from '../../shared/model/application-catalog.model';
+import { IWidgetCatalog } from '../../shared/model/widget-catalog.model';
+import { environment } from 'src/environments/environment';
+import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
+import { CatalogModalComponent } from '../catalog-modal/catalog-modal.component';
+import { ExternalRequestAccessService } from 'src/app/shared/services/external-request-access-service/external-request-access.service';
+import { UsersService } from 'src/app/shared/services/users/users.service';
+
+@Component({
+  selector: 'app-application-catalog',
+  templateUrl: './application-catalog.component.html',
+  styleUrls: ['./application-catalog.component.scss']
+})
+export class ApplicationCatalogComponent implements OnInit {
+  widgetCatalogData: IWidgetCatalog[];
+  appCatalogData: IApplicationCatalog[];
+  resultAccessValue: string;
+  orgUserId: string;
+  firstName: string;
+  lastName: string;
+  radioValue: any;
+  isUserSuperAdmin: boolean;
+
+  get options(): GridsterConfig {
+    return this.applicationCatalogService.options;
+  } get layout(): GridsterItem[] {
+    return this.applicationCatalogService.layout;
+  } constructor(private applicationCatalogService: ApplicationCatalogService, private externalRequestAccessService: ExternalRequestAccessService, private userService: UsersService, private modal: NgbModal) { }
+
+  ngOnInit() {
+    this.applicationCatalogService.clearCatalog();
+    this.radioValue = 'All';
+    this.callAppCatalogExecutor();
+  }
+
+  callAppCatalogExecutor() {
+    //Check whether Admin is Super Admin
+    this.checkAdminIsSuperAdmin();
+    //To fetch ML value
+    this.getExternalAccess();
+
+    //Call user profile service
+    this.getUserProfile();
+
+    //Call Application Catalog services
+    this.getAppCatalogService();
+  }
+
+  checkAdminIsSuperAdmin() {
+    this.applicationCatalogService.checkIfUserIsSuperAdmin().subscribe(data => {
+      this.isUserSuperAdmin = data;
+    }, error => {
+      console.log('checkAdminIsSuperAdmin Error Object' + error);
+    });
+  }
+
+  getAppCatalogService() {
+    //console.log("getAppCatalogServices called");
+    this.applicationCatalogService.getAppCatalog().subscribe(data => {
+      //console.log("Response data" + data);
+      this.appCatalogData = data;
+      for (let entry of this.appCatalogData) {
+        //console.log("Check the URL" + environment.api.appThumbnail);
+        var appCatalog = {
+          x: -1,
+          y: -1,
+          id: entry.id,
+          name: entry.name,
+          mlAppName: entry.mlAppName,
+          imageLink: environment.api.appThumbnail.replace(':appId', <string><any>entry.id),
+          restricted: entry.restricted,
+          select: entry.select,
+          access: entry.access,
+          pending: entry.pending,
+          mlproperty: this.resultAccessValue
+        };
+        this.applicationCatalogService.addItem(appCatalog);
+      }
+    }, error => {
+      console.log('getAppCatalogServices Error Object' + error);
+    });
+  };
+
+  storeSelection(appCatalogData: any) {
+    //console.log("Store selection called " + appCatalogData.name);
+    var pendingFlag: boolean = false;
+    if (appCatalogData.access)
+      pendingFlag = false;
+    else
+      pendingFlag = appCatalogData.pending;
+
+    var appData = {
+      appId: appCatalogData.id,
+      select: appCatalogData.select,
+      pending: pendingFlag
+    };
+    this.applicationCatalogService.updateManualAppSort(appData).subscribe(data => {
+      //console.log("Update App sort data" + data);
+    }, error => {
+      console.log('Update App sort error' + error);
+    });
+
+    this.applicationCatalogService.updateAppCatalog(appData).subscribe(data => {
+      //console.log("Update App Catalog data" + data);
+    }, error => {
+      console.log('Update App Catalog error' + error);
+    });
+  };
+  openAddRoleModal(item: any) {
+    //console.log("OpenModal check" + item.id);
+    if ((!item.restricted) && (item.mlproperty)) {
+      this.modal.open(CatalogModalComponent);
+    }
+  }
+
+  getExternalAccess() {
+    //console.log("getExternalAccess service called");
+    this.externalRequestAccessService.getExternalRequestAccessServiceInfo().subscribe(data => {
+      //console.log("Response data" + data);
+      if (data)
+        this.resultAccessValue = data.accessValue;
+    }, error => {
+      console.log('getExternalAccess Error object' + error);
+    });
+  }
+
+  getUserProfile() {
+    const userProfileObservable = this.userService.getUserProfile();
+    userProfileObservable.subscribe((userProfile: any) => {
+      //console.log('UserProfile is ' + userProfile);
+      if (userProfile) {
+        this.orgUserId = userProfile.orgUserId;
+        this.firstName = userProfile.firstName;
+        this.lastName = userProfile.lastName;
+      }
+    });
+
+  }
+}
diff --git a/portal-FE-common/src/app/pages/contact-us/contact-us-manage/contact-us-manage.component.html b/portal-FE-common/src/app/pages/contact-us/contact-us-manage/contact-us-manage.component.html
new file mode 100644 (file)
index 0000000..0d710f9
--- /dev/null
@@ -0,0 +1,156 @@
+<!--
+  ============LICENSE_START==========================================
+  ONAP Portal
+  ===================================================================
+  Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+  ===================================================================
+  Unless otherwise specified, all software contained herein is licensed
+  under the Apache License, Version 2.0 (the "License");
+  you may not use this software except in compliance with the License.
+  You may obtain a copy of the License at
+              http://www.apache.org/licenses/LICENSE-2.0
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  Unless otherwise specified, all documentation contained herein is licensed
+  under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+  you may not use this documentation except in compliance with the License.
+  You may obtain a copy of the License at
+              https://creativecommons.org/licenses/by/4.0/
+  Unless required by applicable law or agreed to in writing, documentation
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  ============LICENSE_END============================================
+  
+  -->
+<div class="container">
+  <!--Modal Headers-->
+  <div class="modal-header">
+    <h4 class="modal-title">Manage Contact Us</h4>
+    <button type="button" class="close" aria-label="Close" (click)="activeModal.dismiss('Cross')">
+        <span aria-hidden="true">&times;</span>
+    </button>
+  </div>
+
+  <!--Modal Body goes here-->
+  <div class="modal-body">
+    <div class="c-ecomp-portal-abs-table contactus-manage-table">
+      <table b2b-table id="table-main" table-data="contactUsList"      current-page="ignoredCurrentPage">
+        <thead b2b-table-row type="header">
+          <tr>
+            <th id="th-users-0" b2b-table-header key="ecomp_function" default-sort="a">App Name</th>
+            <th id="th-users-1" b2b-table-header key="app_name" sortable="true">Contact        Name</th>
+            <th id="th-users-2" b2b-table-header key="app_name" sortable="true">Contact        Email</th>
+            <th id="th-users-3" b2b-table-header key="role_name" sortable="true">Contact URL</th>
+            <th id="th-users-4" b2b-table-header key="role_name" sortable="true">Description</th>
+            <th id="th-users-5" b2b-table-header key="role_name" sortable="true">Edit</th>
+            <th id="th-users-6" b2b-table-header key="role_name" sortable="true">Delete</th>
+          </tr>
+        </thead>
+        <!-- Use track-by="UNIQUE KEY HERE" or leave out if no unique keys in data -->
+        <tbody b2b-table-row type="body" class="table-body" track-by="$index" *ngFor="let rowData of contactUsList; index as i">
+          <tr id="tr-rowData" ng-click="">
+            <td b2b-table-body>
+              <div id="users-page-td-appName" [innerHtml]="rowData.appName"></div>
+            </td>
+            <td b2b-table-body>
+              <div id="users-page-td-name" [hidden]="showEdit" [innerHtml]="rowData.contactName"></div> 
+              <input   class="input-inline-edit-text" type="text"      *ngIf="showEdit"        [(ngModel)]="rowData.contactName" />
+            </td>
+            <td b2b-table-body>
+              <div id="users-page-td-email" [hidden]="showEdit"        [innerHtml]="rowData.contactEmail"></div> 
+              <input   class="input-inline-edit-text" type="text"      *ngIf="showEdit"        [(ngModel)]="rowData.contactEmail" />
+            </td>
+            <td b2b-table-body>
+              <div id="users-page-td-url" [hidden]="showEdit"  [innerHtml]="rowData.url"></div> 
+              <input           class="input-inline-edit-text" type="text"      *ngIf="showEdit" [(ngModel)]="rowData.url" />
+            </td>
+            <td b2b-table-body>
+              <div id="users-page-td-descr" [hidden]="showEdit"                [innerHtml]=" rowData.description"></div> 
+              <input   class="input-inline-edit-text" type="text"      *ngIf="showEdit"        [(ngModel)]="rowData.description" />
+            </td>
+            <td b2b-table-body>
+              <div class="edit-contact-us" [hidden]="showEdit">
+                  <span class="icon-edit" (click)="showEdit=true">
+                      <i class="icon ion-md-create"></i>
+                  </span>
+              </div> 
+              <span *ngIf="showEdit" (click)="editContactUs(rowData)"> 
+                  <i class="icon ion-md-save"></i>
+              </span>
+            </td>
+            <td b2b-table-body>
+              <div class="delete-contact-us">
+                <span class="icon-trash" (click)="delContactUs(rowData)">
+                    <i class="icon ion-md-trash"></i>
+                </span>
+              </div>
+            </td>
+          </tr>
+        </tbody>
+      </table>
+    </div>
+  
+    <div class="divider-line"></div>
+  
+    <div class="contactus-addWidgetHeader">
+      <div id="addWidgetHeader" class="contact-us-margin">
+        <p class="edit-contactus-title">Add Application Contact Information</p>
+      </div>
+      <div id="addWidget" class="contact-us-margin">
+        <div>
+          <form name="contactForm" novalidate autocomplete="off">
+            <div id="add-contact-us-field-appname" class="add-contact-us-field">
+              <mat-form-field class="contact-us-applications-select">
+                  <mat-label> <span id="required" class="mots-property-label-spn"      visible="false"> *</span>Application Name </mat-label>
+                  <mat-select name="contact-us-applications-select" id="application" 
+                    name="applicationName" [(ngModel)]="selectedApp" [(value)]="selected">
+                    <mat-option *ngFor="let d of contactUsAllAppList" [value]="d" >{{d.title}}</mat-option>
+                  </mat-select>
+              </mat-form-field>
+              <div id="mots-property-label-required"   *ngIf="selectedApp==null || selectedApp==''">
+                <small class="mandatory-categories">App Name is Required</small>
+              </div>
+            </div>
+            <br>
+            <div class="addApplicationContactInfo">
+              <div id="add-contact-us-field-contactname"       class="add-contact-us-field">
+                <div id="property-label-name" class="property-label">Contact Name</div>
+                <input id="property-input-name" name="name" class="input-text-area" type="text"        [(ngModel)]="newContactUs.contactName" />
+              </div>
+              <div id="add-contact-us-field-email" class="add-contact-us-field">
+                <div id="property-label-email" class="property-label">Contact Email</div>
+                <input id="property-input-email" name="email" class="input-text-area" type="text" [(ngModel)]="newContactUs.contactEmail" />
+              </div>
+              <div id="add-contact-us-field-url" class="add-contact-us-field">
+                <div id="property-label-url" class="property-label">Contact    URL</div>
+                <input id="property-input-url" name="url" class="input-text-area" type="text" [(ngModel)]="newContactUs.url" />
+              </div>
+            </div>
+            <div id="add-contact-us-field-desc" class="add-contact-us-field-des">
+              <div id="property-label-desc" class="property-label">Description</div>
+              <textarea id="property-input-desc" name="description"    class="property-label-desc-txtarea" [(ngModel)]="newContactUs.description"></textarea>
+            </div>
+          </form>
+        </div>         
+      </div>
+    </div>
+  </div>
+  <!--Modal Footer goes Here-->
+  <div class="modal-footer">
+      <button type="button" class="btn btn-primary" (click)="activeModal.close('Close')">Close</button> &nbsp;
+      <button type="button" class="btn btn-primary" (click)="addNewContactUs()">Add New</button>
+  </div>
+</div>
\ No newline at end of file
diff --git a/portal-FE-common/src/app/pages/contact-us/contact-us-manage/contact-us-manage.component.scss b/portal-FE-common/src/app/pages/contact-us/contact-us-manage/contact-us-manage.component.scss
new file mode 100644 (file)
index 0000000..bff240e
--- /dev/null
@@ -0,0 +1,79 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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============================================
+ *
+ * 
+ */
+ ::ng-deep .modal-dialog { 
+    max-width: 1200px;
+    width: 1200px;
+    overflow-x: auto;
+    overflow-y: auto;
+}
+
+.addApplicationContactInfo{
+    display: inline-flex;
+}
+
+.addApplicationContactInfo input[type="text"] {
+    width: 22em;
+    margin-right: 8px;
+}
+
+.property-label-desc-txtarea {
+    overflow: auto;
+    resize: vertical;
+    width: 67em;
+}
+
+.divider-line{
+    border-bottom-style: solid;
+    border-bottom-width: 1px;
+    padding-bottom: 50px;
+}
+
+.edit-contactus-title {
+    margin-top: 28px;
+    margin-bottom: 1rem;
+    font-size: 23px;
+}
+
+.required:before {
+    color: #cf2a2a;
+    margin-right: 2px;
+    content: "* ";
+    position: absolute;
+    top: 45px;
+    left: 28px;
+}
diff --git a/portal-FE-common/src/app/pages/contact-us/contact-us-manage/contact-us-manage.component.spec.ts b/portal-FE-common/src/app/pages/contact-us/contact-us-manage/contact-us-manage.component.spec.ts
new file mode 100644 (file)
index 0000000..06b6995
--- /dev/null
@@ -0,0 +1,63 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { ContactUsManageComponent } from './contact-us-manage.component';
+
+describe('ContactUsManageComponent', () => {
+  let component: ContactUsManageComponent;
+  let fixture: ComponentFixture<ContactUsManageComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ ContactUsManageComponent ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(ContactUsManageComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/portal-FE-common/src/app/pages/contact-us/contact-us-manage/contact-us-manage.component.ts b/portal-FE-common/src/app/pages/contact-us/contact-us-manage/contact-us-manage.component.ts
new file mode 100644 (file)
index 0000000..e04ccb7
--- /dev/null
@@ -0,0 +1,182 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+
+import { Component, OnInit, Input} from '@angular/core';
+import { ContactUsService } from '../../../shared/services/index';
+import { NgbActiveModal, NgbModal } from '@ng-bootstrap/ng-bootstrap';
+
+@Component({
+  selector: 'app-contact-us-manage',
+  templateUrl: './contact-us-manage.component.html',
+  styleUrls: ['./contact-us-manage.component.scss']
+})
+export class ContactUsManageComponent implements OnInit {
+
+  contactUsList = [];
+  contactUsAllAppList = [];
+  result: any;
+  selectedApp: any;
+  showEdit: boolean = false;
+  newContactUs ={
+    appId:'',
+    appName:'',
+    description:'',
+    contactName:'',
+    contactEmail:'',
+    url:'' ,
+    activeYN:''                        
+ };
+  
+
+  constructor(public activeModal: NgbActiveModal, public ngbModal: NgbModal, public contactUsService: ContactUsService) { }
+
+  ngOnInit() {
+
+    this.getContactUsList();
+    this.getListOfApp();
+  }
+
+  getContactUsList(){
+    console.log("getContactUsList called...");
+    this.contactUsService.getContactUs()
+      .subscribe( _data => {
+        this.result = _data;
+        console.log("getContactUsList Data :: ", _data);
+        if (this.result.response == null || this.result.response == 'undefined') {
+            console.log('ContactUsService::getContactUsList Failed: Result or result.data is null');
+        }else{
+          for(var i=0; i<this.result.response.length;i++){
+            if(this.result.response[i].appId!=1)
+              this.contactUsList.push(this.result.response[i]);
+          }
+        }
+      },error =>{
+        console.log(error);
+    });
+  }
+
+  getListOfApp(){
+    console.log("getListOfApp called...");
+    this.contactUsService.getListOfApp()
+      .subscribe( _data => {
+        this.result = _data;
+        console.log("getListOfApp Data :: ", _data);
+        if (this.result == null || this.result == 'undefined') {
+            console.log('ContactUsService::getListOfApp Failed: Result or result.data is null');
+        }else{
+          let res1 = this.result;
+          let realAppIndex = 0;
+          this.contactUsAllAppList.length=0;
+          console.log("this.contactUsList ",this.contactUsList)
+          for (var i = 1; i <= res1.length; i++) {
+              if (!res1[i - 1].restrictedApp) {
+                var okToAdd = true;
+                for(var j =0; j<this.contactUsList.length;j++){
+                  if(res1[i - 1].title == this.contactUsList[j].appName){
+                    okToAdd=false;
+                    console.log("okToAdd=false res1[i - 1].title ",res1[i - 1].title);
+                  }
+                }
+                // not allowed to add(duplicate) another entry if the app is already available in the table
+                if(okToAdd){
+                  if(res1[i - 1].title){
+                    this.contactUsAllAppList.push({
+                        index: realAppIndex,
+                        title: res1[i - 1].title,
+                        value: res1[i - 1].index
+                    });
+                  }       
+                  realAppIndex = realAppIndex + 1;
+                }         
+              }
+          }
+        }
+      },error =>{
+        console.log(error);
+    });
+  }
+
+  addNewContactUs(){
+    console.log("Calling addNewContactUs");
+    let selectedApplication = this.selectedApp;
+    this.newContactUs.appId = selectedApplication.value;
+    this.newContactUs.appName = selectedApplication.title;
+    console.log("newContactUsObj ",this.newContactUs);
+    this.contactUsService.addContactUs(this.newContactUs)
+      .subscribe( _data => {
+        this.result = _data;
+        console.log("addContactUs response :: ", _data);
+        this.contactUsList.push(this.newContactUs);
+      },error =>{
+        console.log(error);
+    });
+  }
+
+  editContactUs(contactObj: any){
+
+    var contactUsObj={
+      appId:contactObj.appId,
+      appName:contactObj.appName,
+      description:contactObj.description,
+      contactName:contactObj.contactName,
+      contactEmail:contactObj.contactEmail,
+      url:contactObj.url,                      
+    };
+
+    this.contactUsService.modifyContactUs(contactUsObj)
+      .subscribe( _data => {
+        this.result = _data;
+        console.log("editContactUsFun response :: ", _data);
+        this.showEdit=false;
+      },error =>{
+        console.log(error);
+    });
+  }
+
+  delContactUs(appObj: any){
+      this.contactUsService.removeContactUs(appObj.appId)
+      .subscribe( _data => {
+        this.result = _data;
+        console.log("delContactUsFun response :: ", _data);
+        this.contactUsList.splice(appObj, 1);
+      },error =>{
+        console.log(error);
+      });
+  }
+
+}
diff --git a/portal-FE-common/src/app/pages/contact-us/contact-us.component.html b/portal-FE-common/src/app/pages/contact-us/contact-us.component.html
new file mode 100644 (file)
index 0000000..5930c38
--- /dev/null
@@ -0,0 +1,163 @@
+<!--
+  ============LICENSE_START==========================================
+  ONAP Portal
+  ===================================================================
+  Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+  ===================================================================
+  Unless otherwise specified, all software contained herein is licensed
+  under the Apache License, Version 2.0 (the "License");
+  you may not use this software except in compliance with the License.
+  You may obtain a copy of the License at
+              http://www.apache.org/licenses/LICENSE-2.0
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  Unless otherwise specified, all documentation contained herein is licensed
+  under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+  you may not use this documentation except in compliance with the License.
+  You may obtain a copy of the License at
+              https://creativecommons.org/licenses/by/4.0/
+  Unless required by applicable law or agreed to in writing, documentation
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  ============LICENSE_END============================================
+   
+-->
+<div class="container">
+    <div id="contact-us-title" class="w-ecomp-main-view-title">
+        <h1 class="heading-page">Contact Us</h1>
+    </div>
+    <button type="button" style="float: right;" class="btn btn-primary" (click)="editContactUsModal()">
+      <i class="icon ion-md-person-add"></i>Edit Contact Us
+    </button>
+    <div class="w-ecomp-contactUs-home">
+       <div class="contactUs-home-container" id="page-content">
+          <div class="admins-page-main">
+              <div class="contactUs-general-div">
+                <span class="contactUs-txt">
+                  To report an issue with ECOMP Portal, open a ticket at the 
+                  <a href="{{ush_TicketInfoUrl}}" target="_blank">User Self Help system</a>.
+                </span><br />
+              </div>
+            
+              <div class="contactUs-general-div">
+                <span class="contactUs-txt">
+                  To give feedback to the ECOMP Portal team, send email to 
+                  <a href="mailto:{{portalInfo_Address}}" target="_top">{{portalInfo_Address}}</a>. 
+                </span><br />
+              </div>
+            
+              <div class="contactUs-general-div">
+                <span class="contactUs-txt">
+                  To learn more about ECOMP Portal, visit the 
+                  <a href="{{feedback_Url}}" target="_blank">ECOMP Portal wiki</a> (may need to request access).
+                </span><br />
+              </div>
+
+              <!-- Function Categories -->             
+              <div id="appFunctionInfo" class="w-ecomp-main-view-title"> Application Functions
+                <br />
+                <div b2b-table table-data="contact.functionalTableData" class="b2b-table-div">
+                    <table mat-table [dataSource]="dataSource" matSort>
+                       <!-- Category -->
+                      <ng-container matColumnDef="category">
+                          <th id="col1" mat-header-cell *matHeaderCellDef> Category  </th>
+                          <td id="rowheader_t1_{{i}}-category" 
+                            mat-cell *matCellDef="let element; let i = index;"> {{element.category}}
+                          </td>
+                        </ng-container>
+                    
+                        <!-- Application Name Column -->
+                        <ng-container matColumnDef="eCOMPFunctions">
+                          <th id="col2" mat-header-cell *matHeaderCellDef> ECOMP Functions </th>
+                          <td id="rowheader_t1_{{i}}-eCOMPFunctions" 
+                            mat-cell *matCellDef="let element; let i=index;"> {{element.functions}} </td>
+                        </ng-container>
+
+                         <!-- Application Name Column -->
+                        <ng-container matColumnDef="eCOMPApplications">
+                          <th id="col2" mat-header-cell *matHeaderCellDef> ECOMP Applications </th>
+                          <td id="rowheader_t1_{{i}}-eCOMPApplications" 
+                            mat-cell *matCellDef="let element; let i=index;"> 
+                            <a href="javascript:void(0)" (click)="showApplicationInfo(element.app_Id)">
+                              {{element.app_Name}} 
+                            </a>
+                          </td>
+                        </ng-container>
+                         
+                        <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
+                        <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
+                    </table>                    
+                </div>
+            </div><br />
+                
+            <!-- Display applicationInfo panels -->
+            <div id="allAppInfo">
+                <div class="w-ecomp-main-view-title"> All Applications</div>   <br />  
+                <div class="contactUs-general-div">
+                  <div class="contact-us-table">
+                  <div class="c-ecomp-portal-abs-table default contactUs-table-ht">
+                    <div *ngFor="let rowData of appTable; index as i" class="contactUs-collapsible-panel">
+                        <div id="{{rowData.app_Id}}" class="contactUs-table-ht" class="contactUs-panel-header" (click)="showApplicationInfo(rowData.app_Id)">
+                            <span id="appId{{i}}" class="contactUs-table-spn">{{rowData.app_name}}</span>
+                            <span class="contactUs-table-title-sp">&nbsp;&nbsp;
+                               <span id="arrowup{{rowData.app_Id}}" [hidden]="showUp" title="Collapse app contact section" class="icon-controls-upPRIMARY">
+                                <i class="fa fa-2x fa-angle-up" aria-hidden="true"></i>
+                               </span>&nbsp;&nbsp;
+                               
+                               <span id="arrowdown{{rowData.app_Id}}" [hidden]="showDown" title="Expand app contact section" class="icon-controls-down">
+                                <i class="fa fa-2x fa-angle-down" aria-hidden="true"></i>
+                               </span>
+                            </span>
+                        </div>
+                        <div id="collapse{{rowData.app_Id}}" [hidden]="true" class="contactUs-collapsible-panel">
+                            <div class="contactUs-txt" [hidden]="rowData.contact_name || rowData.contact_email || rowData.url_Info || rowData.desc"> 
+                                <span class="contactUs-collapsible-panel-spn"> 
+                                  No application information is available. Please use the links above to contact the ECOMP Portal team. 
+                                </span>
+                            </div>
+                            <div class="contactUs-txt" *ngIf="rowData.contact_name || rowData.contact_email || rowData.url_Info || rowData.desc"> 
+                                <table class="contactUs-main-table">
+                                <tr>
+                                  <td class="contactUs-panel-labels contactUs-main-panel-labels">Contact:</td>
+                                  <td class="contactUs-panel-labels contactUs-main-panel-value">{{rowData.contact_name}}</td>
+                                </tr>
+                                <tr>
+                                  <td class="contactUs-panel-labels">Email:</td>
+                                  <td class="contactUs-panel-labels"><a href="mailto:{{rowData.contact_email}}" target="_top">{{rowData.contact_email}}</a></td>
+                                </tr>
+                                <tr>
+                                  <td class="contactUs-panel-labels">Info URL:</td>
+                                  <td class="contactUs-panel-labels"><a href="{{rowData.url_Info}}" target="_blank">{{rowData.url_Info}}</a></td>
+                                </tr>
+                                <tr>
+                                  <td class="contactUs-panel-labels">Description:</td>
+                                  <td class="contactUs-panel-labels">{{rowData.desc}}</td>
+                                </tr>
+                                <tr>
+                                  <td class="contactUs-panel-labels">Get access:</td>
+                                  <td class="contactUs-panel-labels"><a href="javascript:void(0)" (click)="goGetAccess(rowData.app_name);">Click for application and role information</a></td>
+                                </tr>
+                                </table>
+                              </div>                           
+                        </div>
+                    </div>
+                  </div>
+                  </div>
+                </div>
+              </div>
+          </div>
+      </div>
+  </div>
+</div>
\ No newline at end of file
diff --git a/portal-FE-common/src/app/pages/contact-us/contact-us.component.scss b/portal-FE-common/src/app/pages/contact-us/contact-us.component.scss
new file mode 100644 (file)
index 0000000..b3fb8d6
--- /dev/null
@@ -0,0 +1,74 @@
+
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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============================================
+ *
+ * 
+ */
+.w-ecomp-contactUs-home .contactUs-txt {
+    font-weight: 400;
+    color: #666;
+    font-size: 15px;
+    font-family: Omnes-ECOMP-W02-Medium,Arial;
+    margin: 10px;
+}
+
+.w-ecomp-contactUs-home .contactUs-home-container .contactUs-general-div {
+    margin: auto!important;
+    padding-top: 15px;
+    padding-bottom: 15px;
+    margin-top: 0;
+    margin-right: 0;
+    margin-left: 0;
+    margin-bottom: 0;
+    width: 1170px;
+}
+
+.w-ecomp-contactUs-home .w-ecomp-main-view-title {
+    font-family: Omnes-ECOMP-W02,Arial;
+    font-size: 20px;
+}
+
+button#edit-button-contact-us {
+    float: right;
+}
+
+.container th{
+    padding-bottom: 15px;
+    font-weight: bold;
+}
+
+.w-ecomp-contactUs-home .contactUs-collapsible-panel {
+    margin: auto;
+}
diff --git a/portal-FE-common/src/app/pages/contact-us/contact-us.component.spec.ts b/portal-FE-common/src/app/pages/contact-us/contact-us.component.spec.ts
new file mode 100644 (file)
index 0000000..db77e07
--- /dev/null
@@ -0,0 +1,63 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { ContactUsComponent } from './contact-us.component';
+
+describe('ContactUsComponent', () => {
+  let component: ContactUsComponent;
+  let fixture: ComponentFixture<ContactUsComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ ContactUsComponent ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(ContactUsComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/portal-FE-common/src/app/pages/contact-us/contact-us.component.ts b/portal-FE-common/src/app/pages/contact-us/contact-us.component.ts
new file mode 100644 (file)
index 0000000..d58733b
--- /dev/null
@@ -0,0 +1,196 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+
+import { Component, OnInit, ViewChild, Input } from '@angular/core';
+import { MatTableDataSource } from '@angular/material';
+import { MatSort, MatPaginator } from '@angular/material';
+import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
+import { ContactUsService } from '../../shared/services/index';
+import { ContactUsManageComponent } from './contact-us-manage/contact-us-manage.component';
+
+@Component({
+  selector: 'app-contact-us',
+  templateUrl: './contact-us.component.html',
+  styleUrls: ['./contact-us.component.scss']
+})
+export class ContactUsComponent implements OnInit {
+
+  contactUsList: Array<Object> = [];
+  appTable: Array<Object> = [];
+  functionalTableData: Array<Object> = [];
+
+  ush_TicketInfoUrl: string;
+  portalInfo_Address: string;
+  feedback_Url: string;
+  showUp: boolean = true;
+  showDown: boolean = false;
+
+  result: any;
+  isEditMode: boolean = false;
+  displayedColumns: string[] = ['category', 'eCOMPFunctions','eCOMPApplications'];
+  dataSource = new MatTableDataSource(this.functionalTableData);
+  @ViewChild(MatSort) sort: MatSort;
+  @ViewChild(MatPaginator) paginator: MatPaginator;
+
+  constructor(public contactUsService: ContactUsService, public ngbModal: NgbModal) { }
+
+  ngOnInit() {
+    this.appTable=[];
+    this.functionalTableData=[];
+
+    this.getContactUSPortalDetails();
+    this.updateContactUsTable();
+    this.getAppCategoryFunctions()
+  }
+
+  getContactUSPortalDetails(){
+    console.log("getContactUSPortalDetails called...");
+    this.contactUsService.getContactUSPortalDetails()
+      .subscribe( _data => {
+        this.result = _data;
+        console.log("getContactUSPortalDetails Data :: ", _data);
+        if (this.result.response == null || this.result.response == 'undefined') {
+            console.log('ContactUsService::getContactUSPortalDetails Failed: Result or result.data is null');
+        }else{
+          var source = JSON.parse(this.result.response);
+          this.ush_TicketInfoUrl = source.ush_ticket_url; 
+          this.portalInfo_Address = source.feedback_email_address; 
+          this.feedback_Url = source.portal_info_url;
+        }
+      },error =>{
+        console.log(error);
+    });
+  }
+
+  updateContactUsTable(){
+    console.log("updateContactUsTable called...");
+    this.contactUsService.getAppsAndContacts()
+      .subscribe( _data => {
+        this.result = _data;
+        console.log("getAppsAndContacts Data :: ", _data);
+        if (this.result.response == null || this.result.response == 'undefined') {
+            console.log('ContactUsService::getAppsAndContacts Failed: Result or result.data is null');
+        }else{
+          var tableData=[];
+          var source = this.result.response;
+          for(var i=0; i<source.length; i++) {
+            var dataArr = source[i];
+            if ( !dataArr.appName  || dataArr.appId == 1) {
+              continue;
+            }
+
+            var dataTemp={
+              app_name: dataArr.appName,
+              contact_name: dataArr.contactName,
+              contact_email: dataArr.contactEmail,
+              desc: dataArr.description,
+              url_Info: dataArr.url,
+              app_Id: dataArr.appId,
+            }
+            
+            tableData.push(dataTemp);
+          }   
+
+          this.appTable=tableData;
+        }
+      },error =>{
+        console.log(error);
+    });
+  }
+
+  getAppCategoryFunctions(){
+    console.log("getAppCategoryFunctions called");
+    this.contactUsService.getAppCategoryFunctions()
+      .subscribe( _data => {
+        this.result = _data;
+        console.log("getAppCategoryFunctions Data :: ", _data);
+        if (this.result.response == null || this.result.response == 'undefined') {
+            console.log('ContactUsService::getAppCategoryFunctions Failed: Result or result.data is null');
+        }else{
+            var tablefunctionalData=[];
+            var source = this.result.response;
+            for(var i=0;i<source.length; i++) {
+              var datafunctionalArr = source[i];
+                var datafuntionalTemp={
+                  category: datafunctionalArr.category,
+                  app_Name: datafunctionalArr.application,
+                  functions: datafunctionalArr.functions,
+                  app_Id: datafunctionalArr.appId,
+                }
+                tablefunctionalData.push(datafuntionalTemp);
+            }                  
+            this.functionalTableData = tablefunctionalData;
+            this.populateTableData(this.functionalTableData);
+        }
+      },error =>{
+        console.log(error);
+    });
+  }
+
+  populateTableData(functionalTableData: Array<Object>){
+    this.dataSource = new MatTableDataSource(functionalTableData);
+    this.dataSource.sort = this.sort;
+    this.dataSource.paginator = this.paginator;
+  }
+
+  editContactUsModal() {
+    const modalRef = this.ngbModal.open(ContactUsManageComponent, { size: 'lg' });
+  }
+
+  showApplicationInfo(appId: any){
+    console.log("AppId Contact US...",appId);
+    let appInfoDiv = document.getElementById('collapse'+appId);
+    let uparrowDiv = document.getElementById('arrowup'+appId);
+    let downarrowDiv = document.getElementById('arrowdown'+appId);
+
+    if(!appInfoDiv.getAttribute('hidden')){
+      appInfoDiv.setAttribute("hidden","true");
+      uparrowDiv.setAttribute("hidden", "true");
+      downarrowDiv.removeAttribute("hidden");
+    }else if(appInfoDiv.getAttribute('hidden')){
+      appInfoDiv.removeAttribute("hidden");
+      uparrowDiv.removeAttribute("hidden");
+      downarrowDiv.setAttribute("hidden","true");
+    }
+  }
+
+  goGetAccess(app_name: any){
+    console.log("Get Access :: goGetAccess method implemetation is pending... appName : ",app_name);
+  }
+
+}
diff --git a/portal-FE-common/src/app/pages/microservice-onboarding/microservice-add-details/microservice-add-details.component.html b/portal-FE-common/src/app/pages/microservice-onboarding/microservice-add-details/microservice-add-details.component.html
new file mode 100644 (file)
index 0000000..4ec8ae3
--- /dev/null
@@ -0,0 +1,214 @@
+<!--
+  ============LICENSE_START==========================================
+  ONAP Portal
+  ===================================================================
+  Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+  ===================================================================
+  Unless otherwise specified, all software contained herein is licensed
+  under the Apache License, Version 2.0 (the "License");
+  you may not use this software except in compliance with the License.
+  You may obtain a copy of the License at
+              http://www.apache.org/licenses/LICENSE-2.0
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  Unless otherwise specified, all documentation contained herein is licensed
+  under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+  you may not use this documentation except in compliance with the License.
+  You may obtain a copy of the License at
+              https://creativecommons.org/licenses/by/4.0/
+  Unless required by applicable law or agreed to in writing, documentation
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  ============LICENSE_END============================================
+  
+  -->
+  
+<div class="container">
+  <form name="form" (ngSubmit)="f.form.valid && saveChanges()" #f="ngForm" novalidate autocomplete="off">
+
+    <!--Modal Headers-->
+    <div class="modal-header">
+      <h4 class="modal-title">Microservice Onboarding</h4>
+      <button type="button" class="close" aria-label="Close" (click)="activeModal.dismiss('Cross')">
+        <span aria-hidden="true">&times;</span>
+      </button>
+    </div>
+  
+    <!--Modal Body goes here-->
+    <div class="modal-body">
+      <div id="microservices" class="microservice-add-details-model">
+        <div class="microservice-properties-main">
+            <div class="item required">
+              <div class="item-label">Microservice Name</div>
+              <input id="microservice-details-input-name" class="table-search-field"
+                type="text" name="name" #name="ngModel" ng-pattern="/^[\w -]*$/" maxlength="100"
+                [(ngModel)]="ms.name"
+                ng-change="microserviceAddDetails.updateServiceName()"
+                [ngClass]="{'is-invalid': f.submitted && name.invalid}" required />
+
+                <div class="error-container" *ngIf="f.submitted && name.invalid">
+                    <div class="error-container">
+                      <small id="microservices-details-input-name-required" class="err-message">
+                        Microservice Name is required
+                      </small>
+                    </div>
+                </div>    
+            </div>
+
+            
+            <div class="item required">
+                <div class="item-label">Microservice Description</div>
+                  <textarea b2b-reset b2b-reset-textarea id="widgets-details-input-desc"
+                    name="desc" [(ngModel)]="ms.desc" #desc="ngModel" class="microservice-desc"
+                    ng-change="microserviceAddDetails.updateDesc()"
+                    [ngClass]="{'is-invalid': f.submitted && desc.invalid}" required>
+                  </textarea>
+
+                  <div class="error-container" *ngIf="f.submitted && desc.invalid">
+                      <div class="error-container">
+                        <small id="microservices-details-input-desc-required" class="err-message">
+                          Microservice Description is required
+                        </small>
+                      </div>
+                  </div>    
+            </div>
+
+            <div class="item required">
+                <div class="service-select">                                   
+                  <mat-form-field>
+                    <mat-label>Applications Name</mat-label>
+                    <mat-select name="microservice-details-application-select"
+                       [(ngModel)]="ms.appId" #appId="ngModel" [(value)]="selected"
+                       [ngClass]="{'is-invalid': f.submitted && appId.invalid}" required>
+                      <mat-option *ngFor="let d of applicationList" [value]="d.value" >{{d.title}}</mat-option>
+                    </mat-select>
+                  </mat-form-field>
+                </div>
+
+                <div class="error-container" *ngIf="f.submitted && appId.invalid">
+                    <div class="error-container">
+                      <small id="microservices-details-input-appid-required" class="err-message">
+                          Please select microservice Application
+                      </small>
+                    </div>
+                </div>       
+            </div>
+
+            <div class="item required">
+              <div class="item-label">Microservice Endpoint URL</div>
+              <input id="microservice-details-input-endpoint-url"
+                [(ngModel)]="ms.url" #url="ngModel" ng-change="microserviceAddDetails.updateURL()" type="text"
+                name="url" maxlength="200" [ngClass]="{'is-invalid': f.submitted && url.invalid}" required />
+
+                <div class="error-container" *ngIf="f.submitted && url.invalid">
+                    <div class="error-container">
+                      <small id="microservices-details-input-url-required" class="err-message">
+                        Microservice Endpoint URL is required
+                      </small>
+                    </div>
+                </div>    
+            </div>
+
+            <div class="item">
+              <div class="service-select">                                     
+                  <mat-form-field>
+                    <mat-label>Security Type</mat-label>
+                    <mat-select name="microservice-details-input-security-type" [(ngModel)]="ms.securityType" [(value)]="selected">
+                      <mat-option *ngFor="let d of availableSecurityTypes" [value]="d.name" >{{d.name}}</mat-option>
+                    </mat-select>
+                  </mat-form-field>
+              </div>                   
+            </div>
+
+            <div class="item" *ngIf="ms.securityType == 'Basic Authentication'">
+              <div class="item-label">Username</div>
+              <input id="microservice-details-input-username" class="table-search-field"
+                type="text" name="username" maxlength="100"
+                [(ngModel)]="ms.username" />
+            </div>
+
+            <div class="item" *ngIf="ms.securityType == 'Basic Authentication'">
+              <div class="item-label">Password</div>
+              <input id="microservice-details-input-password" class="table-search-field"
+                type="password" name="password" maxlength="100"
+                [(ngModel)]="ms.password" />
+            </div>
+
+            <div class="item" *ngIf="isEditMode">
+                <div class="left-test-item">
+                  <div class="item-label">Test Microservice</div>
+                </div>
+                <div class="right-test-item">
+                  <div id="microservice-details-test-button" class="test-button"
+                    (click)="testServiceURL()">Test</div>
+                </div>
+            </div>
+                    
+            <div class="item" *ngIf="isEditMode">
+                <div class="item-label">JSON output</div>
+                <textarea id="microservice-details-input-json" class="json-field"
+                  name="json"></textarea>
+            </div>
+
+            <div class="add-para-item">
+                <div class="item-label add-label-left">Add User Parameter</div>
+                <div class="icon-primary-accordion-plus" (click)="addParameter()">
+                    <i class="icon ion-ios-add-circle-outline"></i>
+                </div>
+            </div>
+
+            <div class="item">
+              <div class="param-label-item-left"
+                *ngIf="ms.parameterList.length > 0">
+                Parameter Key
+              </div>
+              <div class="para-label-item-right"
+                *ngIf="ms.parameterList.length > 0">
+                Parameter Default Value
+              </div>
+
+              <div id="microservice-details-user-paramters" *ngFor="let parameter of ms.parameterList; let i=index">
+                <div class="param-item-left">
+                        <input id="microservice-details-input-user-parameter-key"
+                          class="table-search-field" type="text" name="param-key" maxlength="200"
+                          [(ngModel)]="parameter.para_key" />
+                        <input id="microservice-details-input-user-parameter-value"
+                          class="table-search-fields" type="text" name="param-value"
+                          maxlength="200" [(ngModel)]="parameter.para_value" />
+                </div>
+
+                <div (click)="removeParamItem(parameter)">
+                    <i class="icon ion-ios-remove-circle-outline"></i>
+                </div>
+              </div>
+
+              <div class="microservice-property">      
+                  <mat-checkbox  name="active" type="checkbox" [(ngModel)]="ms.active"
+                    id="microservices-checkbox-app-is-enabled" [checked]="ms.active">
+                    Active
+                  </mat-checkbox>
+              </div>
+            </div>
+          </div>
+      </div> 
+    </div>
+    <!--Modal Footer goes Here-->
+    <div class="modal-footer">
+      <button type="submit" class="btn btn-primary">Save</button> &nbsp;
+      <button type="button" class="btn btn-primary" (click)="activeModal.close('Close')">Cancel</button>
+    </div>
+  </form>
+</div>
\ No newline at end of file
diff --git a/portal-FE-common/src/app/pages/microservice-onboarding/microservice-add-details/microservice-add-details.component.scss b/portal-FE-common/src/app/pages/microservice-onboarding/microservice-add-details/microservice-add-details.component.scss
new file mode 100644 (file)
index 0000000..1ea3909
--- /dev/null
@@ -0,0 +1,211 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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============================================
+ *
+ * 
+ */
+
+::ng-deep .modal-dialog { 
+    max-width: 600px;
+    width: 600px;
+    overflow-x: auto;
+    overflow-y: auto;
+}
+
+::ng-deep .modal-body {
+   padding: -1rem;
+}
+
+::ng-deep .mat-form-field-infix {
+    width: 400px;
+}
+
+.microservice-add-details-model .microservice-properties-main {
+    padding-left: 20px;
+    padding-right: 20px;
+    margin-bottom: 50px;
+    height: 430px;
+    width: 100%;
+    overflow-x: auto;
+}
+
+.microservice-add-details-model .microservice-properties-main .item {
+    position: relative;
+    margin-bottom: 15px;
+    width: 400px;
+}
+
+.microservice-add-details-model .microservice-properties-main .item .error-container {
+    position: absolute;
+    width: 280px;
+    display: block;
+    height: 12px;
+    line-height: 12px;
+}
+
+.microservice-add-details-model .microservice-properties-main .item .error-container .err-message {
+    color: #cf2a2a;
+    font-size: 10px;
+}
+
+.microservice-add-details-model .microservice-properties-main .item .item-label {
+    color: #5a5a5a;
+    font-family: Omnes-ECOMP-W02,Arial;
+    font-size: 14px;
+}
+
+.microservice-add-details-model .microservice-properties-main .item .left-test-item {
+    display: inline-block;
+    width: 85%;
+    background: #fff;
+}
+
+.microservice-add-details-model .microservice-properties-main .item .right-test-item {
+    position: relative;
+    display: inline-block;
+    width: 15%;
+    float: right;
+}
+
+.microservice-add-details-model .microservice-properties-main .item .test-button {
+    color: #fff;
+    font-family: Omnes-ECOMP-W02-Medium,Arial;
+    font-size: 14px;
+    border-style: solid;
+    border-width: 1px;
+    border-radius: 6px;
+    box-shadow: 0 1px 0.99px 0.01px rgba(2,60,89,.004);
+    height: 29px;
+    line-height: 29px;
+    cursor: pointer;
+    text-align: center;
+    background: #067ab4;
+}
+
+.microservice-add-details-model .microservice-properties-main .item {
+    position: relative;
+    margin-bottom: 15px;
+    width: 400px;
+}
+
+.microservice-add-details-model .microservice-properties-main .add-para-item {
+    position: relative;
+    display: inline-flex;
+}
+
+.microservice-add-details-model .microservice-properties-main .add-para-item .add-label-left {
+    line-height: 25px;
+    height: 30px;
+    vertical-align: middle;
+    display: inline-block;
+    margin-right: 10px;
+    background: #fff;
+    color: #5a5a5a;
+    font-family: Omnes-ECOMP-W02,Arial;
+    font-size: 14px;
+}
+
+.microservice-add-details-model .microservice-properties-main .microservice-property {
+    margin-top: 10px;
+    position: relative;
+}
+
+.icon-primary-accordion-minus, .icon-primary-expanded, .icon-primary-accordion-plus, .icon-primary-collapsed {
+    font-size: 20px !important;
+}
+
+#microservice-details-input-name{
+    width: 16em;
+}
+
+#widgets-details-input-desc{
+    width: 25em;
+}
+
+.microservice-desc {
+    overflow: auto;
+    resize: vertical;
+    width: 29em;
+}
+
+.json-field {
+    overflow: auto;
+    resize: vertical;
+    width: 25em;
+}
+
+#microservice-details-input-app{
+    width: 25em;
+    height: 32px;
+}
+
+#microservice-details-input-endpoint-url{
+    width: 25em;
+}
+
+#microservice-details-input-security-type{
+    width: 25em;
+    height: 32px;
+}
+
+.microservice-add-details-model .microservice-properties-main .item .para-label-item-right {
+    margin-left: 201px!important;
+    position: absolute!important;
+    margin-top: -19px!important;
+    width: 50%!important;
+}
+
+.microservice-add-details-model .microservice-properties-main .item .para-item-right {
+    margin-top: -27px;
+    position: absolute;
+    margin-left: 500px;
+}
+
+.table-search-field {
+    width: 48% !important;
+    margin-bottom: 5px;
+}
+
+#microservice-details-user-paramters{
+    display: inline-flex;
+}
+
+.required:before {
+    color: #cf2a2a;
+    margin-right: 2px;
+    content: "* ";
+    position: absolute;
+    top: 28px;
+    left: -10px;
+}
\ No newline at end of file
diff --git a/portal-FE-common/src/app/pages/microservice-onboarding/microservice-add-details/microservice-add-details.component.spec.ts b/portal-FE-common/src/app/pages/microservice-onboarding/microservice-add-details/microservice-add-details.component.spec.ts
new file mode 100644 (file)
index 0000000..5589854
--- /dev/null
@@ -0,0 +1,62 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { MicroserviceAddDetailsComponent } from './microservice-add-details.component';
+
+describe('MicroserviceAddDetailsComponent', () => {
+  let component: MicroserviceAddDetailsComponent;
+  let fixture: ComponentFixture<MicroserviceAddDetailsComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ MicroserviceAddDetailsComponent ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(MicroserviceAddDetailsComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/portal-FE-common/src/app/pages/microservice-onboarding/microservice-add-details/microservice-add-details.component.ts b/portal-FE-common/src/app/pages/microservice-onboarding/microservice-add-details/microservice-add-details.component.ts
new file mode 100644 (file)
index 0000000..5e359dd
--- /dev/null
@@ -0,0 +1,303 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
+import { IMircroservies } from 'src/app/shared/model/microservice-onboarding/microservices';
+import { MicroserviceService, WidgetOnboardingService } from '../../../shared/services/index';
+import { NgbActiveModal, NgbModal } from '@ng-bootstrap/ng-bootstrap';
+
+@Component({
+  selector: 'app-microservice-add-details',
+  templateUrl: './microservice-add-details.component.html',
+  styleUrls: ['./microservice-add-details.component.scss']
+})
+export class MicroserviceAddDetailsComponent implements OnInit {
+
+  @Input() public ms: IMircroservies;
+  @Output() passEntry: EventEmitter<any> = new EventEmitter();
+  result: any;
+  selected: any;
+  isEditMode: any;
+  originalName: string;
+  dupliateName = false;
+  emptyServiceName = false;
+  emptyServiceDesc = false;
+  emptyServiceURL = false;
+  emptyServiceApp = false;
+  availableSecurityTypes = [];
+  availableWidgets = [];
+  applicationList: Array<Object> = [];
+
+  constructor(public microservice: MicroserviceService, public widgetOnboardingService: WidgetOnboardingService, 
+    public activeModal: NgbActiveModal, public ngbModal: NgbModal) { }
+
+  ngOnInit() {
+    if(this.ms.name){
+      this.isEditMode = true;
+    }else{
+      this.isEditMode = false;
+    }
+    this.ms.parameterList = [];
+    this.ms.active = true;
+    this.populateAvailableApps();
+    this.getAvailableSecurityTypes();
+  }
+
+  getAvailableWidgets(serviceId){
+    console.log("getAvailableWidgets called");
+    this.microservice.getWidgetListByService(serviceId)
+    .subscribe(data => {
+        this.result = data;
+        if (this.result == null || this.result) {
+              console.log('MicroserviceService::getServiceList Failed: Result or result.data is null');
+          }else {
+            this.availableWidgets = [];
+            for(var i = 0; i < data.length; i++){
+              this.availableWidgets.push({
+                name: data[i]
+              })
+            }
+          }
+    }, error =>{
+      console.log(error);
+    });
+  };
+  
+  getAvailableSecurityTypes(): Array<String> {
+    this.availableSecurityTypes = [];
+    this.availableSecurityTypes.push({
+      id: 0,
+      name: 'No Authentication'
+    });
+    this.availableSecurityTypes.push({
+      id: 1,
+      name: 'Basic Authentication'
+    });
+    this.availableSecurityTypes.push({
+      id: 2,
+      name: 'Cookie based Authentication'
+    });
+
+    return this.availableSecurityTypes;
+  };
+  
+  populateAvailableApps(){
+    this.widgetOnboardingService.populateAvailableApps()
+      .subscribe( _data => {
+        let allPortalsFilterObject = {index: 0, title: 'Select Application', value: ''};
+        this.applicationList = [allPortalsFilterObject];
+        var realAppIndex = 1;
+        for (let i = 1; i <= _data.length; i++) {
+            if (!_data[i-1].restrictedApp) {
+                this.applicationList.push({
+                    index: realAppIndex,
+                    title: _data[i - 1].name,
+                    value: _data[i - 1].id
+                })
+                realAppIndex = realAppIndex + 1;
+            }
+        }
+      }, error => {
+        console.log(error);
+    }); 
+  };
+
+  addParameter() {
+    this.ms.parameterList.push({}); 
+  }
+
+  testServiceURL(){
+    console.log("testServiceURL called  id is :: ",this.ms.id)
+    this.microservice.getServiceJSON(this.ms.id)
+      .subscribe( _data => {
+        this.result = _data;
+        console.log("testServiceURL response :: ",this.result);
+        document.getElementById("microservice-details-input-json").innerHTML = (JSON.stringify(this.result));
+      }, error => {
+        document.getElementById("microservice-details-input-json").innerHTML = "Something went wrong. Please go back to the previous page or try again later.";
+        console.log(error);
+    });
+  }
+
+  removeParamItem(parameter: any){
+    console.log("removeParamItem called", parameter);
+    this.ms.parameterList.splice(parameter.para_key, 1);
+    this.microservice.getUserParameterById(parameter)
+    .subscribe(data => {
+        this.result = data;
+        if (this.result == null || this.result) {
+              console.log('MicroserviceService::removeParamItem Failed: Result or result.data is null');
+        }else if(this.result && this.result.length > 0) {
+          this.microservice.deleteUserParameterById(parameter.id)
+          .subscribe(__data => {
+            for(var i = 0; i < this.ms.parameterList.length; i++){
+              if(this.ms.parameterList[i].para_key == parameter.para_key
+              && this.ms.parameterList[i].para_value == parameter.para_value){
+                this.ms.parameterList.splice(i, 1);
+                return;
+              }
+            }
+              
+          }, error =>{
+            console.log(error);
+          });
+        }else{
+          for(var i = 0; i < this.ms.parameterList.length; i++){
+            if(this.ms.parameterList[i].para_key == parameter.para_key
+            && this.ms.parameterList[i].para_value == parameter.para_value){
+              this.ms.parameterList.splice(i, 1);
+              return;
+            }
+          }
+        }
+    }, error =>{
+      console.log(error);
+    });
+  }
+
+  //Add Or Update Microservices.
+  saveChanges(){
+    console.log("saveChanges..",this.ms);
+    if(this.ms && this.ms.id && this.ms.id !='undefined'){
+      this.isEditMode = true;
+    }
+    var isValid = true;
+    
+    if(this.ms.name == ''
+      || this.ms.name == undefined){
+      this.emptyServiceName = true;
+      isValid = false;
+    }
+    console.log("a >",isValid);
+    if(this.dupliateName == true){
+      isValid = false;
+    }
+    console.log("b> ",isValid);  
+    if(this.ms.desc == ''
+    || this.ms.desc == undefined){
+      this.emptyServiceDesc = true;
+      isValid = false;
+    }
+    console.log("c> ",isValid); 
+    
+    if(this.ms.url == ''
+      || this.ms.url == undefined){
+        this.emptyServiceURL = true;
+        isValid = false;
+    }
+    console.log("d> ",isValid); 
+      
+    if(this.ms.appId == undefined
+    || this.ms.appId == null){
+      this.emptyServiceApp = true;
+      isValid = false;
+    }
+    
+    console.log("IsValid flag add/update microservices ",isValid ) 
+
+    if(!isValid)
+      return;
+    /*
+    * Check the parameter list, delete those parameters that don't
+    * have key
+    */
+    if(this.ms && this.ms.parameterList){
+      for(var i = 0; i < this.ms.parameterList.length; i++){
+        if(this.ms.parameterList[i].para_key == undefined
+        || this.ms.parameterList[i].para_key == null
+        || this.ms.parameterList[i].para_key == ""){
+          this.ms.parameterList.splice(i, 1);
+          i--;
+        }
+      }
+    }
+    if(this.ms.securityType == undefined ||
+    this.ms.securityType == null)
+      this.ms.securityType = "No Authentication";
+    else{
+      this.ms.securityType = this.ms.securityType;
+      this.ms.username = this.ms.username;
+      this.ms.password = this.ms.password;
+    }
+    
+    var active = 'N';
+    if(this.ms.active == true)
+      active = 'Y';
+    
+    let paramList = [];
+    if(this.ms.parameterList && this.ms.parameterList.length >0){
+      paramList = this.ms.parameterList;
+    }  
+    var newService = {
+      name: this.ms.name,
+      desc: this.ms.desc,
+      appId: this.ms.appId,
+      url: this.ms.url,
+      securityType: this.ms.securityType,
+      username: this.ms.username,
+      password: this.ms.password,
+      active: active,
+      parameterList: paramList
+    };
+
+    if(this.isEditMode){
+      console.log("Edit microservice mode called");
+      this.microservice.updateService(this.ms.id , newService)
+        .subscribe( data => {
+          this.result = data;
+          console.log("update microservice response :: ",this.result);
+          this.passEntry.emit(this.result);
+          this.ngbModal.dismissAll();
+        }, error => {
+          console.log(error);
+          this.ngbModal.dismissAll();
+       }); 
+    }else{  
+      console.log("Add microservice mode called")
+      this.microservice.createService(newService)
+        .subscribe( data => {
+          this.result = data;
+          console.log("add microservice response :: ",this.result);
+          this.passEntry.emit(this.result);
+          this.ngbModal.dismissAll();
+        }, error => {
+          this.ngbModal.dismissAll();
+          console.log(error);
+      }); 
+    }
+  }
+}
diff --git a/portal-FE-common/src/app/pages/microservice-onboarding/microservice-onboarding.component.html b/portal-FE-common/src/app/pages/microservice-onboarding/microservice-onboarding.component.html
new file mode 100644 (file)
index 0000000..45a6865
--- /dev/null
@@ -0,0 +1,89 @@
+<!--
+  ============LICENSE_START==========================================
+  ONAP Portal
+  ===================================================================
+  Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+  ===================================================================
+  Unless otherwise specified, all software contained herein is licensed
+  under the Apache License, Version 2.0 (the "License");
+  you may not use this software except in compliance with the License.
+  You may obtain a copy of the License at
+              http://www.apache.org/licenses/LICENSE-2.0
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  Unless otherwise specified, all documentation contained herein is licensed
+  under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+  you may not use this documentation except in compliance with the License.
+  You may obtain a copy of the License at
+              https://creativecommons.org/licenses/by/4.0/
+  Unless required by applicable law or agreed to in writing, documentation
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  ============LICENSE_END============================================
+  
+  -->
+
+<div class="container"> 
+  <div id="microservice-onboarding-title" class="w-ecomp-main-view-title">
+      <h1 class="heading-page"> Microservice Onboarding</h1>
+  </div>
+
+  <mat-form-field>
+    <input matInput type="text" (keyup)="applyFilter($event.target.value)" placeholder="Search in entire table">
+  </mat-form-field>
+
+  <button type="button" style="float: right;" class="btn btn-primary" (click)="openAddNewMicroserviceModal('')">
+    <i class="icon ion-md-person-add"></i>Add Microservice
+  </button>
+
+  <table mat-table [dataSource]="dataSource" matSort>
+    <!-- Microservice Name Column -->
+    <ng-container matColumnDef="microserviceName">
+      <th id="col1" mat-header-cell *matHeaderCellDef mat-sort-header> Microservice Name  </th>
+      <td (click)="openAddNewMicroserviceModal(element)" id="rowheader_t1_{{i}}-microserviceName" 
+        mat-cell *matCellDef="let element; let i = index;"> {{element.name}}
+      </td>
+    </ng-container>
+
+    <!-- Microservice serviceEndPointURL Column -->
+    <ng-container matColumnDef="serviceEndPointURL">
+      <th id="col2" mat-header-cell *matHeaderCellDef> Service End Point URL </th>
+      <td (click)="openAddNewMicroserviceModal(element)" id="rowheader_t1_{{i}}-serviceEndPointURL" 
+        mat-cell *matCellDef="let element; let i=index;"> {{element.url}} </td>
+    </ng-container>
+
+    <!-- Microservice securityType Column -->
+    <ng-container matColumnDef="securityType">
+      <th id="col2" mat-header-cell *matHeaderCellDef> Security Type </th>
+      <td (click)="openAddNewMicroserviceModal(element)" id="rowheader_t1_{{i}}-securityType" 
+        mat-cell *matCellDef="let element; let i=index;"> {{element.securityType}} </td>
+    </ng-container>
+
+    <!-- Delete Column -->
+    <ng-container matColumnDef="delete">
+      <th id="col4" mat-header-cell *matHeaderCellDef> Delete </th>
+      <td id="rowheader_t1_{{i}}" mat-cell *matCellDef="let element; let i=index;">
+        <span class="icon-trash" id="{{i}}-button-portal-admin-remove" (click)="deleteService(element)">
+          <i class="icon ion-md-trash"></i>
+        </span>
+      </td>
+    </ng-container>
+
+    <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
+    <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
+  </table>
+  <mat-paginator [pageSizeOptions]="[10, 20]" showFirstLastButtons></mat-paginator>
+</div>
\ No newline at end of file
diff --git a/portal-FE-common/src/app/pages/microservice-onboarding/microservice-onboarding.component.scss b/portal-FE-common/src/app/pages/microservice-onboarding/microservice-onboarding.component.scss
new file mode 100644 (file)
index 0000000..135fbda
--- /dev/null
@@ -0,0 +1,46 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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============================================
+ *
+ * 
+ */
+
+.container th{
+    padding-bottom: 15px;
+    font-weight: bold;
+}
+
+.ion-md-trash{
+    cursor: pointer;
+}
\ No newline at end of file
diff --git a/portal-FE-common/src/app/pages/microservice-onboarding/microservice-onboarding.component.spec.ts b/portal-FE-common/src/app/pages/microservice-onboarding/microservice-onboarding.component.spec.ts
new file mode 100644 (file)
index 0000000..09d30a1
--- /dev/null
@@ -0,0 +1,63 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { MicroserviceOnboardingComponent } from './microservice-onboarding.component';
+
+describe('MicroserviceOnboardingComponent', () => {
+  let component: MicroserviceOnboardingComponent;
+  let fixture: ComponentFixture<MicroserviceOnboardingComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ MicroserviceOnboardingComponent ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(MicroserviceOnboardingComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/portal-FE-common/src/app/pages/microservice-onboarding/microservice-onboarding.component.ts b/portal-FE-common/src/app/pages/microservice-onboarding/microservice-onboarding.component.ts
new file mode 100644 (file)
index 0000000..d2d6697
--- /dev/null
@@ -0,0 +1,156 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+
+import { Component, OnInit, ViewChild, Input } from '@angular/core';
+import { MicroserviceService, WidgetOnboardingService } from '../../shared/services/index'
+import { IMircroservies } from 'src/app/shared/model/microservice-onboarding/microservices';
+import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
+import { MatTableDataSource } from '@angular/material';
+import { MatSort, MatPaginator } from '@angular/material';
+import { MicroserviceAddDetailsComponent } from './microservice-add-details/microservice-add-details.component';
+import { ConfirmationModalComponent } from 'src/app/modals/confirmation-modal/confirmation-modal.component';
+import { InformationModalComponent } from 'src/app/modals/information-modal/information-modal.component';
+
+@Component({
+  selector: 'app-microservice-onboarding',
+  templateUrl: './microservice-onboarding.component.html',
+  styleUrls: ['./microservice-onboarding.component.scss']
+})
+export class MicroserviceOnboardingComponent implements OnInit {
+
+  showSpinner = true;
+  microServiceList: Array<IMircroservies> = [];
+  result: any;
+  isEditMode: boolean = false;
+  
+  displayedColumns: string[] = ['microserviceName', 'serviceEndPointURL', 'securityType','delete'];
+  dataSource = new MatTableDataSource(this.microServiceList);
+  @ViewChild(MatSort) sort: MatSort;
+  @ViewChild(MatPaginator) paginator: MatPaginator;
+
+  constructor(public microservice: MicroserviceService, public ngbModal: NgbModal ) { }
+
+  ngOnInit() {
+    this.getOnboardingServices();
+  }
+
+  getOnboardingServices(){
+    //console.log("getOnboardingServices called");
+    this.microservice.getServiceList()
+    .subscribe(_data => {
+        this.result = _data;
+        if (this.result == null || this.result == 'undefined') {
+             console.log('MicroserviceService::getServiceList Failed: Result or result.data is null');
+         }else {
+          this.microServiceList = this.result;
+          this.populateTableData(this.microServiceList);
+         }
+    }, error =>{
+      console.log(error);
+    });
+  }
+
+  deleteService(microserviceObj: IMircroservies, isConfirmed: boolean): void {
+    let confirmationMsg = 'You are about to delete this Microservice : ' + microserviceObj.name+ '. Click OK to continue.';
+    this.openInformationModal("Confirmation",confirmationMsg).result.then((result) => {
+      if (result === 'Ok') {
+        if(!microserviceObj || microserviceObj == null){
+          console.log('MicroserviceOnboardingCtrl::deleteService: No service or ID... cannot delete');
+          return;
+        }
+        //console.log("service id to delete", microserviceObj.id)
+        this.microServiceList.splice(this.microServiceList.indexOf(microserviceObj), 1);
+        this.populateTableData(this.microServiceList);
+        this.microservice.deleteService(microserviceObj.id)
+          .subscribe( data => {
+            this.result = data;
+            this.microServiceList = [];
+            this.getOnboardingServices();
+          }, error => {
+            console.log(error);
+        }); 
+      }
+    }, (resut) => {
+      return;
+    })
+  }
+
+  openAddNewMicroserviceModal(rowData: any){
+    //console.log("openAddNewMicroserviceModal getting called...");
+    const modalRef = this.ngbModal.open(MicroserviceAddDetailsComponent, { size: 'lg' });
+    modalRef.componentInstance.title = 'Microservice Onboarding';
+    if(rowData != 'undefined' && rowData){
+      modalRef.componentInstance.ms = rowData;
+      this.isEditMode = true;
+    }else{
+      modalRef.componentInstance.ms  = {};
+      this.isEditMode = false;
+    }
+    modalRef.componentInstance.passEntry.subscribe((receivedEntry: any) => {
+      //console.log("receivedEntry >>> ",receivedEntry);
+      if(receivedEntry){
+        this.microServiceList = [];
+        this.getOnboardingServices();
+      }
+    });
+  }
+
+  populateTableData(microServiceList: Array<IMircroservies>){
+    this.dataSource = new MatTableDataSource(microServiceList);
+    this.dataSource.sort = this.sort;
+    this.dataSource.paginator = this.paginator;
+  }
+
+  applyFilter(filterValue: string) {
+    this.dataSource.filter = filterValue.trim().toLowerCase();
+  }
+
+  openConfirmationModal(_title: string, _message: string) {
+    const modalInfoRef = this.ngbModal.open(ConfirmationModalComponent);
+    modalInfoRef.componentInstance.title = _title;
+    modalInfoRef.componentInstance.message = _message;
+  }
+
+  openInformationModal(_title: string, _message: string){
+    const modalInfoRef = this.ngbModal.open(InformationModalComponent);
+    modalInfoRef.componentInstance.title = _title;
+    modalInfoRef.componentInstance.message = _message;
+    return modalInfoRef;
+  }
+}
diff --git a/portal-FE-common/src/app/shared/model/account-onboarding/accountOnboarding.ts b/portal-FE-common/src/app/shared/model/account-onboarding/accountOnboarding.ts
new file mode 100644 (file)
index 0000000..c0a5531
--- /dev/null
@@ -0,0 +1,54 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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============================================
+ *
+ * 
+ */
+
+export interface IAccountOnboarding {
+    id ?: any;
+    created ?: any;
+    modified ?: any;
+    createdId ?: any;
+    modifiedId ?: any;
+    rowNum ?: any;
+    auditUserId ?: any;
+    auditTrail ?: any;
+    applicationName ?: any;
+    username ?: any;
+    password ?: any;
+    repassword ?: any;
+    isActive ?: any;
+    endpoints ?: any;
+}
\ No newline at end of file
diff --git a/portal-FE-common/src/app/shared/model/microservice-onboarding/microservices.ts b/portal-FE-common/src/app/shared/model/microservice-onboarding/microservices.ts
new file mode 100644 (file)
index 0000000..db607ef
--- /dev/null
@@ -0,0 +1,58 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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============================================
+ *
+ * 
+ */
+
+export interface IMircroservies {
+       id ?: any;
+       appId ?: any;
+       created ?: any;
+       modified ?: any;
+       createdId ?: any;
+       modifiedId ?: any;
+       rowNum ?: any;
+       auditUserId ?: any;
+       auditTrail ?: any;
+       name ?: any;
+       active ?: any;
+       desc  ?: any;
+       url ?: any;
+       securityType ?: any;
+       username ?: any;
+       password ?: any;
+       parameterList ?: any;
+       option ?: any;
+}
\ No newline at end of file
diff --git a/portal-FE-common/src/app/shared/services/basic-auth-account/basic-auth-account.service.spec.ts b/portal-FE-common/src/app/shared/services/basic-auth-account/basic-auth-account.service.spec.ts
new file mode 100644 (file)
index 0000000..4a6c0f4
--- /dev/null
@@ -0,0 +1,50 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+
+import { TestBed } from '@angular/core/testing';
+
+import { BasicAuthAccountService } from './basic-auth-account.service';
+
+describe('BasicAuthAccountService', () => {
+  beforeEach(() => TestBed.configureTestingModule({}));
+
+  it('should be created', () => {
+    const service: BasicAuthAccountService = TestBed.get(BasicAuthAccountService);
+    expect(service).toBeTruthy();
+  });
+});
diff --git a/portal-FE-common/src/app/shared/services/basic-auth-account/basic-auth-account.service.ts b/portal-FE-common/src/app/shared/services/basic-auth-account/basic-auth-account.service.ts
new file mode 100644 (file)
index 0000000..7741760
--- /dev/null
@@ -0,0 +1,69 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+
+import { Injectable } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+import { environment } from '../../../../environments/environment';
+import { Observable } from 'rxjs';
+
+@Injectable({
+  providedIn: 'root'
+})
+export class BasicAuthAccountService {
+
+  api = environment.api;
+
+  constructor(private http: HttpClient) { }
+
+  createAccount(newAccount: any): Observable<any> {
+    return this.http.post(this.api.basicAuthAccount, newAccount, { withCredentials: true });
+  }
+
+  updateAccount(accountId: any, newAccount: any) {
+    return this.http.put(this.api.basicAuthAccount + "/" + accountId, newAccount, { withCredentials: true } );
+  }
+
+  getAccountList() {
+    return this.http.get(this.api.basicAuthAccount, { withCredentials: true });
+  }
+
+  deleteAccount(accountId: any) {
+    return this.http.delete(this.api.basicAuthAccount + "/" + accountId, { withCredentials: true });
+  }
+
+}
diff --git a/portal-FE-common/src/app/shared/services/contact-us/contact-us.service.spec.ts b/portal-FE-common/src/app/shared/services/contact-us/contact-us.service.spec.ts
new file mode 100644 (file)
index 0000000..03d55d0
--- /dev/null
@@ -0,0 +1,50 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+
+import { TestBed } from '@angular/core/testing';
+
+import { ContactUsService } from './contact-us.service';
+
+describe('ContactUsService', () => {
+  beforeEach(() => TestBed.configureTestingModule({}));
+
+  it('should be created', () => {
+    const service: ContactUsService = TestBed.get(ContactUsService);
+    expect(service).toBeTruthy();
+  });
+});
diff --git a/portal-FE-common/src/app/shared/services/contact-us/contact-us.service.ts b/portal-FE-common/src/app/shared/services/contact-us/contact-us.service.ts
new file mode 100644 (file)
index 0000000..c46abab
--- /dev/null
@@ -0,0 +1,96 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+
+import { Injectable } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+import { environment } from '../../../../environments/environment';
+import { Observable } from 'rxjs';
+import * as uuid from 'uuid';
+
+@Injectable({
+  providedIn: 'root'
+})
+export class ContactUsService {
+
+  api = environment.api;
+  resp:string;
+  headerParams = {'X-Widgets-Type': 'all', 'X-ECOMP-RequestID': uuid.v4() };
+
+  constructor(private http: HttpClient) { }
+
+  getListOfApp(): Observable<any>{ 
+    let getListOfAppURL  = this.api.availableApps;
+    return this.http.get(getListOfAppURL , { withCredentials: true } );
+  }
+
+  getContactUs(): Observable<any>{ 
+    let getContactUsURL  = this.api.getContactUS;
+    return this.http.get(getContactUsURL , { withCredentials: true } );
+  }
+
+  getAppsAndContacts(): Observable<any>{ 
+    let getAppsAndContactsURL  = this.api.getAppsAndContacts;
+    return this.http.get(getAppsAndContactsURL , { withCredentials: true } );
+  }
+
+  getContactUSPortalDetails(): Observable<any>{ 
+    let getContactUSPortalDetailsURL  = this.api.getContactUSPortalDetails;
+    return this.http.get(getContactUSPortalDetailsURL , { withCredentials: true } );
+  }
+
+  getAppCategoryFunctions(): Observable<any>{ 
+    let getAppCategoryFunctionsURL  = this.api.getAppCategoryFunctions;
+    return this.http.get(getAppCategoryFunctionsURL , { withCredentials: true } );
+  }
+
+  addContactUs(newContactUs: any): Observable<any>{
+    let addContactUsURL  = this.api.saveContactUS;
+    return this.http.post(addContactUsURL, newContactUs, { withCredentials: true });
+  }
+
+  modifyContactUs(contactUsObj: any): Observable<any>{
+    let modifyContactUsURL  = this.api.saveContactUS;
+    return this.http.post(modifyContactUsURL, contactUsObj, { withCredentials: true });
+  }
+
+  removeContactUs(id: any): Observable<any>{
+    let removeContactUsURL  = this.api.deleteContactUS + '/' + id;
+    return this.http.post(removeContactUsURL, { withCredentials: true });
+  }
+
+}
diff --git a/portal-FE-common/src/app/shared/services/microservice/microservice.service.spec.ts b/portal-FE-common/src/app/shared/services/microservice/microservice.service.spec.ts
new file mode 100644 (file)
index 0000000..439a948
--- /dev/null
@@ -0,0 +1,49 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+import { TestBed } from '@angular/core/testing';
+
+import { MicroserviceService } from './microservice.service';
+
+describe('MicroserviceService', () => {
+  beforeEach(() => TestBed.configureTestingModule({}));
+
+  it('should be created', () => {
+    const service: MicroserviceService = TestBed.get(MicroserviceService);
+    expect(service).toBeTruthy();
+  });
+});
diff --git a/portal-FE-common/src/app/shared/services/microservice/microservice.service.ts b/portal-FE-common/src/app/shared/services/microservice/microservice.service.ts
new file mode 100644 (file)
index 0000000..da73139
--- /dev/null
@@ -0,0 +1,86 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+
+import { Injectable } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+import { environment } from '../../../../environments/environment';
+import { Observable } from 'rxjs';
+
+@Injectable({
+  providedIn: 'root'
+})
+export class MicroserviceService {
+
+  api = environment.api;
+
+  constructor(private http: HttpClient) { }
+
+  createService(newMicroservice: any): Observable<any> {
+    return this.http.post(this.api.widgetCommon, newMicroservice, { withCredentials: true } );
+  }
+
+  updateService(serviceId: string, newMicroservice: any): Observable<any> {
+    return this.http.put(this.api.widgetCommon + "/" + serviceId, newMicroservice, { withCredentials: true } );
+  }
+
+  deleteService(serviceId: any): Observable<any> {
+    let deleteServiceURL = this.api.widgetCommon + "/" + serviceId;
+    return this.http.delete(deleteServiceURL, { withCredentials: true });
+  }
+
+  getServiceList(): Observable<any> {
+    return this.http.get(this.api.widgetCommon, { withCredentials: true });
+  }
+
+  getWidgetListByService(serviceId: string): Observable<any> {
+    return this.http.get(this.api.widgetCommon + '/' + serviceId, { withCredentials: true });
+  }
+
+  getUserParameterById(paramId: string): Observable<any> {
+    return this.http.get(this.api.widgetCommon + '/services/' +  paramId, { withCredentials: true });
+  }
+
+  deleteUserParameterById(paramId: string): Observable<any> {
+    return this.http.delete(this.api.widgetCommon + '/services/' +  paramId, { withCredentials: true });
+  }
+
+  getServiceJSON(serviceId: string): Observable<any> {
+    return this.http.get(this.api.microserviceProxy + "/" + serviceId, { withCredentials: true });
+  }
+}
diff --git a/portal-FE-common/src/assets/images/spinner.gif b/portal-FE-common/src/assets/images/spinner.gif
new file mode 100644 (file)
index 0000000..c97ec6e
Binary files /dev/null and b/portal-FE-common/src/assets/images/spinner.gif differ
diff --git a/portal-FE-common/src/styles/_fonts.scss b/portal-FE-common/src/styles/_fonts.scss
new file mode 100644 (file)
index 0000000..7711831
--- /dev/null
@@ -0,0 +1,61 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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============================================
+ *
+ * 
+ */
+@font-face {
+  font-family: Omnes-ECOMP-W02, Arial;
+  src: local("Omnes-ECOMP-W02"), url(../assets/fonts/omnesatt2-regular-webfont.ttf) format("truetype"),
+    url(../assets/fonts/omnesatt2-regular-webfont.woff) format("woff"),
+    url(../assets/fonts/omnesatt2-regular-webfont.eot) format("eot");
+}
+
+@font-face {
+  font-family: Omnes-ECOMP-W02-Medium, Arial;
+  src: url(../assets/fonts/omnesatt2-medium-webfont.ttf) format("truetype");
+}
+
+@font-face {
+  font-family: Omnes-ECOMP-W02-Light, Arial;
+  src: url(../assets/fonts/omnesatt2-light-webfont.ttf) format("truetype");
+}
+@font-face {
+  font-family: Omnes-ECOMP-W02-Italic, Arial;
+  src: url(../assets/fonts/omnesatt2-lightitalic-webfont.ttf) format("truetype");
+}
+@font-face {
+  font-family: Omnes-ECOMP-W02-Bold, Arial;
+  src: url(../assets/fonts/omnesatt2-bold-webfont.ttf) format("truetype");
+}
diff --git a/portal-FE-common/src/styles/_responsive.scss b/portal-FE-common/src/styles/_responsive.scss
new file mode 100644 (file)
index 0000000..0e659d9
--- /dev/null
@@ -0,0 +1,44 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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============================================
+ *
+ * 
+ */
+@media screen and (max-width: 992px) {
+    .push-right {
+        .sidebar {
+            left: 270px !important;
+        }
+    }
+}
diff --git a/portal-FE-common/src/styles/_spinner.scss b/portal-FE-common/src/styles/_spinner.scss
new file mode 100644 (file)
index 0000000..406ca78
--- /dev/null
@@ -0,0 +1,67 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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============================================
+ *
+ * 
+ */
+.ecomp-spinner {
+    background: url('../assets/images/spinner.gif') top left no-repeat;
+    width: 32px;
+    height: 32px;
+    position: absolute;
+    top: 35%;
+    left: calc(50% - 32px/2);
+}
+.ecomp-save-spinner {
+    background: url('../assets/images/spinner.gif') top left no-repeat;
+    width: 25px;
+    height: 25px;
+    background-size: 25px;
+    position: absolute;
+    left: -50px;
+    top: 2px;
+}
+.ecomp-small-spinner {
+    background: url('../assets/images/spinner.gif') top left no-repeat;
+    width: 25px;
+    height: 25px;
+    background-size: 25px;
+    position: relative;
+    display: inline-block;
+    vertical-align: 2px;
+    cursor: pointer;
+    top: 6px;
+    color: transparent;
+    margin-left: 8px;
+}
diff --git a/portal-FE-common/src/styles/_utils.scss b/portal-FE-common/src/styles/_utils.scss
new file mode 100644 (file)
index 0000000..8fabfe2
--- /dev/null
@@ -0,0 +1,40 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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============================================
+ *
+ * 
+ */
+.fs-12 {
+    font-size: 12px;
+}
diff --git a/portal-FE-common/src/styles/app.scss b/portal-FE-common/src/styles/app.scss
new file mode 100644 (file)
index 0000000..643948c
--- /dev/null
@@ -0,0 +1,154 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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============================================
+ *
+ * 
+ */
+/* You can add global styles to this file, and also import other style files */
+@import "~@angular/material/prebuilt-themes/indigo-pink.css";
+@import "bootstrap/bootstrap";
+@import "utils";
+@import "responsive";
+@import "spinner";
+@import "fonts";
+
+body {
+  font-family: "Open Sans", Arial, sans-serif !important;
+  overflow: hidden;
+  box-sizing: border-box;
+}
+
+.cdk-global-overlay-wrapper, .cdk-overlay-container {
+  z-index: 99999 !important;
+}
+
+table {
+  width: 100%;
+}
+
+.modal-content {
+  border-radius: 0.6rem !important;
+}
+
+.modal-header {
+  border-bottom: none;
+}
+
+.modal-dialog {
+  max-width: 565px;
+}
+.container{
+  padding-top: 1%;
+}
+
+.btn{
+  border: 1px solid transparent;
+  box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.15);
+  cursor: pointer;
+  display: inline-block;
+  font-weight: normal;
+  line-height: 1;
+  margin: 0 7px 10px 0;
+  max-width: 470px;
+  min-width: 70px;
+  position: relative;
+  text-align: center;
+  vertical-align: middle;
+  white-space: nowrap;
+  overflow: hidden;
+}
+
+.btn.btn-primary {
+  float: right;
+  border-color: #087ac2 transparent #0568ae;
+  background-color: #0568ae;
+  background: linear-gradient(to bottom, #087ac2 0%, #0568ae 100%);
+  box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.15);
+  color: #ffffff;
+  border: 1px solid transparent;
+  padding: 10px 19px 9px 18px;
+  border-radius: 8px;
+}
+
+@media print {
+  .breadcrumb {
+    display: none !important;
+  }
+}
+
+.mat-checkbox-checked.mat-accent .mat-checkbox-background, .mat-checkbox-indeterminate.mat-accent .mat-checkbox-background {
+  background-color: #0775bc;
+}
+
+.mat-checkbox:not(.mat-checkbox-disabled).mat-accent .mat-checkbox-ripple .mat-ripple-element {
+  background-color: #0775bc;
+}
+
+.mat-slide-toggle.mat-checked:not(.mat-disabled) .mat-slide-toggle-bar {
+  background-color: #0878bf;
+}
+
+.mat-slide-toggle.mat-checked:not(.mat-disabled) .mat-slide-toggle-thumb {
+  background-color: #f8f9fa;
+}
+
+.mat-radio-button.mat-accent.mat-radio-checked .mat-radio-outer-circle {
+  border-color: #0878bf;
+}
+
+.mat-radio-button.mat-accent .mat-radio-inner-circle, .mat-radio-button.mat-accent .mat-radio-ripple .mat-ripple-element:not(.mat-radio-persistent-ripple), .mat-radio-button.mat-accent.mat-radio-checked .mat-radio-persistent-ripple, .mat-radio-button.mat-accent:active .mat-radio-persistent-ripple {
+  background-color: #0878bf;
+}
+
+.mat-primary .mat-option.mat-selected:not(.mat-option-disabled) {
+  color: #0776bd;
+}
+
+.mat-primary .mat-pseudo-checkbox-checked, .mat-primary .mat-pseudo-checkbox-indeterminate {
+  background: #0775bc;
+}
+
+.mat-grid-tile .mat-figure{top:0;left:0;right:0;bottom:0;position:absolute;display:flex;align-items:initial !important;justify-content:flex-start !important;height:100%;padding:0;margin:0}
+.mat-ink-bar{ height: 0px !important;}
+.mat-tab-label{font-weight: 1000;}
+
+.mat-checkbox:not(.mat-checkbox-disabled).mat-accent .mat-checkbox-ripple .mat-ripple-element {
+  background-color: #0776bd;
+}
+
+.mat-checkbox-checked.mat-accent .mat-checkbox-background, .mat-checkbox-indeterminate.mat-accent .mat-checkbox-background {
+  background-color: #0776bd;
+}
+
+
diff --git a/portal-FE-common/src/styles/bootstrap/_alert.scss b/portal-FE-common/src/styles/bootstrap/_alert.scss
new file mode 100644 (file)
index 0000000..c2d5c81
--- /dev/null
@@ -0,0 +1,51 @@
+//
+// Base styles
+//
+
+.alert {
+  position: relative;
+  padding: $alert-padding-y $alert-padding-x;
+  margin-bottom: $alert-margin-bottom;
+  border: $alert-border-width solid transparent;
+  @include border-radius($alert-border-radius);
+}
+
+// Headings for larger alerts
+.alert-heading {
+  // Specified to prevent conflicts of changing $headings-color
+  color: inherit;
+}
+
+// Provide class for links that match alerts
+.alert-link {
+  font-weight: $alert-link-font-weight;
+}
+
+
+// Dismissible alerts
+//
+// Expand the right padding and account for the close button's positioning.
+
+.alert-dismissible {
+  padding-right: ($close-font-size + $alert-padding-x * 2);
+
+  // Adjust close link position
+  .close {
+    position: absolute;
+    top: 0;
+    right: 0;
+    padding: $alert-padding-y $alert-padding-x;
+    color: inherit;
+  }
+}
+
+
+// Alternate styles
+//
+// Generate contextual modifier classes for colorizing the alert.
+
+@each $color, $value in $theme-colors {
+  .alert-#{$color} {
+    @include alert-variant(theme-color-level($color, -10), theme-color-level($color, -9), theme-color-level($color, 6));
+  }
+}
diff --git a/portal-FE-common/src/styles/bootstrap/_badge.scss b/portal-FE-common/src/styles/bootstrap/_badge.scss
new file mode 100644 (file)
index 0000000..b87a1b0
--- /dev/null
@@ -0,0 +1,47 @@
+// Base class
+//
+// Requires one of the contextual, color modifier classes for `color` and
+// `background-color`.
+
+.badge {
+  display: inline-block;
+  padding: $badge-padding-y $badge-padding-x;
+  font-size: $badge-font-size;
+  font-weight: $badge-font-weight;
+  line-height: 1;
+  text-align: center;
+  white-space: nowrap;
+  vertical-align: baseline;
+  @include border-radius($badge-border-radius);
+
+  // Empty badges collapse automatically
+  &:empty {
+    display: none;
+  }
+}
+
+// Quick fix for badges in buttons
+.btn .badge {
+  position: relative;
+  top: -1px;
+}
+
+// Pill badges
+//
+// Make them extra rounded with a modifier to replace v3's badges.
+
+.badge-pill {
+  padding-right: $badge-pill-padding-x;
+  padding-left: $badge-pill-padding-x;
+  @include border-radius($badge-pill-border-radius);
+}
+
+// Colors
+//
+// Contextual variations (linked badges get darker on :hover).
+
+@each $color, $value in $theme-colors {
+  .badge-#{$color} {
+    @include badge-variant($value);
+  }
+}
diff --git a/portal-FE-common/src/styles/bootstrap/_breadcrumb.scss b/portal-FE-common/src/styles/bootstrap/_breadcrumb.scss
new file mode 100644 (file)
index 0000000..25b9d85
--- /dev/null
@@ -0,0 +1,38 @@
+.breadcrumb {
+  display: flex;
+  flex-wrap: wrap;
+  padding: $breadcrumb-padding-y $breadcrumb-padding-x;
+  margin-bottom: $breadcrumb-margin-bottom;
+  list-style: none;
+  background-color: $breadcrumb-bg;
+  @include border-radius($border-radius);
+}
+
+.breadcrumb-item {
+  // The separator between breadcrumbs (by default, a forward-slash: "/")
+  + .breadcrumb-item::before {
+    display: inline-block; // Suppress underlining of the separator in modern browsers
+    padding-right: $breadcrumb-item-padding;
+    padding-left: $breadcrumb-item-padding;
+    color: $breadcrumb-divider-color;
+    content: "#{$breadcrumb-divider}";
+  }
+
+  // IE9-11 hack to properly handle hyperlink underlines for breadcrumbs built
+  // without `<ul>`s. The `::before` pseudo-element generates an element
+  // *within* the .breadcrumb-item and thereby inherits the `text-decoration`.
+  //
+  // To trick IE into suppressing the underline, we give the pseudo-element an
+  // underline and then immediately remove it.
+  + .breadcrumb-item:hover::before {
+    text-decoration: underline;
+  }
+  // stylelint-disable-next-line no-duplicate-selectors
+  + .breadcrumb-item:hover::before {
+    text-decoration: none;
+  }
+
+  &.active {
+    color: $breadcrumb-active-color;
+  }
+}
diff --git a/portal-FE-common/src/styles/bootstrap/_button-group.scss b/portal-FE-common/src/styles/bootstrap/_button-group.scss
new file mode 100644 (file)
index 0000000..c1b8265
--- /dev/null
@@ -0,0 +1,166 @@
+// stylelint-disable selector-no-qualifying-type
+
+// Make the div behave like a button
+.btn-group,
+.btn-group-vertical {
+  position: relative;
+  display: inline-flex;
+  vertical-align: middle; // match .btn alignment given font-size hack above
+
+  > .btn {
+    position: relative;
+    flex: 0 1 auto;
+
+    // Bring the hover, focused, and "active" buttons to the front to overlay
+    // the borders properly
+    @include hover {
+      z-index: 1;
+    }
+    &:focus,
+    &:active,
+    &.active {
+      z-index: 1;
+    }
+  }
+
+  // Prevent double borders when buttons are next to each other
+  .btn + .btn,
+  .btn + .btn-group,
+  .btn-group + .btn,
+  .btn-group + .btn-group {
+    margin-left: -$btn-border-width;
+  }
+}
+
+// Optional: Group multiple button groups together for a toolbar
+.btn-toolbar {
+  display: flex;
+  flex-wrap: wrap;
+  justify-content: flex-start;
+
+  .input-group {
+    width: auto;
+  }
+}
+
+.btn-group {
+  > .btn:first-child {
+    margin-left: 0;
+  }
+
+  // Reset rounded corners
+  > .btn:not(:last-child):not(.dropdown-toggle),
+  > .btn-group:not(:last-child) > .btn {
+    @include border-right-radius(0);
+  }
+
+  > .btn:not(:first-child),
+  > .btn-group:not(:first-child) > .btn {
+    @include border-left-radius(0);
+  }
+}
+
+// Sizing
+//
+// Remix the default button sizing classes into new ones for easier manipulation.
+
+.btn-group-sm > .btn { @extend .btn-sm; }
+.btn-group-lg > .btn { @extend .btn-lg; }
+
+
+//
+// Split button dropdowns
+//
+
+.dropdown-toggle-split {
+  padding-right: $btn-padding-x * .75;
+  padding-left: $btn-padding-x * .75;
+
+  &::after {
+    margin-left: 0;
+  }
+}
+
+.btn-sm + .dropdown-toggle-split {
+  padding-right: $btn-padding-x-sm * .75;
+  padding-left: $btn-padding-x-sm * .75;
+}
+
+.btn-lg + .dropdown-toggle-split {
+  padding-right: $btn-padding-x-lg * .75;
+  padding-left: $btn-padding-x-lg * .75;
+}
+
+
+// The clickable button for toggling the menu
+// Set the same inset shadow as the :active state
+.btn-group.show .dropdown-toggle {
+  @include box-shadow($btn-active-box-shadow);
+
+  // Show no shadow for `.btn-link` since it has no other button styles.
+  &.btn-link {
+    @include box-shadow(none);
+  }
+}
+
+
+//
+// Vertical button groups
+//
+
+.btn-group-vertical {
+  flex-direction: column;
+  align-items: flex-start;
+  justify-content: center;
+
+  .btn,
+  .btn-group {
+    width: 100%;
+  }
+
+  > .btn + .btn,
+  > .btn + .btn-group,
+  > .btn-group + .btn,
+  > .btn-group + .btn-group {
+    margin-top: -$btn-border-width;
+    margin-left: 0;
+  }
+
+  // Reset rounded corners
+  > .btn:not(:last-child):not(.dropdown-toggle),
+  > .btn-group:not(:last-child) > .btn {
+    @include border-bottom-radius(0);
+  }
+
+  > .btn:not(:first-child),
+  > .btn-group:not(:first-child) > .btn {
+    @include border-top-radius(0);
+  }
+}
+
+
+// Checkbox and radio options
+//
+// In order to support the browser's form validation feedback, powered by the
+// `required` attribute, we have to "hide" the inputs via `clip`. We cannot use
+// `display: none;` or `visibility: hidden;` as that also hides the popover.
+// Simply visually hiding the inputs via `opacity` would leave them clickable in
+// certain cases which is prevented by using `clip` and `pointer-events`.
+// This way, we ensure a DOM element is visible to position the popover from.
+//
+// See https://github.com/twbs/bootstrap/pull/12794 and
+// https://github.com/twbs/bootstrap/pull/14559 for more information.
+
+.btn-group-toggle {
+  > .btn,
+  > .btn-group > .btn {
+    margin-bottom: 0; // Override default `<label>` value
+
+    input[type="radio"],
+    input[type="checkbox"] {
+      position: absolute;
+      clip: rect(0, 0, 0, 0);
+      pointer-events: none;
+    }
+  }
+}
diff --git a/portal-FE-common/src/styles/bootstrap/_buttons.scss b/portal-FE-common/src/styles/bootstrap/_buttons.scss
new file mode 100644 (file)
index 0000000..3a5f5ee
--- /dev/null
@@ -0,0 +1,147 @@
+// stylelint-disable selector-no-qualifying-type
+
+//
+// Base styles
+//
+
+.btn {
+  display: inline-block;
+  font-weight: $btn-font-weight;
+  text-align: center;
+  white-space: nowrap;
+  vertical-align: middle;
+  user-select: none;
+  border: $btn-border-width solid transparent;
+  @include button-size($btn-padding-y, $btn-padding-x, $font-size-base, $btn-line-height, $btn-border-radius);
+  @include transition($btn-transition);
+
+  // Share hover and focus styles
+  @include hover-focus {
+    text-decoration: none;
+  }
+
+  &:focus,
+  &.focus {
+    outline: 0;
+    box-shadow: $btn-focus-box-shadow;
+  }
+
+  // Disabled comes first so active can properly restyle
+  &.disabled,
+  &:disabled {
+    opacity: $btn-disabled-opacity;
+    @include box-shadow(none);
+  }
+
+  // Opinionated: add "hand" cursor to non-disabled .btn elements
+  &:not([disabled]):not(.disabled) {
+    cursor: pointer;
+  }
+
+  &:not([disabled]):not(.disabled):active,
+  &:not([disabled]):not(.disabled).active {
+    background-image: none;
+    @include box-shadow($btn-active-box-shadow);
+
+    &:focus {
+      @include box-shadow($btn-focus-box-shadow, $btn-active-box-shadow);
+    }
+  }
+}
+
+// Future-proof disabling of clicks on `<a>` elements
+a.btn.disabled,
+fieldset[disabled] a.btn {
+  pointer-events: none;
+}
+
+
+//
+// Alternate buttons
+//
+
+@each $color, $value in $theme-colors {
+  .btn-#{$color} {
+    @include button-variant($value, $value);
+  }
+}
+
+@each $color, $value in $theme-colors {
+  .btn-outline-#{$color} {
+    @if $color == "light" {
+      @include button-outline-variant($value, $gray-900);
+    } @else {
+      @include button-outline-variant($value, $white);
+    }
+  }
+}
+
+
+//
+// Link buttons
+//
+
+// Make a button look and behave like a link
+.btn-link {
+  font-weight: $font-weight-normal;
+  color: $link-color;
+  background-color: transparent;
+
+  @include hover {
+    color: $link-hover-color;
+    text-decoration: $link-hover-decoration;
+    background-color: transparent;
+    border-color: transparent;
+  }
+
+  &:focus,
+  &.focus {
+    text-decoration: $link-hover-decoration;
+    border-color: transparent;
+    box-shadow: none;
+  }
+
+  &:disabled,
+  &.disabled {
+    color: $btn-link-disabled-color;
+  }
+
+  // No need for an active state here
+}
+
+
+//
+// Button Sizes
+//
+
+.btn-lg {
+  @include button-size($btn-padding-y-lg, $btn-padding-x-lg, $font-size-lg, $btn-line-height-lg, $btn-border-radius-lg);
+}
+
+.btn-sm {
+  @include button-size($btn-padding-y-sm, $btn-padding-x-sm, $font-size-sm, $btn-line-height-sm, $btn-border-radius-sm);
+}
+
+
+//
+// Block button
+//
+
+.btn-block {
+  display: block;
+  width: 100%;
+
+  // Vertically space out multiple block buttons
+  + .btn-block {
+    margin-top: $btn-block-spacing-y;
+  }
+}
+
+// Specificity overrides
+input[type="submit"],
+input[type="reset"],
+input[type="button"] {
+  &.btn-block {
+    width: 100%;
+  }
+}
diff --git a/portal-FE-common/src/styles/bootstrap/_card.scss b/portal-FE-common/src/styles/bootstrap/_card.scss
new file mode 100644 (file)
index 0000000..4c4845c
--- /dev/null
@@ -0,0 +1,270 @@
+//
+// Base styles
+//
+
+.card {
+  position: relative;
+  display: flex;
+  flex-direction: column;
+  min-width: 0;
+  word-wrap: break-word;
+  background-color: $card-bg;
+  background-clip: border-box;
+  border: $card-border-width solid $card-border-color;
+  @include border-radius($card-border-radius);
+
+  > hr {
+    margin-right: 0;
+    margin-left: 0;
+  }
+
+  > .list-group:first-child {
+    .list-group-item:first-child {
+      @include border-top-radius($card-border-radius);
+    }
+  }
+
+  > .list-group:last-child {
+    .list-group-item:last-child {
+      @include border-bottom-radius($card-border-radius);
+    }
+  }
+}
+
+.card-body {
+  // Enable `flex-grow: 1` for decks and groups so that card blocks take up
+  // as much space as possible, ensuring footers are aligned to the bottom.
+  flex: 1 1 auto;
+  padding: $card-spacer-x;
+}
+
+.card-title {
+  margin-bottom: $card-spacer-y;
+}
+
+.card-subtitle {
+  margin-top: -($card-spacer-y / 2);
+  margin-bottom: 0;
+}
+
+.card-text:last-child {
+  margin-bottom: 0;
+}
+
+.card-link {
+  @include hover {
+    text-decoration: none;
+  }
+
+  + .card-link {
+    margin-left: $card-spacer-x;
+  }
+}
+
+//
+// Optional textual caps
+//
+
+.card-header {
+  padding: $card-spacer-y $card-spacer-x;
+  margin-bottom: 0; // Removes the default margin-bottom of <hN>
+  background-color: $card-cap-bg;
+  border-bottom: $card-border-width solid $card-border-color;
+
+  &:first-child {
+    @include border-radius($card-inner-border-radius $card-inner-border-radius 0 0);
+  }
+
+  + .list-group {
+    .list-group-item:first-child {
+      border-top: 0;
+    }
+  }
+}
+
+.card-footer {
+  padding: $card-spacer-y $card-spacer-x;
+  background-color: $card-cap-bg;
+  border-top: $card-border-width solid $card-border-color;
+
+  &:last-child {
+    @include border-radius(0 0 $card-inner-border-radius $card-inner-border-radius);
+  }
+}
+
+
+//
+// Header navs
+//
+
+.card-header-tabs {
+  margin-right: -($card-spacer-x / 2);
+  margin-bottom: -$card-spacer-y;
+  margin-left: -($card-spacer-x / 2);
+  border-bottom: 0;
+}
+
+.card-header-pills {
+  margin-right: -($card-spacer-x / 2);
+  margin-left: -($card-spacer-x / 2);
+}
+
+// Card image
+.card-img-overlay {
+  position: absolute;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  padding: $card-img-overlay-padding;
+}
+
+.card-img {
+  width: 100%; // Required because we use flexbox and this inherently applies align-self: stretch
+  @include border-radius($card-inner-border-radius);
+}
+
+// Card image caps
+.card-img-top {
+  width: 100%; // Required because we use flexbox and this inherently applies align-self: stretch
+  @include border-top-radius($card-inner-border-radius);
+}
+
+.card-img-bottom {
+  width: 100%; // Required because we use flexbox and this inherently applies align-self: stretch
+  @include border-bottom-radius($card-inner-border-radius);
+}
+
+
+// Card deck
+
+.card-deck {
+  display: flex;
+  flex-direction: column;
+
+  .card {
+    margin-bottom: $card-deck-margin;
+  }
+
+  @include media-breakpoint-up(sm) {
+    flex-flow: row wrap;
+    margin-right: -$card-deck-margin;
+    margin-left: -$card-deck-margin;
+
+    .card {
+      display: flex;
+      // Flexbugs #4: https://github.com/philipwalton/flexbugs#4-flex-shorthand-declarations-with-unitless-flex-basis-values-are-ignored
+      flex: 1 0 0%;
+      flex-direction: column;
+      margin-right: $card-deck-margin;
+      margin-bottom: 0; // Override the default
+      margin-left: $card-deck-margin;
+    }
+  }
+}
+
+
+//
+// Card groups
+//
+
+.card-group {
+  display: flex;
+  flex-direction: column;
+
+  // The child selector allows nested `.card` within `.card-group`
+  // to display properly.
+  > .card {
+    margin-bottom: $card-group-margin;
+  }
+
+  @include media-breakpoint-up(sm) {
+    flex-flow: row wrap;
+    // The child selector allows nested `.card` within `.card-group`
+    // to display properly.
+    > .card {
+      // Flexbugs #4: https://github.com/philipwalton/flexbugs#4-flex-shorthand-declarations-with-unitless-flex-basis-values-are-ignored
+      flex: 1 0 0%;
+      margin-bottom: 0;
+
+      + .card {
+        margin-left: 0;
+        border-left: 0;
+      }
+
+      // Handle rounded corners
+      @if $enable-rounded {
+        &:first-child {
+          @include border-right-radius(0);
+
+          .card-img-top,
+          .card-header {
+            border-top-right-radius: 0;
+          }
+          .card-img-bottom,
+          .card-footer {
+            border-bottom-right-radius: 0;
+          }
+        }
+
+        &:last-child {
+          @include border-left-radius(0);
+
+          .card-img-top,
+          .card-header {
+            border-top-left-radius: 0;
+          }
+          .card-img-bottom,
+          .card-footer {
+            border-bottom-left-radius: 0;
+          }
+        }
+
+        &:only-child {
+          @include border-radius($card-border-radius);
+
+          .card-img-top,
+          .card-header {
+            @include border-top-radius($card-border-radius);
+          }
+          .card-img-bottom,
+          .card-footer {
+            @include border-bottom-radius($card-border-radius);
+          }
+        }
+
+        &:not(:first-child):not(:last-child):not(:only-child) {
+          @include border-radius(0);
+
+          .card-img-top,
+          .card-img-bottom,
+          .card-header,
+          .card-footer {
+            @include border-radius(0);
+          }
+        }
+      }
+    }
+  }
+}
+
+
+//
+// Columns
+//
+
+.card-columns {
+  .card {
+    margin-bottom: $card-columns-margin;
+  }
+
+  @include media-breakpoint-up(sm) {
+    column-count: $card-columns-count;
+    column-gap: $card-columns-gap;
+
+    .card {
+      display: inline-block; // Don't let them vertically span multiple columns
+      width: 100%; // Don't let their width change
+    }
+  }
+}
diff --git a/portal-FE-common/src/styles/bootstrap/_carousel.scss b/portal-FE-common/src/styles/bootstrap/_carousel.scss
new file mode 100644 (file)
index 0000000..72a5034
--- /dev/null
@@ -0,0 +1,191 @@
+// Wrapper for the slide container and indicators
+.carousel {
+  position: relative;
+}
+
+.carousel-inner {
+  position: relative;
+  width: 100%;
+  overflow: hidden;
+}
+
+.carousel-item {
+  position: relative;
+  display: none;
+  align-items: center;
+  width: 100%;
+  @include transition($carousel-transition);
+  backface-visibility: hidden;
+  perspective: 1000px;
+}
+
+.carousel-item.active,
+.carousel-item-next,
+.carousel-item-prev {
+  display: block;
+}
+
+.carousel-item-next,
+.carousel-item-prev {
+  position: absolute;
+  top: 0;
+}
+
+// CSS3 transforms when supported by the browser
+.carousel-item-next.carousel-item-left,
+.carousel-item-prev.carousel-item-right {
+  transform: translateX(0);
+
+  @supports (transform-style: preserve-3d) {
+    transform: translate3d(0, 0, 0);
+  }
+}
+
+.carousel-item-next,
+.active.carousel-item-right {
+  transform: translateX(100%);
+
+  @supports (transform-style: preserve-3d) {
+    transform: translate3d(100%, 0, 0);
+  }
+}
+
+.carousel-item-prev,
+.active.carousel-item-left {
+  transform: translateX(-100%);
+
+  @supports (transform-style: preserve-3d) {
+    transform: translate3d(-100%, 0, 0);
+  }
+}
+
+
+//
+// Left/right controls for nav
+//
+
+.carousel-control-prev,
+.carousel-control-next {
+  position: absolute;
+  top: 0;
+  bottom: 0;
+  // Use flex for alignment (1-3)
+  display: flex; // 1. allow flex styles
+  align-items: center; // 2. vertically center contents
+  justify-content: center; // 3. horizontally center contents
+  width: $carousel-control-width;
+  color: $carousel-control-color;
+  text-align: center;
+  opacity: $carousel-control-opacity;
+  // We can't have a transition here because WebKit cancels the carousel
+  // animation if you trip this while in the middle of another animation.
+
+  // Hover/focus state
+  @include hover-focus {
+    color: $carousel-control-color;
+    text-decoration: none;
+    outline: 0;
+    opacity: .9;
+  }
+}
+.carousel-control-prev {
+  left: 0;
+  @if $enable-gradients {
+    background: linear-gradient(90deg, rgba(0, 0, 0, .25), rgba(0, 0, 0, .001));
+  }
+}
+.carousel-control-next {
+  right: 0;
+  @if $enable-gradients {
+    background: linear-gradient(270deg, rgba(0, 0, 0, .25), rgba(0, 0, 0, .001));
+  }
+}
+
+// Icons for within
+.carousel-control-prev-icon,
+.carousel-control-next-icon {
+  display: inline-block;
+  width: $carousel-control-icon-width;
+  height: $carousel-control-icon-width;
+  background: transparent no-repeat center center;
+  background-size: 100% 100%;
+}
+.carousel-control-prev-icon {
+  background-image: $carousel-control-prev-icon-bg;
+}
+.carousel-control-next-icon {
+  background-image: $carousel-control-next-icon-bg;
+}
+
+
+// Optional indicator pips
+//
+// Add an ordered list with the following class and add a list item for each
+// slide your carousel holds.
+
+.carousel-indicators {
+  position: absolute;
+  right: 0;
+  bottom: 10px;
+  left: 0;
+  z-index: 15;
+  display: flex;
+  justify-content: center;
+  padding-left: 0; // override <ol> default
+  // Use the .carousel-control's width as margin so we don't overlay those
+  margin-right: $carousel-control-width;
+  margin-left: $carousel-control-width;
+  list-style: none;
+
+  li {
+    position: relative;
+    flex: 0 1 auto;
+    width: $carousel-indicator-width;
+    height: $carousel-indicator-height;
+    margin-right: $carousel-indicator-spacer;
+    margin-left: $carousel-indicator-spacer;
+    text-indent: -999px;
+    background-color: rgba($carousel-indicator-active-bg, .5);
+
+    // Use pseudo classes to increase the hit area by 10px on top and bottom.
+    &::before {
+      position: absolute;
+      top: -10px;
+      left: 0;
+      display: inline-block;
+      width: 100%;
+      height: 10px;
+      content: "";
+    }
+    &::after {
+      position: absolute;
+      bottom: -10px;
+      left: 0;
+      display: inline-block;
+      width: 100%;
+      height: 10px;
+      content: "";
+    }
+  }
+
+  .active {
+    background-color: $carousel-indicator-active-bg;
+  }
+}
+
+
+// Optional captions
+//
+//
+
+.carousel-caption {
+  position: absolute;
+  right: ((100% - $carousel-caption-width) / 2);
+  bottom: 20px;
+  left: ((100% - $carousel-caption-width) / 2);
+  z-index: 10;
+  padding-top: 20px;
+  padding-bottom: 20px;
+  color: $carousel-caption-color;
+  text-align: center;
+}
diff --git a/portal-FE-common/src/styles/bootstrap/_close.scss b/portal-FE-common/src/styles/bootstrap/_close.scss
new file mode 100644 (file)
index 0000000..f1763cc
--- /dev/null
@@ -0,0 +1,34 @@
+.close {
+  float: right;
+  font-size: $close-font-size;
+  font-weight: $close-font-weight;
+  line-height: 1;
+  color: $close-color;
+  text-shadow: $close-text-shadow;
+  opacity: .5;
+
+  @include hover-focus {
+    color: $close-color;
+    text-decoration: none;
+    opacity: .75;
+  }
+
+  // Opinionated: add "hand" cursor to non-disabled .close elements
+  &:not([disabled]):not(.disabled) {
+    cursor: pointer;
+  }
+}
+
+// Additional properties for button version
+// iOS requires the button element instead of an anchor tag.
+// If you want the anchor version, it requires `href="#"`.
+// See https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile
+
+// stylelint-disable property-no-vendor-prefix, selector-no-qualifying-type
+button.close {
+  padding: 0;
+  background-color: transparent;
+  border: 0;
+  -webkit-appearance: none;
+}
+// stylelint-enable
diff --git a/portal-FE-common/src/styles/bootstrap/_code.scss b/portal-FE-common/src/styles/bootstrap/_code.scss
new file mode 100644 (file)
index 0000000..9de20fa
--- /dev/null
@@ -0,0 +1,56 @@
+// Inline and block code styles
+code,
+kbd,
+pre,
+samp {
+  font-family: $font-family-monospace;
+}
+
+// Inline code
+code {
+  font-size: $code-font-size;
+  color: $code-color;
+  word-break: break-word;
+
+  // Streamline the style when inside anchors to avoid broken underline and more
+  a > & {
+    color: inherit;
+  }
+}
+
+// User input typically entered via keyboard
+kbd {
+  padding: $kbd-padding-y $kbd-padding-x;
+  font-size: $kbd-font-size;
+  color: $kbd-color;
+  background-color: $kbd-bg;
+  @include border-radius($border-radius-sm);
+  @include box-shadow($kbd-box-shadow);
+
+  kbd {
+    padding: 0;
+    font-size: 100%;
+    font-weight: $nested-kbd-font-weight;
+    @include box-shadow(none);
+  }
+}
+
+// Blocks of code
+pre {
+  display: block;
+  font-size: $code-font-size;
+  color: $pre-color;
+
+  // Account for some code outputs that place code tags in pre tags
+  code {
+    font-size: inherit;
+    color: inherit;
+    word-break: normal;
+  }
+}
+
+// Enable scrollable blocks of code
+.pre-scrollable {
+  max-height: $pre-scrollable-max-height;
+  overflow-y: scroll;
+}
diff --git a/portal-FE-common/src/styles/bootstrap/_custom-forms.scss b/portal-FE-common/src/styles/bootstrap/_custom-forms.scss
new file mode 100644 (file)
index 0000000..d99a86d
--- /dev/null
@@ -0,0 +1,282 @@
+// Embedded icons from Open Iconic.
+// Released under MIT and copyright 2014 Waybury.
+// https://useiconic.com/open
+
+
+// Checkboxes and radios
+//
+// Base class takes care of all the key behavioral aspects.
+
+.custom-control {
+  position: relative;
+  display: block;
+  min-height: (1rem * $line-height-base);
+  padding-left: $custom-control-gutter;
+}
+
+.custom-control-inline {
+  display: inline-flex;
+  margin-right: $custom-control-spacer-x;
+}
+
+.custom-control-input {
+  position: absolute;
+  z-index: -1; // Put the input behind the label so it doesn't overlay text
+  opacity: 0;
+
+  &:checked ~ .custom-control-label::before {
+    color: $custom-control-indicator-checked-color;
+    @include gradient-bg($custom-control-indicator-checked-bg);
+    @include box-shadow($custom-control-indicator-checked-box-shadow);
+  }
+
+  &:focus ~ .custom-control-label::before {
+    // the mixin is not used here to make sure there is feedback
+    box-shadow: $custom-control-indicator-focus-box-shadow;
+  }
+
+  &:active ~ .custom-control-label::before {
+    color: $custom-control-indicator-active-color;
+    background-color: $custom-control-indicator-active-bg;
+    @include box-shadow($custom-control-indicator-active-box-shadow);
+  }
+
+  &:disabled {
+    ~ .custom-control-label {
+      color: $custom-control-label-disabled-color;
+
+      &::before {
+        background-color: $custom-control-indicator-disabled-bg;
+      }
+    }
+  }
+}
+
+// Custom control indicators
+//
+// Build the custom controls out of psuedo-elements.
+
+.custom-control-label {
+  margin-bottom: 0;
+
+  // Background-color and (when enabled) gradient
+  &::before {
+    position: absolute;
+    top: (($line-height-base - $custom-control-indicator-size) / 2);
+    left: 0;
+    display: block;
+    width: $custom-control-indicator-size;
+    height: $custom-control-indicator-size;
+    pointer-events: none;
+    content: "";
+    user-select: none;
+    background-color: $custom-control-indicator-bg;
+    @include box-shadow($custom-control-indicator-box-shadow);
+  }
+
+  // Foreground (icon)
+  &::after {
+    position: absolute;
+    top: (($line-height-base - $custom-control-indicator-size) / 2);
+    left: 0;
+    display: block;
+    width: $custom-control-indicator-size;
+    height: $custom-control-indicator-size;
+    content: "";
+    background-repeat: no-repeat;
+    background-position: center center;
+    background-size: $custom-control-indicator-bg-size;
+  }
+}
+
+
+// Checkboxes
+//
+// Tweak just a few things for checkboxes.
+
+.custom-checkbox {
+  .custom-control-label::before {
+    @include border-radius($custom-checkbox-indicator-border-radius);
+  }
+
+  .custom-control-input:checked ~ .custom-control-label {
+    &::before {
+      @include gradient-bg($custom-control-indicator-checked-bg);
+    }
+    &::after {
+      background-image: $custom-checkbox-indicator-icon-checked;
+    }
+  }
+
+  .custom-control-input:indeterminate ~ .custom-control-label {
+    &::before {
+      @include gradient-bg($custom-checkbox-indicator-indeterminate-bg);
+      @include box-shadow($custom-checkbox-indicator-indeterminate-box-shadow);
+    }
+    &::after {
+      background-image: $custom-checkbox-indicator-icon-indeterminate;
+    }
+  }
+}
+
+// Radios
+//
+// Tweak just a few things for radios.
+
+.custom-radio {
+  .custom-control-label::before {
+    border-radius: $custom-radio-indicator-border-radius;
+  }
+
+  .custom-control-input:checked ~ .custom-control-label {
+    &::before {
+      @include gradient-bg($custom-control-indicator-checked-bg);
+    }
+    &::after {
+      background-image: $custom-radio-indicator-icon-checked;
+    }
+  }
+}
+
+
+// Select
+//
+// Replaces the browser default select with a custom one, mostly pulled from
+// http://primercss.io.
+//
+
+.custom-select {
+  display: inline-block;
+  width: 100%;
+  height: $input-height;
+  padding: $custom-select-padding-y ($custom-select-padding-x + $custom-select-indicator-padding) $custom-select-padding-y $custom-select-padding-x;
+  line-height: $custom-select-line-height;
+  color: $custom-select-color;
+  vertical-align: middle;
+  background: $custom-select-bg $custom-select-indicator no-repeat right $custom-select-padding-x center;
+  background-size: $custom-select-bg-size;
+  border: $custom-select-border-width solid $custom-select-border-color;
+  @if $enable-rounded {
+    border-radius: $custom-select-border-radius;
+  } @else {
+    border-radius: 0;
+  }
+  appearance: none;
+
+  &:focus {
+    border-color: $custom-select-focus-border-color;
+    outline: 0;
+    box-shadow: $custom-select-focus-box-shadow;
+
+    &::-ms-value {
+      // For visual consistency with other platforms/browsers,
+      // suppress the default white text on blue background highlight given to
+      // the selected option text when the (still closed) <select> receives focus
+      // in IE and (under certain conditions) Edge.
+      // See https://github.com/twbs/bootstrap/issues/19398.
+      color: $input-color;
+      background-color: $input-bg;
+    }
+  }
+
+  &[multiple],
+  &[size]:not([size="1"]) {
+    height: auto;
+    padding-right: $custom-select-padding-x;
+    background-image: none;
+  }
+
+  &:disabled {
+    color: $custom-select-disabled-color;
+    background-color: $custom-select-disabled-bg;
+  }
+
+  // Hides the default caret in IE11
+  &::-ms-expand {
+    opacity: 0;
+  }
+}
+
+.custom-select-sm {
+  height: $custom-select-height-sm;
+  padding-top: $custom-select-padding-y;
+  padding-bottom: $custom-select-padding-y;
+  font-size: $custom-select-font-size-sm;
+}
+
+.custom-select-lg {
+  height: $custom-select-height-lg;
+  padding-top: $custom-select-padding-y;
+  padding-bottom: $custom-select-padding-y;
+  font-size: $custom-select-font-size-lg;
+}
+
+
+// File
+//
+// Custom file input.
+
+.custom-file {
+  position: relative;
+  display: inline-block;
+  width: 100%;
+  height: $custom-file-height;
+  margin-bottom: 0;
+}
+
+.custom-file-input {
+  position: relative;
+  z-index: 2;
+  width: 100%;
+  height: $custom-file-height;
+  margin: 0;
+  opacity: 0;
+
+  &:focus ~ .custom-file-control {
+    border-color: $custom-file-focus-border-color;
+    box-shadow: $custom-file-focus-box-shadow;
+
+    &::before {
+      border-color: $custom-file-focus-border-color;
+    }
+  }
+
+  @each $lang, $value in $custom-file-text {
+    &:lang(#{$lang}) ~ .custom-file-label::after {
+      content: $value;
+    }
+  }
+}
+
+.custom-file-label {
+  position: absolute;
+  top: 0;
+  right: 0;
+  left: 0;
+  z-index: 1;
+  height: $custom-file-height;
+  padding: $custom-file-padding-y $custom-file-padding-x;
+  line-height: $custom-file-line-height;
+  color: $custom-file-color;
+  background-color: $custom-file-bg;
+  border: $custom-file-border-width solid $custom-file-border-color;
+  @include border-radius($custom-file-border-radius);
+  @include box-shadow($custom-file-box-shadow);
+
+  &::after {
+    position: absolute;
+    top: 0;
+    right: 0;
+    bottom: 0;
+    z-index: 3;
+    display: block;
+    height: calc(#{$custom-file-height} - #{$custom-file-border-width} * 2);
+    padding: $custom-file-padding-y $custom-file-padding-x;
+    line-height: $custom-file-line-height;
+    color: $custom-file-button-color;
+    content: "Browse";
+    @include gradient-bg($custom-file-button-bg);
+    border-left: $custom-file-border-width solid $custom-file-border-color;
+    @include border-radius(0 $custom-file-border-radius $custom-file-border-radius 0);
+  }
+}
diff --git a/portal-FE-common/src/styles/bootstrap/_dropdown.scss b/portal-FE-common/src/styles/bootstrap/_dropdown.scss
new file mode 100644 (file)
index 0000000..a9d4cfe
--- /dev/null
@@ -0,0 +1,131 @@
+// The dropdown wrapper (`<div>`)
+.dropup,
+.dropdown {
+  position: relative;
+}
+
+.dropdown-toggle {
+  // Generate the caret automatically
+  @include caret;
+}
+
+// The dropdown menu
+.dropdown-menu {
+  position: absolute;
+  top: 100%;
+  left: 0;
+  z-index: $zindex-dropdown;
+  display: none; // none by default, but block on "open" of the menu
+  float: left;
+  min-width: $dropdown-min-width;
+  padding: $dropdown-padding-y 0;
+  margin: $dropdown-spacer 0 0; // override default ul
+  font-size: $font-size-base; // Redeclare because nesting can cause inheritance issues
+  color: $body-color;
+  text-align: left; // Ensures proper alignment if parent has it changed (e.g., modal footer)
+  list-style: none;
+  background-color: $dropdown-bg;
+  background-clip: padding-box;
+  border: $dropdown-border-width solid $dropdown-border-color;
+  @include border-radius($dropdown-border-radius);
+  @include box-shadow($dropdown-box-shadow);
+}
+
+// Allow for dropdowns to go bottom up (aka, dropup-menu)
+// Just add .dropup after the standard .dropdown class and you're set.
+.dropup {
+  .dropdown-menu {
+    margin-top: 0;
+    margin-bottom: $dropdown-spacer;
+  }
+
+  .dropdown-toggle {
+    @include caret(up);
+  }
+}
+
+.dropright {
+  .dropdown-menu {
+    margin-top: 0;
+    margin-left: $dropdown-spacer;
+  }
+
+  .dropdown-toggle {
+    @include caret(right);
+    &::after {
+      vertical-align: 0;
+    }
+  }
+}
+
+.dropleft {
+  .dropdown-menu {
+    margin-top: 0;
+    margin-right: $dropdown-spacer;
+  }
+
+  .dropdown-toggle {
+    @include caret(left);
+    &::before {
+      vertical-align: 0;
+    }
+  }
+}
+
+// Dividers (basically an `<hr>`) within the dropdown
+.dropdown-divider {
+  @include nav-divider($dropdown-divider-bg);
+}
+
+// Links, buttons, and more within the dropdown menu
+//
+// `<button>`-specific styles are denoted with `// For <button>s`
+.dropdown-item {
+  display: block;
+  width: 100%; // For `<button>`s
+  padding: $dropdown-item-padding-y $dropdown-item-padding-x;
+  clear: both;
+  font-weight: $font-weight-normal;
+  color: $dropdown-link-color;
+  text-align: inherit; // For `<button>`s
+  white-space: nowrap; // prevent links from randomly breaking onto new lines
+  background-color: transparent; // For `<button>`s
+  border: 0; // For `<button>`s
+
+  @include hover-focus {
+    color: $dropdown-link-hover-color;
+    text-decoration: none;
+    @include gradient-bg($dropdown-link-hover-bg);
+  }
+
+  &.active,
+  &:active {
+    color: $dropdown-link-active-color;
+    text-decoration: none;
+    @include gradient-bg($dropdown-link-active-bg);
+  }
+
+  &.disabled,
+  &:disabled {
+    color: $dropdown-link-disabled-color;
+    background-color: transparent;
+    // Remove CSS gradients if they're enabled
+    @if $enable-gradients {
+      background-image: none;
+    }
+  }
+}
+
+.dropdown-menu.show {
+  display: block;
+}
+
+// Dropdown section headers
+.dropdown-header {
+  display: block;
+  padding: $dropdown-padding-y $dropdown-item-padding-x;
+  margin-bottom: 0; // for use with heading elements
+  font-size: $font-size-sm;
+  color: $dropdown-header-color;
+  white-space: nowrap; // as with > li > a
+}
diff --git a/portal-FE-common/src/styles/bootstrap/_forms.scss b/portal-FE-common/src/styles/bootstrap/_forms.scss
new file mode 100644 (file)
index 0000000..b0954f8
--- /dev/null
@@ -0,0 +1,333 @@
+// stylelint-disable selector-no-qualifying-type
+
+//
+// Textual form controls
+//
+
+.form-control {
+  display: block;
+  width: 100%;
+  padding: $input-padding-y $input-padding-x;
+  font-size: $font-size-base;
+  line-height: $input-line-height;
+  color: $input-color;
+  background-color: $input-bg;
+  background-clip: padding-box;
+  border: $input-border-width solid $input-border-color;
+
+  // Note: This has no effect on <select>s in some browsers, due to the limited stylability of `<select>`s in CSS.
+  @if $enable-rounded {
+    // Manually use the if/else instead of the mixin to account for iOS override
+    border-radius: $input-border-radius;
+  } @else {
+    // Otherwise undo the iOS default
+    border-radius: 0;
+  }
+
+  @include box-shadow($input-box-shadow);
+  @include transition($input-transition);
+
+  // Unstyle the caret on `<select>`s in IE10+.
+  &::-ms-expand {
+    background-color: transparent;
+    border: 0;
+  }
+
+  // Customize the `:focus` state to imitate native WebKit styles.
+  @include form-control-focus();
+
+  // Placeholder
+  &::placeholder {
+    color: $input-placeholder-color;
+    // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526.
+    opacity: 1;
+  }
+
+  // Disabled and read-only inputs
+  //
+  // HTML5 says that controls under a fieldset > legend:first-child won't be
+  // disabled if the fieldset is disabled. Due to implementation difficulty, we
+  // don't honor that edge case; we style them as disabled anyway.
+  &:disabled,
+  &[readonly] {
+    background-color: $input-disabled-bg;
+    // iOS fix for unreadable disabled content; see https://github.com/twbs/bootstrap/issues/11655.
+    opacity: 1;
+  }
+}
+
+select.form-control {
+  &:not([size]):not([multiple]) {
+    height: $input-height;
+  }
+
+  &:focus::-ms-value {
+    // Suppress the nested default white text on blue background highlight given to
+    // the selected option text when the (still closed) <select> receives focus
+    // in IE and (under certain conditions) Edge, as it looks bad and cannot be made to
+    // match the appearance of the native widget.
+    // See https://github.com/twbs/bootstrap/issues/19398.
+    color: $input-color;
+    background-color: $input-bg;
+  }
+}
+
+// Make file inputs better match text inputs by forcing them to new lines.
+.form-control-file,
+.form-control-range {
+  display: block;
+  width: 100%;
+}
+
+
+//
+// Labels
+//
+
+// For use with horizontal and inline forms, when you need the label (or legend)
+// text to align with the form controls.
+.col-form-label {
+  padding-top: calc(#{$input-padding-y} + #{$input-border-width});
+  padding-bottom: calc(#{$input-padding-y} + #{$input-border-width});
+  margin-bottom: 0; // Override the `<label>/<legend>` default
+  font-size: inherit; // Override the `<legend>` default
+  line-height: $input-line-height;
+}
+
+.col-form-label-lg {
+  padding-top: calc(#{$input-padding-y-lg} + #{$input-border-width});
+  padding-bottom: calc(#{$input-padding-y-lg} + #{$input-border-width});
+  font-size: $font-size-lg;
+  line-height: $input-line-height-lg;
+}
+
+.col-form-label-sm {
+  padding-top: calc(#{$input-padding-y-sm} + #{$input-border-width});
+  padding-bottom: calc(#{$input-padding-y-sm} + #{$input-border-width});
+  font-size: $font-size-sm;
+  line-height: $input-line-height-sm;
+}
+
+
+// Readonly controls as plain text
+//
+// Apply class to a readonly input to make it appear like regular plain
+// text (without any border, background color, focus indicator)
+
+.form-control-plaintext {
+  display: block;
+  width: 100%;
+  padding-top: $input-padding-y;
+  padding-bottom: $input-padding-y;
+  margin-bottom: 0; // match inputs if this class comes on inputs with default margins
+  line-height: $input-line-height;
+  background-color: transparent;
+  border: solid transparent;
+  border-width: $input-border-width 0;
+
+  &.form-control-sm,
+  &.form-control-lg {
+    padding-right: 0;
+    padding-left: 0;
+  }
+}
+
+
+// Form control sizing
+//
+// Build on `.form-control` with modifier classes to decrease or increase the
+// height and font-size of form controls.
+//
+// The `.form-group-* form-control` variations are sadly duplicated to avoid the
+// issue documented in https://github.com/twbs/bootstrap/issues/15074.
+
+.form-control-sm {
+  padding: $input-padding-y-sm $input-padding-x-sm;
+  font-size: $font-size-sm;
+  line-height: $input-line-height-sm;
+  @include border-radius($input-border-radius-sm);
+}
+
+select.form-control-sm {
+  &:not([size]):not([multiple]) {
+    height: $input-height-sm;
+  }
+}
+
+.form-control-lg {
+  padding: $input-padding-y-lg $input-padding-x-lg;
+  font-size: $font-size-lg;
+  line-height: $input-line-height-lg;
+  @include border-radius($input-border-radius-lg);
+}
+
+select.form-control-lg {
+  &:not([size]):not([multiple]) {
+    height: $input-height-lg;
+  }
+}
+
+
+// Form groups
+//
+// Designed to help with the organization and spacing of vertical forms. For
+// horizontal forms, use the predefined grid classes.
+
+.form-group {
+  margin-bottom: $form-group-margin-bottom;
+}
+
+.form-text {
+  display: block;
+  margin-top: $form-text-margin-top;
+}
+
+
+// Form grid
+//
+// Special replacement for our grid system's `.row` for tighter form layouts.
+
+.form-row {
+  display: flex;
+  flex-wrap: wrap;
+  margin-right: -5px;
+  margin-left: -5px;
+
+  > .col,
+  > [class*="col-"] {
+    padding-right: 5px;
+    padding-left: 5px;
+  }
+}
+
+
+// Checkboxes and radios
+//
+// Indent the labels to position radios/checkboxes as hanging controls.
+
+.form-check {
+  position: relative;
+  display: block;
+  padding-left: $form-check-input-gutter;
+}
+
+.form-check-input {
+  position: absolute;
+  margin-top: $form-check-input-margin-y;
+  margin-left: -$form-check-input-gutter;
+
+  &:disabled ~ .form-check-label {
+    color: $text-muted;
+  }
+}
+
+.form-check-label {
+  margin-bottom: 0; // Override default `<label>` bottom margin
+}
+
+.form-check-inline {
+  display: inline-flex;
+  align-items: center;
+  padding-left: 0; // Override base .form-check
+  margin-right: $form-check-inline-margin-x;
+
+  // Undo .form-check-input defaults and add some `margin-right`.
+  .form-check-input {
+    position: static;
+    margin-top: 0;
+    margin-right: $form-check-inline-input-margin-x;
+    margin-left: 0;
+  }
+}
+
+
+// Form validation
+//
+// Provide feedback to users when form field values are valid or invalid. Works
+// primarily for client-side validation via scoped `:invalid` and `:valid`
+// pseudo-classes but also includes `.is-invalid` and `.is-valid` classes for
+// server side validation.
+
+@include form-validation-state("valid", $form-feedback-valid-color);
+@include form-validation-state("invalid", $form-feedback-invalid-color);
+
+// Inline forms
+//
+// Make forms appear inline(-block) by adding the `.form-inline` class. Inline
+// forms begin stacked on extra small (mobile) devices and then go inline when
+// viewports reach <768px.
+//
+// Requires wrapping inputs and labels with `.form-group` for proper display of
+// default HTML form controls and our custom form controls (e.g., input groups).
+
+.form-inline {
+  display: flex;
+  flex-flow: row wrap;
+  align-items: center; // Prevent shorter elements from growing to same height as others (e.g., small buttons growing to normal sized button height)
+
+  // Because we use flex, the initial sizing of checkboxes is collapsed and
+  // doesn't occupy the full-width (which is what we want for xs grid tier),
+  // so we force that here.
+  .form-check {
+    width: 100%;
+  }
+
+  // Kick in the inline
+  @include media-breakpoint-up(sm) {
+    label {
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      margin-bottom: 0;
+    }
+
+    // Inline-block all the things for "inline"
+    .form-group {
+      display: flex;
+      flex: 0 0 auto;
+      flex-flow: row wrap;
+      align-items: center;
+      margin-bottom: 0;
+    }
+
+    // Allow folks to *not* use `.form-group`
+    .form-control {
+      display: inline-block;
+      width: auto; // Prevent labels from stacking above inputs in `.form-group`
+      vertical-align: middle;
+    }
+
+    // Make static controls behave like regular ones
+    .form-control-plaintext {
+      display: inline-block;
+    }
+
+    .input-group {
+      width: auto;
+    }
+
+    // Remove default margin on radios/checkboxes that were used for stacking, and
+    // then undo the floating of radios and checkboxes to match.
+    .form-check {
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      width: auto;
+      padding-left: 0;
+    }
+    .form-check-input {
+      position: relative;
+      margin-top: 0;
+      margin-right: $form-check-input-margin-x;
+      margin-left: 0;
+    }
+
+    .custom-control {
+      align-items: center;
+      justify-content: center;
+    }
+    .custom-control-label {
+      margin-bottom: 0;
+    }
+  }
+}
diff --git a/portal-FE-common/src/styles/bootstrap/_functions.scss b/portal-FE-common/src/styles/bootstrap/_functions.scss
new file mode 100644 (file)
index 0000000..1266d34
--- /dev/null
@@ -0,0 +1,86 @@
+// Bootstrap functions
+//
+// Utility mixins and functions for evalutating source code across our variables, maps, and mixins.
+
+// Ascending
+// Used to evaluate Sass maps like our grid breakpoints.
+@mixin _assert-ascending($map, $map-name) {
+  $prev-key: null;
+  $prev-num: null;
+  @each $key, $num in $map {
+    @if $prev-num == null {
+      // Do nothing
+    } @else if not comparable($prev-num, $num) {
+      @warn "Potentially invalid value for #{$map-name}: This map must be in ascending order, but key '#{$key}' has value #{$num} whose unit makes it incomparable to #{$prev-num}, the value of the previous key '#{$prev-key}' !";
+    } @else if $prev-num >= $num {
+      @warn "Invalid value for #{$map-name}: This map must be in ascending order, but key '#{$key}' has value #{$num} which isn't greater than #{$prev-num}, the value of the previous key '#{$prev-key}' !";
+    }
+    $prev-key: $key;
+    $prev-num: $num;
+  }
+}
+
+// Starts at zero
+// Another grid mixin that ensures the min-width of the lowest breakpoint starts at 0.
+@mixin _assert-starts-at-zero($map) {
+  $values: map-values($map);
+  $first-value: nth($values, 1);
+  @if $first-value != 0 {
+    @warn "First breakpoint in `$grid-breakpoints` must start at 0, but starts at #{$first-value}.";
+  }
+}
+
+// Replace `$search` with `$replace` in `$string`
+// Used on our SVG icon backgrounds for custom forms.
+//
+// @author Hugo Giraudel
+// @param {String} $string - Initial string
+// @param {String} $search - Substring to replace
+// @param {String} $replace ('') - New value
+// @return {String} - Updated string
+@function str-replace($string, $search, $replace: "") {
+  $index: str-index($string, $search);
+
+  @if $index {
+    @return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
+  }
+
+  @return $string;
+}
+
+// Color contrast
+@function color-yiq($color) {
+  $r: red($color);
+  $g: green($color);
+  $b: blue($color);
+
+  $yiq: (($r * 299) + ($g * 587) + ($b * 114)) / 1000;
+
+  @if ($yiq >= $yiq-contrasted-threshold) {
+    @return $yiq-text-dark;
+  } @else {
+    @return $yiq-text-light;
+  }
+}
+
+// Retrieve color Sass maps
+@function color($key: "blue") {
+  @return map-get($colors, $key);
+}
+
+@function theme-color($key: "primary") {
+  @return map-get($theme-colors, $key);
+}
+
+@function gray($key: "100") {
+  @return map-get($grays, $key);
+}
+
+// Request a theme color level
+@function theme-color-level($color-name: "primary", $level: 0) {
+  $color: theme-color($color-name);
+  $color-base: if($level > 0, #000, #fff);
+  $level: abs($level);
+
+  @return mix($color-base, $color, $level * $theme-color-interval);
+}
diff --git a/portal-FE-common/src/styles/bootstrap/_grid.scss b/portal-FE-common/src/styles/bootstrap/_grid.scss
new file mode 100644 (file)
index 0000000..a227515
--- /dev/null
@@ -0,0 +1,52 @@
+// Container widths
+//
+// Set the container width, and override it for fixed navbars in media queries.
+
+@if $enable-grid-classes {
+  .container {
+    @include make-container();
+    @include make-container-max-widths();
+  }
+}
+
+// Fluid container
+//
+// Utilizes the mixin meant for fixed width containers, but with 100% width for
+// fluid, full width layouts.
+
+@if $enable-grid-classes {
+  .container-fluid {
+    @include make-container();
+  }
+}
+
+// Row
+//
+// Rows contain and clear the floats of your columns.
+
+@if $enable-grid-classes {
+  .row {
+    @include make-row();
+  }
+
+  // Remove the negative margin from default .row, then the horizontal padding
+  // from all immediate children columns (to prevent runaway style inheritance).
+  .no-gutters {
+    margin-right: 0;
+    margin-left: 0;
+
+    > .col,
+    > [class*="col-"] {
+      padding-right: 0;
+      padding-left: 0;
+    }
+  }
+}
+
+// Columns
+//
+// Common styles for small and large grid columns
+
+@if $enable-grid-classes {
+  @include make-grid-columns();
+}
diff --git a/portal-FE-common/src/styles/bootstrap/_images.scss b/portal-FE-common/src/styles/bootstrap/_images.scss
new file mode 100644 (file)
index 0000000..2bce02f
--- /dev/null
@@ -0,0 +1,42 @@
+// Responsive images (ensure images don't scale beyond their parents)
+//
+// This is purposefully opt-in via an explicit class rather than being the default for all `<img>`s.
+// We previously tried the "images are responsive by default" approach in Bootstrap v2,
+// and abandoned it in Bootstrap v3 because it breaks lots of third-party widgets (including Google Maps)
+// which weren't expecting the images within themselves to be involuntarily resized.
+// See also https://github.com/twbs/bootstrap/issues/18178
+.img-fluid {
+  @include img-fluid;
+}
+
+
+// Image thumbnails
+.img-thumbnail {
+  padding: $thumbnail-padding;
+  background-color: $thumbnail-bg;
+  border: $thumbnail-border-width solid $thumbnail-border-color;
+  @include border-radius($thumbnail-border-radius);
+  @include box-shadow($thumbnail-box-shadow);
+
+  // Keep them at most 100% wide
+  @include img-fluid;
+}
+
+//
+// Figures
+//
+
+.figure {
+  // Ensures the caption's text aligns with the image.
+  display: inline-block;
+}
+
+.figure-img {
+  margin-bottom: ($spacer / 2);
+  line-height: 1;
+}
+
+.figure-caption {
+  font-size: $figure-caption-font-size;
+  color: $figure-caption-color;
+}
diff --git a/portal-FE-common/src/styles/bootstrap/_input-group.scss b/portal-FE-common/src/styles/bootstrap/_input-group.scss
new file mode 100644 (file)
index 0000000..7ef0267
--- /dev/null
@@ -0,0 +1,156 @@
+// stylelint-disable selector-no-qualifying-type
+
+//
+// Base styles
+//
+
+.input-group {
+  position: relative;
+  display: flex;
+  flex-wrap: wrap; // For form validation feedback
+  align-items: stretch;
+  width: 100%;
+
+  .form-control,
+  .custom-select,
+  .custom-file {
+    position: relative; // For focus state's z-index
+    flex: 1 1 auto;
+    // Add width 1% and flex-basis auto to ensure that button will not wrap out
+    // the column. Applies to IE Edge+ and Firefox. Chrome does not require this.
+    width: 1%;
+    margin-bottom: 0;
+
+    // Bring the "active" form control to the top of surrounding elements
+    &:focus {
+      z-index: 3;
+    }
+
+    + .form-control {
+      margin-left: -$input-border-width;
+    }
+  }
+
+  .form-control,
+  .custom-select {
+    &:not(:last-child) { @include border-right-radius(0); }
+    &:not(:first-child) { @include border-left-radius(0); }
+  }
+
+  // Custom file inputs have more complex markup, thus requiring different
+  // border-radius overrides.
+  .custom-file {
+    display: flex;
+    align-items: center;
+
+    &:not(:last-child) .custom-file-control,
+    &:not(:last-child) .custom-file-control::before { @include border-right-radius(0); }
+    &:not(:first-child) .custom-file-control,
+    &:not(:first-child) .custom-file-control::before { @include border-left-radius(0); }
+  }
+}
+
+
+// Prepend and append
+//
+// While it requires one extra layer of HTML for each, dedicated prepend and
+// append elements allow us to 1) be less clever, 2) simplify our selectors, and
+// 3) support HTML5 form validation.
+
+.input-group-prepend,
+.input-group-append {
+  display: flex;
+  align-items: center;
+
+  // Ensure buttons are always above inputs for more visually pleasing borders.
+  // This isn't needed for `.input-group-text` since it shares the same border-color
+  // as our inputs.
+  .btn {
+    position: relative;
+    z-index: 2;
+  }
+
+  .btn + .btn,
+  .btn + .input-group-text,
+  .input-group-text + .input-group-text,
+  .input-group-text + .btn {
+    margin-left: -$input-border-width;
+  }
+}
+
+.input-group-prepend { margin-right: -$input-border-width; }
+.input-group-append { margin-left: -$input-border-width; }
+
+
+// Textual addons
+//
+// Serves as a catch-all element for any text or radio/checkbox input you wish
+// to prepend or append to an input.
+
+.input-group-text {
+  padding: $input-padding-y $input-padding-x;
+  margin-bottom: 0; // Allow use of <label> elements by overriding our default margin-bottom
+  font-size: $font-size-base; // Match inputs
+  font-weight: $font-weight-normal;
+  line-height: $input-line-height;
+  color: $input-group-addon-color;
+  text-align: center;
+  white-space: nowrap;
+  background-color: $input-group-addon-bg;
+  border: $input-border-width solid $input-group-addon-border-color;
+  @include border-radius($input-border-radius);
+
+  // Nuke default margins from checkboxes and radios to vertically center within.
+  input[type="radio"],
+  input[type="checkbox"] {
+    margin-top: 0;
+  }
+}
+
+
+// Sizing
+//
+// Remix the default form control sizing classes into new ones for easier
+// manipulation.
+
+.input-group-lg > .form-control,
+.input-group-lg > .input-group-prepend > .input-group-text,
+.input-group-lg > .input-group-append > .input-group-text,
+.input-group-lg > .input-group-prepend > .btn,
+.input-group-lg > .input-group-append > .btn {
+  @extend .form-control-lg;
+}
+
+.input-group-sm > .form-control,
+.input-group-sm > .input-group-prepend > .input-group-text,
+.input-group-sm > .input-group-append > .input-group-text,
+.input-group-sm > .input-group-prepend > .btn,
+.input-group-sm > .input-group-append > .btn {
+  @extend .form-control-sm;
+}
+
+
+// Prepend and append rounded corners
+//
+// These rulesets must come after the sizing ones to properly override sm and lg
+// border-radius values when extending. They're more specific than we'd like
+// with the `.input-group >` part, but without it, we cannot override the sizing.
+
+
+.input-group > .input-group-prepend > .btn,
+.input-group > .input-group-prepend > .input-group-text,
+.input-group > .input-group-append:not(:last-child) > .btn,
+.input-group > .input-group-append:not(:last-child) > .input-group-text,
+.input-group > .input-group-append:last-child > .btn:not(:last-child):not(.dropdown-toggle),
+.input-group > .input-group-append:last-child > .input-group-text:not(:last-child) {
+  @include border-right-radius(0);
+}
+
+.input-group > .input-group-append > .btn,
+.input-group > .input-group-append > .input-group-text,
+.input-group > .input-group-prepend:not(:first-child) > .btn,
+.input-group > .input-group-prepend:not(:first-child) > .input-group-text,
+.input-group > .input-group-prepend:first-child > .btn:not(:first-child),
+.input-group > .input-group-prepend:first-child > .input-group-text:not(:first-child) {
+  @include border-left-radius(0);
+}
diff --git a/portal-FE-common/src/styles/bootstrap/_jumbotron.scss b/portal-FE-common/src/styles/bootstrap/_jumbotron.scss
new file mode 100644 (file)
index 0000000..7966bba
--- /dev/null
@@ -0,0 +1,16 @@
+.jumbotron {
+  padding: $jumbotron-padding ($jumbotron-padding / 2);
+  margin-bottom: $jumbotron-padding;
+  background-color: $jumbotron-bg;
+  @include border-radius($border-radius-lg);
+
+  @include media-breakpoint-up(sm) {
+    padding: ($jumbotron-padding * 2) $jumbotron-padding;
+  }
+}
+
+.jumbotron-fluid {
+  padding-right: 0;
+  padding-left: 0;
+  @include border-radius(0);
+}
diff --git a/portal-FE-common/src/styles/bootstrap/_list-group.scss b/portal-FE-common/src/styles/bootstrap/_list-group.scss
new file mode 100644 (file)
index 0000000..9f145c1
--- /dev/null
@@ -0,0 +1,115 @@
+// Base class
+//
+// Easily usable on <ul>, <ol>, or <div>.
+
+.list-group {
+  display: flex;
+  flex-direction: column;
+
+  // No need to set list-style: none; since .list-group-item is block level
+  padding-left: 0; // reset padding because ul and ol
+  margin-bottom: 0;
+}
+
+
+// Interactive list items
+//
+// Use anchor or button elements instead of `li`s or `div`s to create interactive
+// list items. Includes an extra `.active` modifier class for selected items.
+
+.list-group-item-action {
+  width: 100%; // For `<button>`s (anchors become 100% by default though)
+  color: $list-group-action-color;
+  text-align: inherit; // For `<button>`s (anchors inherit)
+
+  // Hover state
+  @include hover-focus {
+    color: $list-group-action-hover-color;
+    text-decoration: none;
+    background-color: $list-group-hover-bg;
+  }
+
+  &:active {
+    color: $list-group-action-active-color;
+    background-color: $list-group-action-active-bg;
+  }
+}
+
+
+// Individual list items
+//
+// Use on `li`s or `div`s within the `.list-group` parent.
+
+.list-group-item {
+  position: relative;
+  display: block;
+  padding: $list-group-item-padding-y $list-group-item-padding-x;
+  // Place the border on the list items and negative margin up for better styling
+  margin-bottom: -$list-group-border-width;
+  background-color: $list-group-bg;
+  border: $list-group-border-width solid $list-group-border-color;
+
+  &:first-child {
+    @include border-top-radius($list-group-border-radius);
+  }
+
+  &:last-child {
+    margin-bottom: 0;
+    @include border-bottom-radius($list-group-border-radius);
+  }
+
+  @include hover-focus {
+    z-index: 1; // Place hover/active items above their siblings for proper border styling
+    text-decoration: none;
+  }
+
+  &.disabled,
+  &:disabled {
+    color: $list-group-disabled-color;
+    background-color: $list-group-disabled-bg;
+  }
+
+  // Include both here for `<a>`s and `<button>`s
+  &.active {
+    z-index: 2; // Place active items above their siblings for proper border styling
+    color: $list-group-active-color;
+    background-color: $list-group-active-bg;
+    border-color: $list-group-active-border-color;
+  }
+}
+
+
+// Flush list items
+//
+// Remove borders and border-radius to keep list group items edge-to-edge. Most
+// useful within other components (e.g., cards).
+
+.list-group-flush {
+  .list-group-item {
+    border-right: 0;
+    border-left: 0;
+    @include border-radius(0);
+  }
+
+  &:first-child {
+    .list-group-item:first-child {
+      border-top: 0;
+    }
+  }
+
+  &:last-child {
+    .list-group-item:last-child {
+      border-bottom: 0;
+    }
+  }
+}
+
+
+// Contextual variants
+//
+// Add modifier classes to change text and background color on individual items.
+// Organizationally, this must come after the `:hover` states.
+
+@each $color, $value in $theme-colors {
+  @include list-group-item-variant($color, theme-color-level($color, -9), theme-color-level($color, 6));
+}
diff --git a/portal-FE-common/src/styles/bootstrap/_media.scss b/portal-FE-common/src/styles/bootstrap/_media.scss
new file mode 100644 (file)
index 0000000..b573052
--- /dev/null
@@ -0,0 +1,8 @@
+.media {
+  display: flex;
+  align-items: flex-start;
+}
+
+.media-body {
+  flex: 1;
+}
diff --git a/portal-FE-common/src/styles/bootstrap/_mixins.scss b/portal-FE-common/src/styles/bootstrap/_mixins.scss
new file mode 100644 (file)
index 0000000..d9a1774
--- /dev/null
@@ -0,0 +1,42 @@
+// Toggles
+//
+// Used in conjunction with global variables to enable certain theme features.
+
+// Utilities
+@import "mixins/breakpoints";
+@import "mixins/hover";
+@import "mixins/image";
+@import "mixins/badge";
+@import "mixins/resize";
+@import "mixins/screen-reader";
+@import "mixins/size";
+@import "mixins/reset-text";
+@import "mixins/text-emphasis";
+@import "mixins/text-hide";
+@import "mixins/text-truncate";
+@import "mixins/visibility";
+
+// // Components
+@import "mixins/alert";
+@import "mixins/buttons";
+@import "mixins/caret";
+@import "mixins/pagination";
+@import "mixins/lists";
+@import "mixins/list-group";
+@import "mixins/nav-divider";
+@import "mixins/forms";
+@import "mixins/table-row";
+
+// // Skins
+@import "mixins/background-variant";
+@import "mixins/border-radius";
+@import "mixins/box-shadow";
+@import "mixins/gradients";
+@import "mixins/transition";
+
+// // Layout
+@import "mixins/clearfix";
+// @import "mixins/navbar-align";
+@import "mixins/grid-framework";
+@import "mixins/grid";
+@import "mixins/float";
diff --git a/portal-FE-common/src/styles/bootstrap/_modal.scss b/portal-FE-common/src/styles/bootstrap/_modal.scss
new file mode 100644 (file)
index 0000000..edda836
--- /dev/null
@@ -0,0 +1,168 @@
+// .modal-open      - body class for killing the scroll
+// .modal           - container to scroll within
+// .modal-dialog    - positioning shell for the actual modal
+// .modal-content   - actual modal w/ bg and corners and stuff
+
+
+// Kill the scroll on the body
+.modal-open {
+  overflow: hidden;
+}
+
+// Container that the modal scrolls within
+.modal {
+  position: fixed;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  z-index: $zindex-modal;
+  display: none;
+  overflow: hidden;
+  // Prevent Chrome on Windows from adding a focus outline. For details, see
+  // https://github.com/twbs/bootstrap/pull/10951.
+  outline: 0;
+  // We deliberately don't use `-webkit-overflow-scrolling: touch;` due to a
+  // gnarly iOS Safari bug: https://bugs.webkit.org/show_bug.cgi?id=158342
+  // See also https://github.com/twbs/bootstrap/issues/17695
+
+  .modal-open & {
+    overflow-x: hidden;
+    overflow-y: auto;
+  }
+}
+
+// Shell div to position the modal with bottom padding
+.modal-dialog {
+  position: relative;
+  width: auto;
+  margin: $modal-dialog-margin;
+  // allow clicks to pass through for custom click handling to close modal
+  pointer-events: none;
+
+  // When fading in the modal, animate it to slide down
+  .modal.fade & {
+    @include transition($modal-transition);
+    transform: translate(0, -25%);
+  }
+  .modal.show & {
+    transform: translate(0, 0);
+  }
+}
+
+.modal-dialog-centered {
+  display: flex;
+  align-items: center;
+  min-height: calc(100% - (#{$modal-dialog-margin} * 2));
+}
+
+// Actual modal
+.modal-content {
+  position: relative;
+  display: flex;
+  flex-direction: column;
+  width: 100%; // Ensure `.modal-content` extends the full width of the parent `.modal-dialog`
+  // counteract the pointer-events: none; in the .modal-dialog
+  pointer-events: auto;
+  background-color: $modal-content-bg;
+  background-clip: padding-box;
+  border: $modal-content-border-width solid $modal-content-border-color;
+  @include border-radius($border-radius-lg);
+  @include box-shadow($modal-content-box-shadow-xs);
+  // Remove focus outline from opened modal
+  outline: 0;
+}
+
+// Modal background
+.modal-backdrop {
+  position: fixed;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  z-index: $zindex-modal-backdrop;
+  background-color: $modal-backdrop-bg;
+
+  // Fade for backdrop
+  &.fade { opacity: 0; }
+  &.show { opacity: $modal-backdrop-opacity; }
+}
+
+// Modal header
+// Top section of the modal w/ title and dismiss
+.modal-header {
+  display: flex;
+  align-items: flex-start; // so the close btn always stays on the upper right corner
+  justify-content: space-between; // Put modal header elements (title and dismiss) on opposite ends
+  padding: $modal-header-padding;
+  border-bottom: $modal-header-border-width solid $modal-header-border-color;
+  @include border-top-radius($border-radius-lg);
+
+  .close {
+    padding: $modal-header-padding;
+    // auto on the left force icon to the right even when there is no .modal-title
+    margin: (-$modal-header-padding) (-$modal-header-padding) (-$modal-header-padding) auto;
+  }
+}
+
+// Title text within header
+.modal-title {
+  margin-bottom: 0;
+  line-height: $modal-title-line-height;
+}
+
+// Modal body
+// Where all modal content resides (sibling of .modal-header and .modal-footer)
+.modal-body {
+  position: relative;
+  // Enable `flex-grow: 1` so that the body take up as much space as possible
+  // when should there be a fixed height on `.modal-dialog`.
+  flex: 1 1 auto;
+  padding: $modal-inner-padding;
+}
+
+// Footer (for actions)
+.modal-footer {
+  display: flex;
+  align-items: center; // vertically center
+  justify-content: flex-end; // Right align buttons with flex property because text-align doesn't work on flex items
+  padding: $modal-inner-padding;
+  border-top: $modal-footer-border-width solid $modal-footer-border-color;
+
+  // Easily place margin between footer elements
+  > :not(:first-child) { margin-left: .25rem; }
+  > :not(:last-child) { margin-right: .25rem; }
+}
+
+// Measure scrollbar width for padding body during modal show/hide
+.modal-scrollbar-measure {
+  position: absolute;
+  top: -9999px;
+  width: 50px;
+  height: 50px;
+  overflow: scroll;
+}
+
+// Scale up the modal
+@include media-breakpoint-up(sm) {
+  // Automatically set modal's width for larger viewports
+  .modal-dialog {
+    max-width: $modal-md;
+    margin: $modal-dialog-margin-y-sm-up auto;
+  }
+
+  .modal-dialog-centered {
+    min-height: calc(100% - (#{$modal-dialog-margin-y-sm-up} * 2));
+  }
+
+  .modal-content {
+    @include box-shadow($modal-content-box-shadow-sm-up);
+  }
+
+  .modal-sm { max-width: $modal-sm; }
+
+}
+
+@include media-breakpoint-up(lg) {
+  .modal-lg { max-width: $modal-lg; }
+}
diff --git a/portal-FE-common/src/styles/bootstrap/_nav.scss b/portal-FE-common/src/styles/bootstrap/_nav.scss
new file mode 100644 (file)
index 0000000..fc82161
--- /dev/null
@@ -0,0 +1,118 @@
+// Base class
+//
+// Kickstart any navigation component with a set of style resets. Works with
+// `<nav>`s or `<ul>`s.
+
+.nav {
+  display: flex;
+  flex-wrap: wrap;
+  padding-left: 0;
+  margin-bottom: 0;
+  list-style: none;
+}
+
+.nav-link {
+  display: block;
+  padding: $nav-link-padding-y $nav-link-padding-x;
+
+  @include hover-focus {
+    text-decoration: none;
+  }
+
+  // Disabled state lightens text
+  &.disabled {
+    color: $nav-link-disabled-color;
+  }
+}
+
+//
+// Tabs
+//
+
+.nav-tabs {
+  border-bottom: $nav-tabs-border-width solid $nav-tabs-border-color;
+
+  .nav-item {
+    margin-bottom: -$nav-tabs-border-width;
+  }
+
+  .nav-link {
+    border: $nav-tabs-border-width solid transparent;
+    @include border-top-radius($nav-tabs-border-radius);
+
+    @include hover-focus {
+      border-color: $nav-tabs-link-hover-border-color;
+    }
+
+    &.disabled {
+      color: $nav-link-disabled-color;
+      background-color: transparent;
+      border-color: transparent;
+    }
+  }
+
+  .nav-link.active,
+  .nav-item.show .nav-link {
+    color: $nav-tabs-link-active-color;
+    background-color: $nav-tabs-link-active-bg;
+    border-color: $nav-tabs-link-active-border-color;
+  }
+
+  .dropdown-menu {
+    // Make dropdown border overlap tab border
+    margin-top: -$nav-tabs-border-width;
+    // Remove the top rounded corners here since there is a hard edge above the menu
+    @include border-top-radius(0);
+  }
+}
+
+
+//
+// Pills
+//
+
+.nav-pills {
+  .nav-link {
+    @include border-radius($nav-pills-border-radius);
+  }
+
+  .nav-link.active,
+  .show > .nav-link {
+    color: $nav-pills-link-active-color;
+    background-color: $nav-pills-link-active-bg;
+  }
+}
+
+
+//
+// Justified variants
+//
+
+.nav-fill {
+  .nav-item {
+    flex: 1 1 auto;
+    text-align: center;
+  }
+}
+
+.nav-justified {
+  .nav-item {
+    flex-basis: 0;
+    flex-grow: 1;
+    text-align: center;
+  }
+}
+
+
+// Tabbable tabs
+//
+// Hide tabbable panes to start, show them when `.active`
+
+.tab-content {
+  > .tab-pane {
+    display: none;
+  }
+  > .active {
+    display: block;
+  }
+}
diff --git a/portal-FE-common/src/styles/bootstrap/_navbar.scss b/portal-FE-common/src/styles/bootstrap/_navbar.scss
new file mode 100644 (file)
index 0000000..6b76649
--- /dev/null
@@ -0,0 +1,311 @@
+// Contents
+//
+// Navbar
+// Navbar brand
+// Navbar nav
+// Navbar text
+// Navbar divider
+// Responsive navbar
+// Navbar position
+// Navbar themes
+
+
+// Navbar
+//
+// Provide a static navbar from which we expand to create full-width, fixed, and
+// other navbar variations.
+
+.navbar {
+  position: relative;
+  display: flex;
+  flex-wrap: wrap; // allow us to do the line break for collapsing content
+  align-items: center;
+  justify-content: space-between; // space out brand from logo
+  padding: $navbar-padding-y $navbar-padding-x;
+
+  // Because flex properties aren't inherited, we need to redeclare these first
+  // few properities so that content nested within behave properly.
+  > .container,
+  > .container-fluid {
+    display: flex;
+    flex-wrap: wrap;
+    align-items: center;
+    justify-content: space-between;
+  }
+}
+
+
+// Navbar brand
+//
+// Used for brand, project, or site names.
+
+.navbar-brand {
+  display: inline-block;
+  padding-top: $navbar-brand-padding-y;
+  padding-bottom: $navbar-brand-padding-y;
+  margin-right: $navbar-padding-x;
+  font-size: $navbar-brand-font-size;
+  line-height: inherit;
+  white-space: nowrap;
+
+  @include hover-focus {
+    text-decoration: none;
+  }
+}
+
+
+// Navbar nav
+//
+// Custom navbar navigation (doesn't require `.nav`, but does make use of `.nav-link`).
+
+.navbar-nav {
+  display: flex;
+  flex-direction: column; // cannot use `inherit` to get the `.navbar`s value
+  padding-left: 0;
+  margin-bottom: 0;
+  list-style: none;
+
+  .nav-link {
+    padding-right: 0;
+    padding-left: 0;
+  }
+
+  .dropdown-menu {
+    position: static;
+    float: none;
+  }
+}
+
+
+// Navbar text
+//
+//
+
+.navbar-text {
+  display: inline-block;
+  padding-top: $nav-link-padding-y;
+  padding-bottom: $nav-link-padding-y;
+}
+
+
+// Responsive navbar
+//
+// Custom styles for responsive collapsing and toggling of navbar contents.
+// Powered by the collapse Bootstrap JavaScript plugin.
+
+// When collapsed, prevent the toggleable navbar contents from appearing in
+// the default flexbox row orienation. Requires the use of `flex-wrap: wrap`
+// on the `.navbar` parent.
+.navbar-collapse {
+  flex-basis: 100%;
+  flex-grow: 1;
+  // For always expanded or extra full navbars, ensure content aligns itself
+  // properly vertically. Can be easily overridden with flex utilities.
+  align-items: center;
+}
+
+// Button for toggling the navbar when in its collapsed state
+.navbar-toggler {
+  padding: $navbar-toggler-padding-y $navbar-toggler-padding-x;
+  font-size: $navbar-toggler-font-size;
+  line-height: 1;
+  background-color: transparent; // remove default button style
+  border: $border-width solid transparent; // remove default button style
+  @include border-radius($navbar-toggler-border-radius);
+
+  @include hover-focus {
+    text-decoration: none;
+  }
+
+  // Opinionated: add "hand" cursor to non-disabled .navbar-toggler elements
+  &:not([disabled]):not(.disabled) {
+    cursor: pointer;
+  }
+}
+
+// Keep as a separate element so folks can easily override it with another icon
+// or image file as needed.
+.navbar-toggler-icon {
+  display: inline-block;
+  width: 1.5em;
+  height: 1.5em;
+  vertical-align: middle;
+  content: "";
+  background: no-repeat center center;
+  background-size: 100% 100%;
+}
+
+// Generate series of `.navbar-expand-*` responsive classes for configuring
+// where your navbar collapses.
+.navbar-expand {
+  @each $breakpoint in map-keys($grid-breakpoints) {
+    $next: breakpoint-next($breakpoint, $grid-breakpoints);
+    $infix: breakpoint-infix($next, $grid-breakpoints);
+
+    &#{$infix} {
+      @include media-breakpoint-down($breakpoint) {
+        > .container,
+        > .container-fluid {
+          padding-right: 0;
+          padding-left: 0;
+        }
+      }
+
+      @include media-breakpoint-up($next) {
+        flex-flow: row nowrap;
+        justify-content: flex-start;
+
+        .navbar-nav {
+          flex-direction: row;
+
+          .dropdown-menu {
+            position: absolute;
+          }
+
+          .dropdown-menu-right {
+            right: 0;
+            left: auto; // Reset the default from `.dropdown-menu`
+          }
+
+          .nav-link {
+            padding-right: .5rem;
+            padding-left: .5rem;
+          }
+        }
+
+        // For nesting containers, have to redeclare for alignment purposes
+        > .container,
+        > .container-fluid {
+          flex-wrap: nowrap;
+        }
+
+        .navbar-collapse {
+          display: flex !important;  // stylelint-disable-line declaration-no-important
+
+          // Changes flex-bases to auto because of an IE10 bug
+          flex-basis: auto;
+        }
+
+        .navbar-toggler {
+          display: none;
+        }
+
+        .dropup {
+          .dropdown-menu {
+            top: auto;
+            bottom: 100%;
+          }
+        }
+      }
+    }
+  }
+}
+
+
+// Navbar themes
+//
+// Styles for switching between navbars with light or dark background.
+
+// Dark links against a light background
+.navbar-light {
+  .navbar-brand {
+    color: $navbar-light-active-color;
+
+    @include hover-focus {
+      color: $navbar-light-active-color;
+    }
+  }
+
+  .navbar-nav {
+    .nav-link {
+      color: $navbar-light-color;
+
+      @include hover-focus {
+        color: $navbar-light-hover-color;
+      }
+
+      &.disabled {
+        color: $navbar-light-disabled-color;
+      }
+    }
+
+    .show > .nav-link,
+    .active > .nav-link,
+    .nav-link.show,
+    .nav-link.active {
+      color: $navbar-light-active-color;
+    }
+  }
+
+  .navbar-toggler {
+    color: $navbar-light-color;
+    border-color: $navbar-light-toggler-border-color;
+  }
+
+  .navbar-toggler-icon {
+    background-image: $navbar-light-toggler-icon-bg;
+  }
+
+  .navbar-text {
+    color: $navbar-light-color;
+    a {
+      color: $navbar-light-active-color;
+
+      @include hover-focus {
+        color: $navbar-light-active-color;
+      }
+    }
+  }
+}
+
+// White links against a dark background
+.navbar-dark {
+  .navbar-brand {
+    color: $navbar-dark-active-color;
+
+    @include hover-focus {
+      color: $navbar-dark-active-color;
+    }
+  }
+
+  .navbar-nav {
+    .nav-link {
+      color: $navbar-dark-color;
+
+      @include hover-focus {
+        color: $navbar-dark-hover-color;
+      }
+
+      &.disabled {
+        color: $navbar-dark-disabled-color;
+      }
+    }
+
+    .show > .nav-link,
+    .active > .nav-link,
+    .nav-link.show,
+    .nav-link.active {
+      color: $navbar-dark-active-color;
+    }
+  }
+
+  .navbar-toggler {
+    color: $navbar-dark-color;
+    border-color: $navbar-dark-toggler-border-color;
+  }
+
+  .navbar-toggler-icon {
+    background-image: $navbar-dark-toggler-icon-bg;
+  }
+
+  .navbar-text {
+    color: $navbar-dark-color;
+    a {
+      color: $navbar-dark-active-color;
+
+      @include hover-focus {
+        color: $navbar-dark-active-color;
+      }
+    }
+  }
+}
diff --git a/portal-FE-common/src/styles/bootstrap/_pagination.scss b/portal-FE-common/src/styles/bootstrap/_pagination.scss
new file mode 100644 (file)
index 0000000..286febc
--- /dev/null
@@ -0,0 +1,72 @@
+.pagination {
+  display: flex;
+  @include list-unstyled();
+  @include border-radius();
+}
+
+.page-link {
+  position: relative;
+  display: block;
+  padding: $pagination-padding-y $pagination-padding-x;
+  margin-left: -$pagination-border-width;
+  line-height: $pagination-line-height;
+  color: $pagination-color;
+  background-color: $pagination-bg;
+  border: $pagination-border-width solid $pagination-border-color;
+
+  @include hover-focus {
+    color: $pagination-hover-color;
+    text-decoration: none;
+    background-color: $pagination-hover-bg;
+    border-color: $pagination-hover-border-color;
+  }
+
+
+  // Opinionated: add "hand" cursor to non-disabled .page-link elements
+  &:not([disabled]):not(.disabled) {
+    cursor: pointer;
+  }
+}
+
+.page-item {
+  &:first-child {
+    .page-link {
+      margin-left: 0;
+      @include border-left-radius($border-radius);
+    }
+  }
+  &:last-child {
+    .page-link {
+      @include border-right-radius($border-radius);
+    }
+  }
+
+  &.active .page-link {
+    z-index: 1;
+    color: $pagination-active-color;
+    background-color: $pagination-active-bg;
+    border-color: $pagination-active-border-color;
+  }
+
+  &.disabled .page-link {
+    color: $pagination-disabled-color;
+    pointer-events: none;
+    // Opinionated: remove the "hand" cursor set previously for .page-link
+    cursor: auto;
+    background-color: $pagination-disabled-bg;
+    border-color: $pagination-disabled-border-color;
+  }
+}
+
+
+//
+// Sizing
+//
+
+.pagination-lg {
+  @include pagination-size($pagination-padding-y-lg, $pagination-padding-x-lg, $font-size-lg, $line-height-lg, $border-radius-lg);
+}
+
+.pagination-sm {
+  @include pagination-size($pagination-padding-y-sm, $pagination-padding-x-sm, $font-size-sm, $line-height-sm, $border-radius-sm);
+}
diff --git a/portal-FE-common/src/styles/bootstrap/_popover.scss b/portal-FE-common/src/styles/bootstrap/_popover.scss
new file mode 100644 (file)
index 0000000..3e41643
--- /dev/null
@@ -0,0 +1,183 @@
+.popover {
+  position: absolute;
+  top: 0;
+  left: 0;
+  z-index: $zindex-popover;
+  display: block;
+  max-width: $popover-max-width;
+  // Our parent element can be arbitrary since tooltips are by default inserted as a sibling of their target element.
+  // So reset our font and text properties to avoid inheriting weird values.
+  @include reset-text();
+  font-size: $font-size-sm;
+  // Allow breaking very long words so they don't overflow the popover's bounds
+  word-wrap: break-word;
+  background-color: $popover-bg;
+  background-clip: padding-box;
+  border: $popover-border-width solid $popover-border-color;
+  @include border-radius($border-radius-lg);
+  @include box-shadow($popover-box-shadow);
+
+  .arrow {
+    position: absolute;
+    display: block;
+    width: $popover-arrow-width;
+    height: $popover-arrow-height;
+    margin: 0 $border-radius-lg;
+
+    &::before,
+    &::after {
+      position: absolute;
+      display: block;
+      content: "";
+      border-color: transparent;
+      border-style: solid;
+    }
+  }
+}
+
+.bs-popover-top {
+  margin-bottom: $popover-arrow-height;
+
+  .arrow {
+    bottom: calc((#{$popover-arrow-height} + #{$popover-border-width}) * -1);
+  }
+
+  .arrow::before,
+  .arrow::after {
+    border-width: $popover-arrow-height ($popover-arrow-width / 2) 0;
+  }
+
+  .arrow::before {
+    bottom: 0;
+    border-top-color: $popover-arrow-outer-color;
+  }
+
+  .arrow::after {
+    bottom: $popover-border-width;
+    border-top-color: $popover-arrow-color;
+  }
+}
+
+.bs-popover-right {
+  margin-left: $popover-arrow-height;
+
+  .arrow {
+    left: calc((#{$popover-arrow-height} + #{$popover-border-width}) * -1);
+    width: $popover-arrow-height;
+    height: $popover-arrow-width;
+    margin: $border-radius-lg 0; // make sure the arrow does not touch the popover's rounded corners
+  }
+
+  .arrow::before,
+  .arrow::after {
+    border-width: ($popover-arrow-width / 2) $popover-arrow-height ($popover-arrow-width / 2) 0;
+  }
+
+  .arrow::before {
+    left: 0;
+    border-right-color: $popover-arrow-outer-color;
+  }
+
+  .arrow::after {
+    left: $popover-border-width;
+    border-right-color: $popover-arrow-color;
+  }
+}
+
+.bs-popover-bottom {
+  margin-top: $popover-arrow-height;
+
+  .arrow {
+    top: calc((#{$popover-arrow-height} + #{$popover-border-width}) * -1);
+  }
+
+  .arrow::before,
+  .arrow::after {
+    border-width: 0 ($popover-arrow-width / 2) $popover-arrow-height ($popover-arrow-width / 2);
+  }
+
+  .arrow::before {
+    top: 0;
+    border-bottom-color: $popover-arrow-outer-color;
+  }
+
+  .arrow::after {
+    top: $popover-border-width;
+    border-bottom-color: $popover-arrow-color;
+  }
+
+  // This will remove the popover-header's border just below the arrow
+  .popover-header::before {
+    position: absolute;
+    top: 0;
+    left: 50%;
+    display: block;
+    width: $popover-arrow-width;
+    margin-left: ($popover-arrow-width / -2);
+    content: "";
+    border-bottom: $popover-border-width solid $popover-header-bg;
+  }
+}
+
+.bs-popover-left {
+  margin-right: $popover-arrow-height;
+
+  .arrow {
+    right: calc((#{$popover-arrow-height} + #{$popover-border-width}) * -1);
+    width: $popover-arrow-height;
+    height: $popover-arrow-width;
+    margin: $border-radius-lg 0; // make sure the arrow does not touch the popover's rounded corners
+  }
+
+  .arrow::before,
+  .arrow::after {
+    border-width: ($popover-arrow-width / 2) 0 ($popover-arrow-width / 2) $popover-arrow-height;
+  }
+
+  .arrow::before {
+    right: 0;
+    border-left-color: $popover-arrow-outer-color;
+  }
+
+  .arrow::after {
+    right: $popover-border-width;
+    border-left-color: $popover-arrow-color;
+  }
+}
+
+.bs-popover-auto {
+  &[x-placement^="top"] {
+    @extend .bs-popover-top;
+  }
+  &[x-placement^="right"] {
+    @extend .bs-popover-right;
+  }
+  &[x-placement^="bottom"] {
+    @extend .bs-popover-bottom;
+  }
+  &[x-placement^="left"] {
+    @extend .bs-popover-left;
+  }
+}
+
+
+// Offset the popover to account for the popover arrow
+.popover-header {
+  padding: $popover-header-padding-y $popover-header-padding-x;
+  margin-bottom: 0; // Reset the default from Reboot
+  font-size: $font-size-base;
+  color: $popover-header-color;
+  background-color: $popover-header-bg;
+  border-bottom: $popover-border-width solid darken($popover-header-bg, 5%);
+  $offset-border-width: calc(#{$border-radius-lg} - #{$popover-border-width});
+  @include border-top-radius($offset-border-width);
+
+  &:empty {
+    display: none;
+  }
+}
+
+.popover-body {
+  padding: $popover-body-padding-y $popover-body-padding-x;
+  color: $popover-body-color;
+}
diff --git a/portal-FE-common/src/styles/bootstrap/_print.scss b/portal-FE-common/src/styles/bootstrap/_print.scss
new file mode 100644 (file)
index 0000000..6505d3e
--- /dev/null
@@ -0,0 +1,110 @@
+// stylelint-disable declaration-no-important, selector-no-qualifying-type
+
+// Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css
+
+// ==========================================================================
+// Print styles.
+// Inlined to avoid the additional HTTP request:
+// http://www.phpied.com/delay-loading-your-print-css/
+// ==========================================================================
+
+@if $enable-print-styles {
+  @media print {
+    *,
+    *::before,
+    *::after {
+      // Bootstrap specific; comment out `color` and `background`
+      //color: #000 !important; // Black prints faster: http://www.sanbeiji.com/archives/953
+      text-shadow: none !important;
+      //background: transparent !important;
+      box-shadow: none !important;
+    }
+
+    a,
+    a:visited {
+      text-decoration: underline;
+    }
+
+    // Bootstrap specific; comment the following selector out
+    //a[href]::after {
+    //  content: " (" attr(href) ")";
+    //}
+
+    abbr[title]::after {
+      content: " (" attr(title) ")";
+    }
+
+    // Bootstrap specific; comment the following selector out
+    //
+    // Don't show links that are fragment identifiers,
+    // or use the `javascript:` pseudo protocol
+    //
+
+    //a[href^="#"]::after,
+    //a[href^="javascript:"]::after {
+    // content: "";
+    //}
+
+    pre {
+      white-space: pre-wrap !important;
+    }
+    pre,
+    blockquote {
+      border: $border-width solid #999;   // Bootstrap custom code; using `$border-width` instead of 1px
+      page-break-inside: avoid;
+    }
+
+    //
+    // Printing Tables:
+    // http://css-discuss.incutio.com/wiki/Printing_Tables
+    //
+
+    thead {
+      display: table-header-group;
+    }
+
+    tr,
+    img {
+      page-break-inside: avoid;
+    }
+
+    p,
+    h2,
+    h3 {
+      orphans: 3;
+      widows: 3;
+    }
+
+    h2,
+    h3 {
+      page-break-after: avoid;
+    }
+
+    // Bootstrap specific changes start
+
+    // Bootstrap components
+    .navbar {
+      display: none;
+    }
+    .badge {
+      border: $border-width solid #000;
+    }
+
+    .table {
+      border-collapse: collapse !important;
+
+      td,
+      th {
+        background-color: #fff !important;
+      }
+    }
+    .table-bordered {
+      th,
+      td {
+        border: 1px solid #ddd !important;
+      }
+    }
+
+    // Bootstrap specific changes end
+  }
+}
diff --git a/portal-FE-common/src/styles/bootstrap/_progress.scss b/portal-FE-common/src/styles/bootstrap/_progress.scss
new file mode 100644 (file)
index 0000000..a581116
--- /dev/null
@@ -0,0 +1,33 @@
+@keyframes progress-bar-stripes {
+  from { background-position: $progress-height 0; }
+  to { background-position: 0 0; }
+}
+
+.progress {
+  display: flex;
+  height: $progress-height;
+  overflow: hidden; // force rounded corners by cropping it
+  font-size: $progress-font-size;
+  background-color: $progress-bg;
+  @include border-radius($progress-border-radius);
+  @include box-shadow($progress-box-shadow);
+}
+
+.progress-bar {
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  color: $progress-bar-color;
+  text-align: center;
+  background-color: $progress-bar-bg;
+  @include transition($progress-bar-transition);
+}
+
+.progress-bar-striped {
+  @include gradient-striped();
+  background-size: $progress-height $progress-height;
+}
+
+.progress-bar-animated {
+  animation: progress-bar-stripes $progress-bar-animation-timing;
+}
diff --git a/portal-FE-common/src/styles/bootstrap/_reboot.scss b/portal-FE-common/src/styles/bootstrap/_reboot.scss
new file mode 100644 (file)
index 0000000..5393413
--- /dev/null
@@ -0,0 +1,505 @@
+// stylelint-disable at-rule-no-vendor-prefix, declaration-no-important, selector-no-qualifying-type, property-no-vendor-prefix
+
+// Reboot
+//
+// Normalization of HTML elements, manually forked from Normalize.css to remove
+// styles targeting irrelevant browsers while applying new styles.
+//
+// Normalize is licensed MIT. https://github.com/necolas/normalize.css
+
+
+// Document
+//
+// 1. Change from `box-sizing: content-box` so that `width` is not affected by `padding` or `border`.
+// 2. Change the default font family in all browsers.
+// 3. Correct the line height in all browsers.
+// 4. Prevent adjustments of font size after orientation changes in IE on Windows Phone and in iOS.
+// 5. Setting @viewport causes scrollbars to overlap content in IE11 and Edge, so
+//    we force a non-overlapping, non-auto-hiding scrollbar to counteract.
+// 6. Change the default tap highlight to be completely transparent in iOS.
+
+*,
+*::before,
+*::after {
+  box-sizing: border-box; // 1
+}
+
+html {
+  font-family: sans-serif; // 2
+  line-height: 1.15; // 3
+  -webkit-text-size-adjust: 100%; // 4
+  -ms-text-size-adjust: 100%; // 4
+  -ms-overflow-style: scrollbar; // 5
+  -webkit-tap-highlight-color: rgba(0, 0, 0, 0); // 6
+}
+
+// IE10+ doesn't honor `<meta name="viewport">` in some cases.
+@at-root {
+  @-ms-viewport {
+    width: device-width;
+  }
+}
+
+// stylelint-disable selector-list-comma-newline-after
+// Shim for "new" HTML5 structural elements to display correctly (IE10, older browsers)
+article, aside, dialog, figcaption, figure, footer, header, hgroup, main, nav, section {
+  display: block;
+}
+// stylelint-enable selector-list-comma-newline-after
+
+// Body
+//
+// 1. Remove the margin in all browsers.
+// 2. As a best practice, apply a default `background-color`.
+// 3. Set an explicit initial text-align value so that we can later use the
+//    the `inherit` value on things like `<th>` elements.
+
+body {
+  margin: 0; // 1
+  font-family: $font-family-base;
+  font-size: $font-size-base;
+  font-weight: $font-weight-base;
+  line-height: $line-height-base;
+  color: $body-color;
+  text-align: left; // 3
+  background-color: $body-bg; // 2
+}
+
+// Suppress the focus outline on elements that cannot be accessed via keyboard.
+// This prevents an unwanted focus outline from appearing around elements that
+// might still respond to pointer events.
+//
+// Credit: https://github.com/suitcss/base
+[tabindex="-1"]:focus {
+  outline: 0 !important;
+}
+
+
+// Content grouping
+//
+// 1. Add the correct box sizing in Firefox.
+// 2. Show the overflow in Edge and IE.
+
+hr {
+  box-sizing: content-box; // 1
+  height: 0; // 1
+  overflow: visible; // 2
+}
+
+
+//
+// Typography
+//
+
+// Remove top margins from headings
+//
+// By default, `<h1>`-`<h6>` all receive top and bottom margins. We nuke the top
+// margin for easier control within type scales as it avoids margin collapsing.
+// stylelint-disable selector-list-comma-newline-after
+h1, h2, h3, h4, h5, h6 {
+  margin-top: 0;
+  margin-bottom: $headings-margin-bottom;
+}
+// stylelint-enable selector-list-comma-newline-after
+
+// Reset margins on paragraphs
+//
+// Similarly, the top margin on `<p>`s get reset. However, we also reset the
+// bottom margin to use `rem` units instead of `em`.
+p {
+  margin-top: 0;
+  margin-bottom: $paragraph-margin-bottom;
+}
+
+// Abbreviations
+//
+// 1. Remove the bottom border in Firefox 39-.
+// 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
+// 3. Add explicit cursor to indicate changed behavior.
+// 4. Duplicate behavior to the data-* attribute for our tooltip plugin
+
+abbr[title],
+abbr[data-original-title] { // 4
+  text-decoration: underline; // 2
+  text-decoration: underline dotted; // 2
+  cursor: help; // 3
+  border-bottom: 0; // 1
+}
+
+address {
+  margin-bottom: 1rem;
+  font-style: normal;
+  line-height: inherit;
+}
+
+ol,
+ul,
+dl {
+  margin-top: 0;
+  margin-bottom: 1rem;
+}
+
+ol ol,
+ul ul,
+ol ul,
+ul ol {
+  margin-bottom: 0;
+}
+
+dt {
+  font-weight: $dt-font-weight;
+}
+
+dd {
+  margin-bottom: .5rem;
+  margin-left: 0; // Undo browser default
+}
+
+blockquote {
+  margin: 0 0 1rem;
+}
+
+dfn {
+  font-style: italic; // Add the correct font style in Android 4.3-
+}
+
+// stylelint-disable font-weight-notation
+b,
+strong {
+  font-weight: bolder; // Add the correct font weight in Chrome, Edge, and Safari
+}
+// stylelint-enable font-weight-notation
+
+small {
+  font-size: 80%; // Add the correct font size in all browsers
+}
+
+//
+// Prevent `sub` and `sup` elements from affecting the line height in
+// all browsers.
+//
+
+sub,
+sup {
+  position: relative;
+  font-size: 75%;
+  line-height: 0;
+  vertical-align: baseline;
+}
+
+sub { bottom: -.25em; }
+sup { top: -.5em; }
+
+
+//
+// Links
+//
+
+a {
+  color: $link-color;
+  text-decoration: $link-decoration;
+  background-color: transparent; // Remove the gray background on active links in IE 10.
+  -webkit-text-decoration-skip: objects; // Remove gaps in links underline in iOS 8+ and Safari 8+.
+
+  @include hover {
+    color: $link-hover-color;
+    text-decoration: $link-hover-decoration;
+  }
+}
+
+// And undo these styles for placeholder links/named anchors (without href)
+// which have not been made explicitly keyboard-focusable (without tabindex).
+// It would be more straightforward to just use a[href] in previous block, but that
+// causes specificity issues in many other styles that are too complex to fix.
+// See https://github.com/twbs/bootstrap/issues/19402
+
+a:not([href]):not([tabindex]) {
+  color: inherit;
+  text-decoration: none;
+
+  @include hover-focus {
+    color: inherit;
+    text-decoration: none;
+  }
+
+  &:focus {
+    outline: 0;
+  }
+}
+
+
+//
+// Code
+//
+
+// stylelint-disable font-family-no-duplicate-names
+pre,
+code,
+kbd,
+samp {
+  font-family: monospace, monospace; // Correct the inheritance and scaling of font size in all browsers.
+  font-size: 1em; // Correct the odd `em` font sizing in all browsers.
+}
+// stylelint-enable font-family-no-duplicate-names
+
+pre {
+  // Remove browser default top margin
+  margin-top: 0;
+  // Reset browser default of `1em` to use `rem`s
+  margin-bottom: 1rem;
+  // Don't allow content to break outside
+  overflow: auto;
+  // We have @viewport set which causes scrollbars to overlap content in IE11 and Edge, so
+  // we force a non-overlapping, non-auto-hiding scrollbar to counteract.
+  -ms-overflow-style: scrollbar;
+}
+
+
+//
+// Figures
+//
+
+figure {
+  // Apply a consistent margin strategy (matches our type styles).
+  margin: 0 0 1rem;
+}
+
+
+//
+// Images and content
+//
+
+img {
+  vertical-align: middle;
+  border-style: none; // Remove the border on images inside links in IE 10-.
+}
+
+svg:not(:root) {
+  overflow: hidden; // Hide the overflow in IE
+}
+
+
+// Avoid 300ms click delay on touch devices that support the `touch-action` CSS property.
+//
+// In particular, unlike most other browsers, IE11+Edge on Windows 10 on touch devices and IE Mobile 10-11
+// DON'T remove the click delay when `<meta name="viewport" content="width=device-width">` is present.
+// However, they DO support removing the click delay via `touch-action: manipulation`.
+// See:
+// * https://getbootstrap.com/docs/4.0/content/reboot/#click-delay-optimization-for-touch
+// * https://caniuse.com/#feat=css-touch-action
+// * https://patrickhlauke.github.io/touch/tests/results/#suppressing-300ms-delay
+
+a,
+area,
+button,
+[role="button"],
+input:not([type="range"]),
+label,
+select,
+summary,
+textarea {
+  touch-action: manipulation;
+}
+
+
+//
+// Tables
+//
+
+table {
+  border-collapse: collapse; // Prevent double borders
+}
+
+caption {
+  padding-top: $table-cell-padding;
+  padding-bottom: $table-cell-padding;
+  color: $text-muted;
+  text-align: left;
+  caption-side: bottom;
+}
+
+th {
+  // Matches default `<td>` alignment by inheriting from the `<body>`, or the
+  // closest parent with a set `text-align`.
+  text-align: inherit;
+}
+
+
+//
+// Forms
+//
+
+label {
+  // Allow labels to use `margin` for spacing.
+  display: inline-block;
+  margin-bottom: .5rem;
+}
+
+// Remove the default `border-radius` that macOS Chrome adds.
+//
+// Details at https://github.com/twbs/bootstrap/issues/24093
+button {
+  border-radius: 0;
+}
+
+// Work around a Firefox/IE bug where the transparent `button` background
+// results in a loss of the default `button` focus styles.
+//
+// Credit: https://github.com/suitcss/base/
+button:focus {
+  outline: 1px dotted;
+  outline: 5px auto -webkit-focus-ring-color;
+}
+
+input,
+button,
+select,
+optgroup,
+textarea {
+  margin: 0; // Remove the margin in Firefox and Safari
+  font-family: inherit;
+  font-size: inherit;
+  line-height: inherit;
+}
+
+button,
+input {
+  overflow: visible; // Show the overflow in Edge
+}
+
+button,
+select {
+  text-transform: none; // Remove the inheritance of text transform in Firefox
+}
+
+// 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`
+//    controls in Android 4.
+// 2. Correct the inability to style clickable types in iOS and Safari.
+button,
+html [type="button"], // 1
+[type="reset"],
+[type="submit"] {
+  -webkit-appearance: button; // 2
+}
+
+// Remove inner border and padding from Firefox, but don't restore the outline like Normalize.
+button::-moz-focus-inner,
+[type="button"]::-moz-focus-inner,
+[type="reset"]::-moz-focus-inner,
+[type="submit"]::-moz-focus-inner {
+  padding: 0;
+  border-style: none;
+}
+
+input[type="radio"],
+input[type="checkbox"] {
+  box-sizing: border-box; // 1. Add the correct box sizing in IE 10-
+  padding: 0; // 2. Remove the padding in IE 10-
+}
+
+
+input[type="date"],
+input[type="time"],
+input[type="datetime-local"],
+input[type="month"] {
+  // Remove the default appearance of temporal inputs to avoid a Mobile Safari
+  // bug where setting a custom line-height prevents text from being vertically
+  // centered within the input.
+  // See https://bugs.webkit.org/show_bug.cgi?id=139848
+  // and https://github.com/twbs/bootstrap/issues/11266
+  -webkit-appearance: listbox;
+}
+
+textarea {
+  overflow: auto; // Remove the default vertical scrollbar in IE.
+  // Textareas should really only resize vertically so they don't break their (horizontal) containers.
+  resize: vertical;
+}
+
+fieldset {
+  // Browsers set a default `min-width: min-content;` on fieldsets,
+  // unlike e.g. `<div>`s, which have `min-width: 0;` by default.
+  // So we reset that to ensure fieldsets behave more like a standard block element.
+  // See https://github.com/twbs/bootstrap/issues/12359
+  // and https://html.spec.whatwg.org/multipage/#the-fieldset-and-legend-elements
+  min-width: 0;
+  // Reset the default outline behavior of fieldsets so they don't affect page layout.
+  padding: 0;
+  margin: 0;
+  border: 0;
+}
+
+// 1. Correct the text wrapping in Edge and IE.
+// 2. Correct the color inheritance from `fieldset` elements in IE.
+legend {
+  display: block;
+  width: 100%;
+  max-width: 100%; // 1
+  padding: 0;
+  margin-bottom: .5rem;
+  font-size: 1.5rem;
+  line-height: inherit;
+  color: inherit; // 2
+  white-space: normal; // 1
+}
+
+progress {
+  vertical-align: baseline; // Add the correct vertical alignment in Chrome, Firefox, and Opera.
+}
+
+// Correct the cursor style of increment and decrement buttons in Chrome.
+[type="number"]::-webkit-inner-spin-button,
+[type="number"]::-webkit-outer-spin-button {
+  height: auto;
+}
+
+[type="search"] {
+  // This overrides the extra rounded corners on search inputs in iOS so that our
+  // `.form-control` class can properly style them. Note that this cannot simply
+  // be added to `.form-control` as it's not specific enough. For details, see
+  // https://github.com/twbs/bootstrap/issues/11586.
+  outline-offset: -2px; // 2. Correct the outline style in Safari.
+  -webkit-appearance: none;
+}
+
+//
+// Remove the inner padding and cancel buttons in Chrome and Safari on macOS.
+//
+
+[type="search"]::-webkit-search-cancel-button,
+[type="search"]::-webkit-search-decoration {
+  -webkit-appearance: none;
+}
+
+//
+// 1. Correct the inability to style clickable types in iOS and Safari.
+// 2. Change font properties to `inherit` in Safari.
+//
+
+::-webkit-file-upload-button {
+  font: inherit; // 2
+  -webkit-appearance: button; // 1
+}
+
+//
+// Correct element displays
+//
+
+output {
+  display: inline-block;
+}
+
+summary {
+  display: list-item; // Add the correct display in all browsers
+  cursor: pointer;
+}
+
+template {
+  display: none; // Add the correct display in IE
+}
+
+// Always hide an element with the `hidden` HTML attribute (from PureCSS).
+// Needed for proper display in IE 10-.
+[hidden] {
+  display: none !important;
+}
diff --git a/portal-FE-common/src/styles/bootstrap/_root.scss b/portal-FE-common/src/styles/bootstrap/_root.scss
new file mode 100644 (file)
index 0000000..ad550df
--- /dev/null
@@ -0,0 +1,19 @@
+:root {
+  // Custom variable values only support SassScript inside `#{}`.
+  @each $color, $value in $colors {
+    --#{$color}: #{$value};
+  }
+
+  @each $color, $value in $theme-colors {
+    --#{$color}: #{$value};
+  }
+
+  @each $bp, $value in $grid-breakpoints {
+    --breakpoint-#{$bp}: #{$value};
+  }
+
+  // Use `inspect` for lists so that quoted items keep the quotes.
+  // See https://github.com/sass/sass/issues/2383#issuecomment-336349172
+  --font-family-sans-serif: #{inspect($font-family-sans-serif)};
+  --font-family-monospace: #{inspect($font-family-monospace)};
+}
diff --git a/portal-FE-common/src/styles/bootstrap/_tables.scss b/portal-FE-common/src/styles/bootstrap/_tables.scss
new file mode 100644 (file)
index 0000000..0e3b119
--- /dev/null
@@ -0,0 +1,180 @@
+//
+// Basic Bootstrap table
+//
+
+.table {
+  width: 100%;
+  max-width: 100%;
+  margin-bottom: $spacer;
+  background-color: $table-bg; // Reset for nesting within parents with `background-color`.
+
+  th,
+  td {
+    padding: $table-cell-padding;
+    vertical-align: top;
+    border-top: $table-border-width solid $table-border-color;
+  }
+
+  thead th {
+    vertical-align: bottom;
+    border-bottom: (2 * $table-border-width) solid $table-border-color;
+  }
+
+  tbody + tbody {
+    border-top: (2 * $table-border-width) solid $table-border-color;
+  }
+
+  .table {
+    background-color: $body-bg;
+  }
+}
+
+
+//
+// Condensed table w/ half padding
+//
+
+.table-sm {
+  th,
+  td {
+    padding: $table-cell-padding-sm;
+  }
+}
+
+
+// Bordered version
+//
+// Add borders all around the table and between all the columns.
+
+.table-bordered {
+  border: $table-border-width solid $table-border-color;
+
+  th,
+  td {
+    border: $table-border-width solid $table-border-color;
+  }
+
+  thead {
+    th,
+    td {
+      border-bottom-width: (2 * $table-border-width);
+    }
+  }
+}
+
+
+// Zebra-striping
+//
+// Default zebra-stripe styles (alternating gray and transparent backgrounds)
+
+.table-striped {
+  tbody tr:nth-of-type(odd) {
+    background-color: $table-accent-bg;
+  }
+}
+
+
+// Hover effect
+//
+// Placed here since it has to come after the potential zebra striping
+
+.table-hover {
+  tbody tr {
+    @include hover {
+      background-color: $table-hover-bg;
+    }
+  }
+}
+
+
+// Table backgrounds
+//
+// Exact selectors below required to override `.table-striped` and prevent
+// inheritance to nested tables.
+
+@each $color, $value in $theme-colors {
+  @include table-row-variant($color, theme-color-level($color, -9));
+}
+
+@include table-row-variant(active, $table-active-bg);
+
+
+// Dark styles
+//
+// Same table markup, but inverted color scheme: dark background and light text.
+
+// stylelint-disable-next-line no-duplicate-selectors
+.table {
+  .thead-dark {
+    th {
+      color: $table-dark-color;
+      background-color: $table-dark-bg;
+      border-color: $table-dark-border-color;
+    }
+  }
+
+  .thead-light {
+    th {
+      color: $table-head-color;
+      background-color: $table-head-bg;
+      border-color: $table-border-color;
+    }
+  }
+}
+
+.table-dark {
+  color: $table-dark-color;
+  background-color: $table-dark-bg;
+
+  th,
+  td,
+  thead th {
+    border-color: $table-dark-border-color;
+  }
+
+  &.table-bordered {
+    border: 0;
+  }
+
+  &.table-striped {
+    tbody tr:nth-of-type(odd) {
+      background-color: $table-dark-accent-bg;
+    }
+  }
+
+  &.table-hover {
+    tbody tr {
+      @include hover {
+        background-color: $table-dark-hover-bg;
+      }
+    }
+  }
+}
+
+
+// Responsive tables
+//
+// Generate series of `.table-responsive-*` classes for configuring the screen
+// size of where your table will overflow.
+
+.table-responsive {
+  @each $breakpoint in map-keys($grid-breakpoints) {
+    $next: breakpoint-next($breakpoint, $grid-breakpoints);
+    $infix: breakpoint-infix($next, $grid-breakpoints);
+
+    &#{$infix} {
+      @include media-breakpoint-down($breakpoint) {
+        display: block;
+        width: 100%;
+        overflow-x: auto;
+        -webkit-overflow-scrolling: touch;
+        -ms-overflow-style: -ms-autohiding-scrollbar; // See https://github.com/twbs/bootstrap/pull/10057
+
+        // Prevent double border on horizontal scroll due to use of `display: block;`
+        > .table-bordered {
+          border: 0;
+        }
+      }
+    }
+  }
+}
diff --git a/portal-FE-common/src/styles/bootstrap/_tooltip.scss b/portal-FE-common/src/styles/bootstrap/_tooltip.scss
new file mode 100644 (file)
index 0000000..a03de57
--- /dev/null
@@ -0,0 +1,115 @@
+// Base class
+.tooltip {
+  position: absolute;
+  z-index: $zindex-tooltip;
+  display: block;
+  margin: $tooltip-margin;
+  // Our parent element can be arbitrary since tooltips are by default inserted as a sibling of their target element.
+  // So reset our font and text properties to avoid inheriting weird values.
+  @include reset-text();
+  font-size: $font-size-sm;
+  // Allow breaking very long words so they don't overflow the tooltip's bounds
+  word-wrap: break-word;
+  opacity: 0;
+
+  &.show { opacity: $tooltip-opacity; }
+
+  .arrow {
+    position: absolute;
+    display: block;
+    width: $tooltip-arrow-width;
+    height: $tooltip-arrow-height;
+
+    &::before {
+      position: absolute;
+      content: "";
+      border-color: transparent;
+      border-style: solid;
+    }
+  }
+}
+
+.bs-tooltip-top {
+  padding: $tooltip-arrow-height 0;
+
+  .arrow {
+    bottom: 0;
+
+    &::before {
+      top: 0;
+      border-width: $tooltip-arrow-height ($tooltip-arrow-width / 2) 0;
+      border-top-color: $tooltip-arrow-color;
+    }
+  }
+}
+
+.bs-tooltip-right {
+  padding: 0 $tooltip-arrow-height;
+
+  .arrow {
+    left: 0;
+    width: $tooltip-arrow-height;
+    height: $tooltip-arrow-width;
+
+    &::before {
+      right: 0;
+      border-width: ($tooltip-arrow-width / 2) $tooltip-arrow-height ($tooltip-arrow-width / 2) 0;
+      border-right-color: $tooltip-arrow-color;
+    }
+  }
+}
+
+.bs-tooltip-bottom {
+  padding: $tooltip-arrow-height 0;
+
+  .arrow {
+    top: 0;
+
+    &::before {
+      bottom: 0;
+      border-width: 0 ($tooltip-arrow-width / 2) $tooltip-arrow-height;
+      border-bottom-color: $tooltip-arrow-color;
+    }
+  }
+}
+
+.bs-tooltip-left {
+  padding: 0 $tooltip-arrow-height;
+
+  .arrow {
+    right: 0;
+    width: $tooltip-arrow-height;
+    height: $tooltip-arrow-width;
+
+    &::before {
+      left: 0;
+      border-width: ($tooltip-arrow-width / 2) 0 ($tooltip-arrow-width / 2) $tooltip-arrow-height;
+      border-left-color: $tooltip-arrow-color;
+    }
+  }
+}
+
+.bs-tooltip-auto {
+  &[x-placement^="top"] {
+    @extend .bs-tooltip-top;
+  }
+  &[x-placement^="right"] {
+    @extend .bs-tooltip-right;
+  }
+  &[x-placement^="bottom"] {
+    @extend .bs-tooltip-bottom;
+  }
+  &[x-placement^="left"] {
+    @extend .bs-tooltip-left;
+  }
+}
+
+// Wrapper for the tooltip content
+.tooltip-inner {
+  max-width: $tooltip-max-width;
+  padding: $tooltip-padding-y $tooltip-padding-x;
+  color: $tooltip-color;
+  text-align: center;
+  background-color: $tooltip-bg;
+  @include border-radius($border-radius);
+}
diff --git a/portal-FE-common/src/styles/bootstrap/_transitions.scss b/portal-FE-common/src/styles/bootstrap/_transitions.scss
new file mode 100644 (file)
index 0000000..df5744b
--- /dev/null
@@ -0,0 +1,36 @@
+// stylelint-disable selector-no-qualifying-type
+
+.fade {
+  opacity: 0;
+  @include transition($transition-fade);
+
+  &.show {
+    opacity: 1;
+  }
+}
+
+.collapse {
+  display: none;
+  &.show {
+    display: block;
+  }
+}
+
+tr {
+  &.collapse.show {
+    display: table-row;
+  }
+}
+
+tbody {
+  &.collapse.show {
+    display: table-row-group;
+  }
+}
+
+.collapsing {
+  position: relative;
+  height: 0;
+  overflow: hidden;
+  @include transition($transition-collapse);
+}
diff --git a/portal-FE-common/src/styles/bootstrap/_type.scss b/portal-FE-common/src/styles/bootstrap/_type.scss
new file mode 100644 (file)
index 0000000..57d610f
--- /dev/null
@@ -0,0 +1,125 @@
+// stylelint-disable declaration-no-important, selector-list-comma-newline-after
+
+//
+// Headings
+//
+
+h1, h2, h3, h4, h5, h6,
+.h1, .h2, .h3, .h4, .h5, .h6 {
+  margin-bottom: $headings-margin-bottom;
+  font-family: $headings-font-family;
+  font-weight: $headings-font-weight;
+  line-height: $headings-line-height;
+  color: $headings-color;
+}
+
+h1, .h1 { font-size: $h1-font-size; }
+h2, .h2 { font-size: $h2-font-size; }
+h3, .h3 { font-size: $h3-font-size; }
+h4, .h4 { font-size: $h4-font-size; }
+h5, .h5 { font-size: $h5-font-size; }
+h6, .h6 { font-size: $h6-font-size; }
+
+.lead {
+  font-size: $lead-font-size;
+  font-weight: $lead-font-weight;
+}
+
+// Type display classes
+.display-1 {
+  font-size: $display1-size;
+  font-weight: $display1-weight;
+  line-height: $display-line-height;
+}
+.display-2 {
+  font-size: $display2-size;
+  font-weight: $display2-weight;
+  line-height: $display-line-height;
+}
+.display-3 {
+  font-size: $display3-size;
+  font-weight: $display3-weight;
+  line-height: $display-line-height;
+}
+.display-4 {
+  font-size: $display4-size;
+  font-weight: $display4-weight;
+  line-height: $display-line-height;
+}
+
+
+//
+// Horizontal rules
+//
+
+hr {
+  margin-top: $hr-margin-y;
+  margin-bottom: $hr-margin-y;
+  border: 0;
+  border-top: $hr-border-width solid $hr-border-color;
+}
+
+
+//
+// Emphasis
+//
+
+small,
+.small {
+  font-size: $small-font-size;
+  font-weight: $font-weight-normal;
+}
+
+mark,
+.mark {
+  padding: $mark-padding;
+  background-color: $mark-bg;
+}
+
+
+//
+// Lists
+//
+
+.list-unstyled {
+  @include list-unstyled;
+}
+
+// Inline turns list items into inline-block
+.list-inline {
+  @include list-unstyled;
+}
+.list-inline-item {
+  display: inline-block;
+
+  &:not(:last-child) {
+    margin-right: $list-inline-padding;
+  }
+}
+
+
+//
+// Misc
+//
+
+// Builds on `abbr`
+.initialism {
+  font-size: 90%;
+  text-transform: uppercase;
+}
+
+// Blockquotes
+.blockquote {
+  margin-bottom: $spacer;
+  font-size: $blockquote-font-size;
+}
+
+.blockquote-footer {
+  display: block;
+  font-size: 80%; // back to default font-size
+  color: $blockquote-small-color;
+
+  &::before {
+    content: "\2014 \00A0"; // em dash, nbsp
+  }
+}
diff --git a/portal-FE-common/src/styles/bootstrap/_utilities.scss b/portal-FE-common/src/styles/bootstrap/_utilities.scss
new file mode 100644 (file)
index 0000000..7b2a1eb
--- /dev/null
@@ -0,0 +1,14 @@
+@import "utilities/align";
+@import "utilities/background";
+@import "utilities/borders";
+@import "utilities/clearfix";
+@import "utilities/display";
+@import "utilities/embed";
+@import "utilities/flex";
+@import "utilities/float";
+@import "utilities/position";
+@import "utilities/screenreaders";
+@import "utilities/sizing";
+@import "utilities/spacing";
+@import "utilities/text";
+@import "utilities/visibility";
diff --git a/portal-FE-common/src/styles/bootstrap/_variables.scss b/portal-FE-common/src/styles/bootstrap/_variables.scss
new file mode 100644 (file)
index 0000000..2dde711
--- /dev/null
@@ -0,0 +1,874 @@
+// import font
+@import url(http://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,400,300,600);
+// Variables
+//
+// Variables should follow the `$component-state-property-size` formula for
+// consistent naming. Ex: $nav-link-disabled-color and $modal-content-box-shadow-xs.
+
+
+//
+// Color system
+//
+
+// stylelint-disable
+$white:    #fff !default;
+$gray-100: #f8f9fa !default;
+$gray-200: #e9ecef !default;
+$gray-300: #dee2e6 !default;
+$gray-400: #ced4da !default;
+$gray-500: #adb5bd !default;
+$gray-600: #868e96 !default;
+$gray-700: #495057 !default;
+$gray-800: #343a40 !default;
+$gray-900: #212529 !default;
+$black:    #000 !default;
+
+$grays: () !default;
+$grays: map-merge((
+  "100": $gray-100,
+  "200": $gray-200,
+  "300": $gray-300,
+  "400": $gray-400,
+  "500": $gray-500,
+  "600": $gray-600,
+  "700": $gray-700,
+  "800": $gray-800,
+  "900": $gray-900
+), $grays);
+
+$blue:    #007bff !default;
+$indigo:  #6610f2 !default;
+$purple:  #6f42c1 !default;
+$pink:    #e83e8c !default;
+$red:     #dc3545 !default;
+$orange:  #fd7e14 !default;
+$yellow:  #ffc107 !default;
+$green:   #28a745 !default;
+$teal:    #20c997 !default;
+$cyan:    #17a2b8 !default;
+
+$colors: () !default;
+$colors: map-merge((
+  "blue":       $blue,
+  "indigo":     $indigo,
+  "purple":     $purple,
+  "pink":       $pink,
+  "red":        $red,
+  "orange":     $orange,
+  "yellow":     $yellow,
+  "green":      $green,
+  "teal":       $teal,
+  "cyan":       $cyan,
+  "white":      $white,
+  "gray":       $gray-600,
+  "gray-dark":  $gray-800
+), $colors);
+
+$primary:       $blue !default;
+$secondary:     $gray-600 !default;
+$success:       $green !default;
+$info:          $cyan !default;
+$warning:       $yellow !default;
+$danger:        $red !default;
+$light:         $gray-100 !default;
+$dark:          $gray-800 !default;
+
+$theme-colors: () !default;
+$theme-colors: map-merge((
+  "primary":    $primary,
+  "secondary":  $secondary,
+  "success":    $success,
+  "info":       $info,
+  "warning":    $warning,
+  "danger":     $danger,
+  "light":      $light,
+  "dark":       $dark
+), $theme-colors);
+// stylelint-enable
+
+// Set a specific jump point for requesting color jumps
+$theme-color-interval:      8% !default;
+
+// The yiq lightness value that determines when the lightness of color changes from "dark" to "light". Acceptable values are between 0 and 255.
+$yiq-contrasted-threshold: 150 !default;
+
+// Customize the light and dark text colors for use in our YIQ color contrast function.
+$yiq-text-dark: $gray-900 !default;
+$yiq-text-light: $white !default;
+
+// Options
+//
+// Quickly modify global styling by enabling or disabling optional features.
+
+$enable-caret:              true !default;
+$enable-rounded:            true !default;
+$enable-shadows:            false !default;
+$enable-gradients:          false !default;
+$enable-transitions:        true !default;
+$enable-hover-media-query:  false !default;
+$enable-grid-classes:       true !default;
+$enable-print-styles:       true !default;
+
+
+// Spacing
+//
+// Control the default styling of most Bootstrap elements by modifying these
+// variables. Mostly focused on spacing.
+// You can add more entries to the $spacers map, should you need more variation.
+
+$spacer: 1rem !default;
+$spacers: (
+  0: 0,
+  1: ($spacer * .25),
+  2: ($spacer * .5),
+  3: $spacer,
+  4: ($spacer * 1.5),
+  5: ($spacer * 3)
+) !default;
+
+// This variable affects the `.h-*` and `.w-*` classes.
+$sizes: (
+  25: 25%,
+  50: 50%,
+  75: 75%,
+  100: 100%
+) !default;
+
+// Body
+//
+// Settings for the `<body>` element.
+
+$body-bg:                   $white !default;
+$body-color:                $gray-900 !default;
+
+// Links
+//
+// Style anchor elements.
+
+$link-color:                theme-color("primary") !default;
+$link-decoration:           none !default;
+$link-hover-color:          darken($link-color, 15%) !default;
+$link-hover-decoration:     underline !default;
+
+// Paragraphs
+//
+// Style p element.
+
+$paragraph-margin-bottom:   1rem !default;
+
+
+// Grid breakpoints
+//
+// Define the minimum dimensions at which your layout will change,
+// adapting to different screen sizes, for use in media queries.
+
+$grid-breakpoints: (
+  xs: 0,
+  sm: 576px,
+  md: 768px,
+  lg: 992px,
+  xl: 1200px
+) !default;
+
+@include _assert-ascending($grid-breakpoints, "$grid-breakpoints");
+@include _assert-starts-at-zero($grid-breakpoints);
+
+
+// Grid containers
+//
+// Define the maximum width of `.container` for different screen sizes.
+
+$container-max-widths: (
+  sm: 540px,
+  md: 720px,
+  lg: 960px,
+  xl: 1140px
+) !default;
+
+@include _assert-ascending($container-max-widths, "$container-max-widths");
+
+
+// Grid columns
+//
+// Set the number of columns and specify the width of the gutters.
+
+$grid-columns:                12 !default;
+$grid-gutter-width:           30px !default;
+
+// Components
+//
+// Define common padding and border radius sizes and more.
+
+$line-height-lg:              1.5 !default;
+$line-height-sm:              1.5 !default;
+
+$border-width:                1px !default;
+$border-color:                $gray-200 !default;
+
+$border-radius:               .25rem !default;
+$border-radius-lg:            .3rem !default;
+$border-radius-sm:            .2rem !default;
+
+$component-active-color:      $white !default;
+$component-active-bg:         theme-color("primary") !default;
+
+$caret-width:                 .3em !default;
+
+$transition-base:             all .2s ease-in-out !default;
+$transition-fade:             opacity .15s linear !default;
+$transition-collapse:         height .35s ease !default;
+
+
+// Fonts
+//
+// Font, line-height, and color for body text, headings, and more.
+
+// stylelint-disable value-keyword-case
+$font-family-sans-serif:      "Open Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol" !default;
+$font-family-monospace:       "Open Sans", "SFMono-Regular", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace !default;
+$font-family-base:            $font-family-sans-serif !default;
+// stylelint-enable value-keyword-case
+
+$font-size-base:              1rem !default; // Assumes the browser default, typically `16px`
+$font-size-lg:                ($font-size-base * 1.25) !default;
+$font-size-sm:                ($font-size-base * .875) !default;
+
+$font-weight-light:           300 !default;
+$font-weight-normal:          400 !default;
+$font-weight-bold:            700 !default;
+
+$font-weight-base:            $font-weight-normal !default;
+$line-height-base:            1.5 !default;
+
+$h1-font-size:                $font-size-base * 2.5 !default;
+$h2-font-size:                $font-size-base * 2 !default;
+$h3-font-size:                $font-size-base * 1.75 !default;
+$h4-font-size:                $font-size-base * 1.5 !default;
+$h5-font-size:                $font-size-base * 1.25 !default;
+$h6-font-size:                $font-size-base !default;
+
+$headings-margin-bottom:      ($spacer / 2) !default;
+$headings-font-family:        inherit !default;
+$headings-font-weight:        500 !default;
+$headings-line-height:        1.2 !default;
+$headings-color:              inherit !default;
+
+$display1-size:               6rem !default;
+$display2-size:               5.5rem !default;
+$display3-size:               4.5rem !default;
+$display4-size:               3.5rem !default;
+
+$display1-weight:             300 !default;
+$display2-weight:             300 !default;
+$display3-weight:             300 !default;
+$display4-weight:             300 !default;
+$display-line-height:         $headings-line-height !default;
+
+$lead-font-size:              ($font-size-base * 1.25) !default;
+$lead-font-weight:            300 !default;
+
+$small-font-size:             80% !default;
+
+$text-muted:                  $gray-600 !default;
+
+$blockquote-small-color:      $gray-600 !default;
+$blockquote-font-size:        ($font-size-base * 1.25) !default;
+
+$hr-border-color:             rgba($black, .1) !default;
+$hr-border-width:             $border-width !default;
+
+$mark-padding:                .2em !default;
+
+$dt-font-weight:              $font-weight-bold !default;
+
+$kbd-box-shadow:              inset 0 -.1rem 0 rgba($black, .25) !default;
+$nested-kbd-font-weight:      $font-weight-bold !default;
+
+$list-inline-padding:         .5rem !default;
+
+$mark-bg:                     #fcf8e3 !default;
+
+$hr-margin-y:                 $spacer !default;
+
+
+// Tables
+//
+// Customizes the `.table` component with basic values, each used across all table variations.
+
+$table-cell-padding:          .75rem !default;
+$table-cell-padding-sm:       .3rem !default;
+
+$table-bg:                    transparent !default;
+$table-accent-bg:             rgba($black, .05) !default;
+$table-hover-bg:              rgba($black, .075) !default;
+$table-active-bg:             $table-hover-bg !default;
+
+$table-border-width:          $border-width !default;
+$table-border-color:          $gray-300 !default;
+
+$table-head-bg:               $gray-200 !default;
+$table-head-color:            $gray-700 !default;
+
+$table-dark-bg:               $gray-900 !default;
+$table-dark-accent-bg:        rgba($white, .05) !default;
+$table-dark-hover-bg:         rgba($white, .075) !default;
+$table-dark-border-color:     lighten($gray-900, 7.5%) !default;
+$table-dark-color:            $body-bg !default;
+
+
+// Buttons + Forms
+//
+// Shared variables that are reassigned to `$input-` and `$btn-` specific variables.
+
+$input-btn-padding-y:         .375rem !default;
+$input-btn-padding-x:         .75rem !default;
+$input-btn-line-height:       $line-height-base !default;
+
+$input-btn-focus-width:       .2rem !default;
+$input-btn-focus-color:       rgba(theme-color("primary"), .25) !default;
+$input-btn-focus-box-shadow:  0 0 0 $input-btn-focus-width $input-btn-focus-color !default;
+
+$input-btn-padding-y-sm:      .25rem !default;
+$input-btn-padding-x-sm:      .5rem !default;
+$input-btn-line-height-sm:    $line-height-sm !default;
+
+$input-btn-padding-y-lg:      .5rem !default;
+$input-btn-padding-x-lg:      1rem !default;
+$input-btn-line-height-lg:    $line-height-lg !default;
+
+$input-btn-border-width:      $border-width !default;
+
+
+// Buttons
+//
+// For each of Bootstrap's buttons, define text, background, and border color.
+
+$btn-padding-y:               $input-btn-padding-y !default;
+$btn-padding-x:               $input-btn-padding-x !default;
+$btn-line-height:             $input-btn-line-height !default;
+
+$btn-padding-y-sm:            $input-btn-padding-y-sm !default;
+$btn-padding-x-sm:            $input-btn-padding-x-sm !default;
+$btn-line-height-sm:          $input-btn-line-height-sm !default;
+
+$btn-padding-y-lg:            $input-btn-padding-y-lg !default;
+$btn-padding-x-lg:            $input-btn-padding-x-lg !default;
+$btn-line-height-lg:          $input-btn-line-height-lg !default;
+
+$btn-border-width:            $input-btn-border-width !default;
+
+$btn-font-weight:             $font-weight-normal !default;
+$btn-box-shadow:              inset 0 1px 0 rgba($white, .15), 0 1px 1px rgba($black, .075) !default;
+$btn-focus-width:             $input-btn-focus-width !default;
+$btn-focus-box-shadow:        $input-btn-focus-box-shadow !default;
+$btn-disabled-opacity:        .65 !default;
+$btn-active-box-shadow:       inset 0 3px 5px rgba($black, .125) !default;
+
+$btn-link-disabled-color:     $gray-600 !default;
+
+$btn-block-spacing-y:         .5rem !default;
+
+// Allows for customizing button radius independently from global border radius
+$btn-border-radius:           $border-radius !default;
+$btn-border-radius-lg:        $border-radius-lg !default;
+$btn-border-radius-sm:        $border-radius-sm !default;
+
+$btn-transition:              color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;
+
+
+// Forms
+
+$input-padding-y:                       $input-btn-padding-y !default;
+$input-padding-x:                       $input-btn-padding-x !default;
+$input-line-height:                     $input-btn-line-height !default;
+
+$input-padding-y-sm:                    $input-btn-padding-y-sm !default;
+$input-padding-x-sm:                    $input-btn-padding-x-sm !default;
+$input-line-height-sm:                  $input-btn-line-height-sm !default;
+
+$input-padding-y-lg:                    $input-btn-padding-y-lg !default;
+$input-padding-x-lg:                    $input-btn-padding-x-lg !default;
+$input-line-height-lg:                  $input-btn-line-height-lg !default;
+
+$input-bg:                              $white !default;
+$input-disabled-bg:                     $gray-200 !default;
+
+$input-color:                           $gray-700 !default;
+$input-border-color:                    $gray-400 !default;
+$input-border-width:                    $input-btn-border-width !default;
+$input-box-shadow:                      inset 0 1px 1px rgba($black, .075) !default;
+
+$input-border-radius:                   $border-radius !default;
+$input-border-radius-lg:                $border-radius-lg !default;
+$input-border-radius-sm:                $border-radius-sm !default;
+
+$input-focus-bg:                        $input-bg !default;
+$input-focus-border-color:              lighten(theme-color("primary"), 25%) !default;
+$input-focus-color:                     $input-color !default;
+$input-focus-width:                     $input-btn-focus-width !default;
+$input-focus-box-shadow:                $input-btn-focus-box-shadow !default;
+
+$input-placeholder-color:               $gray-600 !default;
+
+$input-height-border:                   $input-btn-border-width * 2 !default;
+
+$input-height-inner:                    ($font-size-base * $input-btn-line-height) + ($input-btn-padding-y * 2) !default;
+$input-height:                          calc(#{$input-height-inner} + #{$input-height-border}) !default;
+
+$input-height-inner-sm:                 ($font-size-sm * $input-btn-line-height-sm) + ($input-btn-padding-y-sm * 2) !default;
+$input-height-sm:                       calc(#{$input-height-inner-sm} + #{$input-height-border}) !default;
+
+$input-height-inner-lg:                 ($font-size-lg * $input-btn-line-height-lg) + ($input-btn-padding-y-lg * 2) !default;
+$input-height-lg:                       calc(#{$input-height-inner-lg} + #{$input-height-border}) !default;
+
+$input-transition:                      border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;
+
+$form-text-margin-top:                  .25rem !default;
+
+$form-check-input-gutter:               1.25rem !default;
+$form-check-input-margin-y:             .3rem !default;
+$form-check-input-margin-x:             .25rem !default;
+
+$form-check-inline-margin-x:            .75rem !default;
+$form-check-inline-input-margin-x:      .3125rem !default;
+
+$form-group-margin-bottom:              1rem !default;
+
+$input-group-addon-color:               $input-color !default;
+$input-group-addon-bg:                  $gray-200 !default;
+$input-group-addon-border-color:        $input-border-color !default;
+
+$custom-control-gutter:                 1.5rem !default;
+$custom-control-spacer-x:               1rem !default;
+
+$custom-control-indicator-size:         1rem !default;
+$custom-control-indicator-bg:           $gray-300 !default;
+$custom-control-indicator-bg-size:      50% 50% !default;
+$custom-control-indicator-box-shadow:   inset 0 .25rem .25rem rgba($black, .1) !default;
+
+$custom-control-indicator-disabled-bg:          $gray-200 !default;
+$custom-control-label-disabled-color:     $gray-600 !default;
+
+$custom-control-indicator-checked-color:        $white !default;
+$custom-control-indicator-checked-bg:           theme-color("primary") !default;
+$custom-control-indicator-checked-box-shadow:   none !default;
+
+$custom-control-indicator-focus-box-shadow:     0 0 0 1px $body-bg, $input-btn-focus-box-shadow !default;
+
+$custom-control-indicator-active-color:         $white !default;
+$custom-control-indicator-active-bg:            lighten(theme-color("primary"), 35%) !default;
+$custom-control-indicator-active-box-shadow:    none !default;
+
+$custom-checkbox-indicator-border-radius:       $border-radius !default;
+$custom-checkbox-indicator-icon-checked:        str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='#{$custom-control-indicator-checked-color}' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"), "#", "%23") !default;
+
+$custom-checkbox-indicator-indeterminate-bg:    theme-color("primary") !default;
+$custom-checkbox-indicator-indeterminate-color: $custom-control-indicator-checked-color !default;
+$custom-checkbox-indicator-icon-indeterminate:  str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3E%3Cpath stroke='#{$custom-checkbox-indicator-indeterminate-color}' d='M0 2h4'/%3E%3C/svg%3E"), "#", "%23") !default;
+$custom-checkbox-indicator-indeterminate-box-shadow: none !default;
+
+$custom-radio-indicator-border-radius:          50% !default;
+$custom-radio-indicator-icon-checked:           str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='#{$custom-control-indicator-checked-color}'/%3E%3C/svg%3E"), "#", "%23") !default;
+
+$custom-select-padding-y:           .375rem !default;
+$custom-select-padding-x:          .75rem !default;
+$custom-select-height:              $input-height !default;
+$custom-select-indicator-padding:   1rem !default; // Extra padding to account for the presence of the background-image based indicator
+$custom-select-line-height:         $input-btn-line-height !default;
+$custom-select-color:               $input-color !default;
+$custom-select-disabled-color:      $gray-600 !default;
+$custom-select-bg:                  $white !default;
+$custom-select-disabled-bg:         $gray-200 !default;
+$custom-select-bg-size:             8px 10px !default; // In pixels because image dimensions
+$custom-select-indicator-color:     $gray-800 !default;
+$custom-select-indicator:           str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='#{$custom-select-indicator-color}' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E"), "#", "%23") !default;
+$custom-select-border-width:        $input-btn-border-width !default;
+$custom-select-border-color:        $input-border-color !default;
+$custom-select-border-radius:       $border-radius !default;
+
+$custom-select-focus-border-color:  $input-focus-border-color !default;
+$custom-select-focus-box-shadow:    inset 0 1px 2px rgba($black, .075), $input-btn-focus-box-shadow !default;
+
+$custom-select-font-size-sm:        75% !default;
+$custom-select-height-sm:           $input-height-sm !default;
+
+$custom-select-font-size-lg:        125% !default;
+$custom-select-height-lg:           $input-height-lg !default;
+
+$custom-file-height:                $input-height !default;
+$custom-file-focus-border-color:    $input-focus-border-color !default;
+$custom-file-focus-box-shadow:      $input-btn-focus-box-shadow !default;
+
+$custom-file-padding-y:             $input-btn-padding-y !default;
+$custom-file-padding-x:             $input-btn-padding-x !default;
+$custom-file-line-height:           $input-btn-line-height !default;
+$custom-file-color:                 $input-color !default;
+$custom-file-bg:                    $input-bg !default;
+$custom-file-border-width:          $input-btn-border-width !default;
+$custom-file-border-color:          $input-border-color !default;
+$custom-file-border-radius:         $input-border-radius !default;
+$custom-file-box-shadow:            $input-box-shadow !default;
+$custom-file-button-color:          $custom-file-color !default;
+$custom-file-button-bg:             $input-group-addon-bg !default;
+$custom-file-text: (
+  en: "Browse"
+) !default;
+
+
+// Form validation
+$form-feedback-margin-top:          $form-text-margin-top !default;
+$form-feedback-font-size:           $small-font-size !default;
+$form-feedback-valid-color:         theme-color("success") !default;
+$form-feedback-invalid-color:       theme-color("danger") !default;
+
+
+// Dropdowns
+//
+// Dropdown menu container and contents.
+
+$dropdown-min-width:                10rem !default;
+$dropdown-padding-y:                .5rem !default;
+$dropdown-spacer:                   .125rem !default;
+$dropdown-bg:                       $white !default;
+$dropdown-border-color:             rgba($black, .15) !default;
+$dropdown-border-radius:            $border-radius !default;
+$dropdown-border-width:             $border-width !default;
+$dropdown-divider-bg:               $gray-200 !default;
+$dropdown-box-shadow:               0 .5rem 1rem rgba($black, .175) !default;
+
+$dropdown-link-color:               $gray-900 !default;
+$dropdown-link-hover-color:         darken($gray-900, 5%) !default;
+$dropdown-link-hover-bg:            $gray-100 !default;
+
+$dropdown-link-active-color:        $component-active-color !default;
+$dropdown-link-active-bg:           $component-active-bg !default;
+
+$dropdown-link-disabled-color:      $gray-600 !default;
+
+$dropdown-item-padding-y:           .25rem !default;
+$dropdown-item-padding-x:           1.5rem !default;
+
+$dropdown-header-color:             $gray-600 !default;
+
+
+// Z-index master list
+//
+// Warning: Avoid customizing these values. They're used for a bird's eye view
+// of components dependent on the z-axis and are designed to all work together.
+
+$zindex-dropdown:                   1000 !default;
+$zindex-sticky:                     1020 !default;
+$zindex-fixed:                      1030 !default;
+$zindex-modal-backdrop:             1040 !default;
+$zindex-modal:                      1050 !default;
+$zindex-popover:                    1060 !default;
+$zindex-tooltip:                    1070 !default;
+
+// Navs
+
+$nav-link-padding-y:                .5rem !default;
+$nav-link-padding-x:                1rem !default;
+$nav-link-disabled-color:           $gray-600 !default;
+
+$nav-tabs-border-color:             $gray-300 !default;
+$nav-tabs-border-width:             $border-width !default;
+$nav-tabs-border-radius:            $border-radius !default;
+$nav-tabs-link-hover-border-color:  $gray-200 $gray-200 $nav-tabs-border-color !default;
+$nav-tabs-link-active-color:        $gray-700 !default;
+$nav-tabs-link-active-bg:           $body-bg !default;
+$nav-tabs-link-active-border-color: $gray-300 $gray-300 $nav-tabs-link-active-bg !default;
+
+$nav-pills-border-radius:           $border-radius !default;
+$nav-pills-link-active-color:       $component-active-color !default;
+$nav-pills-link-active-bg:          $component-active-bg !default;
+
+// Navbar
+
+$navbar-padding-y:                  ($spacer / 2) !default;
+$navbar-padding-x:                  $spacer !default;
+
+$navbar-brand-font-size:            $font-size-lg !default;
+// Compute the navbar-brand padding-y so the navbar-brand will have the same height as navbar-text and nav-link
+$nav-link-height:                   ($font-size-base * $line-height-base + $nav-link-padding-y * 2) !default;
+$navbar-brand-height:               $navbar-brand-font-size * $line-height-base !default;
+$navbar-brand-padding-y:            ($nav-link-height - $navbar-brand-height) / 2 !default;
+
+$navbar-toggler-padding-y:          .25rem !default;
+$navbar-toggler-padding-x:          .75rem !default;
+$navbar-toggler-font-size:          $font-size-lg !default;
+$navbar-toggler-border-radius:      $btn-border-radius !default;
+
+$navbar-dark-color:                 rgba($white, .5) !default;
+$navbar-dark-hover-color:           rgba($white, .75) !default;
+$navbar-dark-active-color:          $white !default;
+$navbar-dark-disabled-color:        rgba($white, .25) !default;
+$navbar-dark-toggler-icon-bg:       str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='#{$navbar-dark-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E"), "#", "%23") !default;
+$navbar-dark-toggler-border-color:  rgba($white, .1) !default;
+
+$navbar-light-color:                rgba($black, .5) !default;
+$navbar-light-hover-color:          rgba($black, .7) !default;
+$navbar-light-active-color:         rgba($black, .9) !default;
+$navbar-light-disabled-color:       rgba($black, .3) !default;
+$navbar-light-toggler-icon-bg:      str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='#{$navbar-light-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E"), "#", "%23") !default;
+$navbar-light-toggler-border-color: rgba($black, .1) !default;
+
+// Pagination
+
+$pagination-padding-y:              .5rem !default;
+$pagination-padding-x:              .75rem !default;
+$pagination-padding-y-sm:           .25rem !default;
+$pagination-padding-x-sm:           .5rem !default;
+$pagination-padding-y-lg:           .75rem !default;
+$pagination-padding-x-lg:           1.5rem !default;
+$pagination-line-height:            1.25 !default;
+
+$pagination-color:                  $link-color !default;
+$pagination-bg:                     $white !default;
+$pagination-border-width:           $border-width !default;
+$pagination-border-color:           $gray-300 !default;
+
+$pagination-hover-color:            $link-hover-color !default;
+$pagination-hover-bg:               $gray-200 !default;
+$pagination-hover-border-color:     $gray-300 !default;
+
+$pagination-active-color:           $white !default;
+$pagination-active-bg:              theme-color("primary") !default;
+$pagination-active-border-color:    theme-color("primary") !default;
+
+$pagination-disabled-color:         $gray-600 !default;
+$pagination-disabled-bg:            $white !default;
+$pagination-disabled-border-color:  $gray-300 !default;
+
+
+// Jumbotron
+
+$jumbotron-padding:                 2rem !default;
+$jumbotron-bg:                      $gray-200 !default;
+
+
+// Cards
+
+$card-spacer-y:                     .75rem !default;
+$card-spacer-x:                     1.25rem !default;
+$card-border-width:                 $border-width !default;
+$card-border-radius:                $border-radius !default;
+$card-border-color:                 rgba($black, .125) !default;
+$card-inner-border-radius:          calc(#{$card-border-radius} - #{$card-border-width}) !default;
+$card-cap-bg:                       rgba($black, .03) !default;
+$card-bg:                           $white !default;
+
+$card-img-overlay-padding:          1.25rem !default;
+
+$card-group-margin:                 ($grid-gutter-width / 2) !default;
+$card-deck-margin:                  $card-group-margin !default;
+
+$card-columns-count:                3 !default;
+$card-columns-gap:                  1.25rem !default;
+$card-columns-margin:               $card-spacer-y !default;
+
+
+// Tooltips
+
+$tooltip-max-width:           200px !default;
+$tooltip-color:               $white !default;
+$tooltip-bg:                  $black !default;
+$tooltip-opacity:             .9 !default;
+$tooltip-padding-y:           .25rem !default;
+$tooltip-padding-x:           .5rem !default;
+$tooltip-margin:              0 !default;
+
+$tooltip-arrow-width:         .8rem !default;
+$tooltip-arrow-height:        .4rem !default;
+$tooltip-arrow-color:         $tooltip-bg !default;
+
+
+// Popovers
+
+$popover-bg:                        $white !default;
+$popover-max-width:                 276px !default;
+$popover-border-width:              $border-width !default;
+$popover-border-color:              rgba($black, .2) !default;
+$popover-box-shadow:                0 .25rem .5rem rgba($black, .2) !default;
+
+$popover-header-bg:                 darken($popover-bg, 3%) !default;
+$popover-header-color:              $headings-color !default;
+$popover-header-padding-y:          .5rem !default;
+$popover-header-padding-x:          .75rem !default;
+
+$popover-body-color:                $body-color !default;
+$popover-body-padding-y:            $popover-header-padding-y !default;
+$popover-body-padding-x:            $popover-header-padding-x !default;
+
+$popover-arrow-width:               1rem !default;
+$popover-arrow-height:              .5rem !default;
+$popover-arrow-color:               $popover-bg !default;
+
+$popover-arrow-outer-color:         fade-in($popover-border-color, .05) !default;
+
+
+// Badges
+
+$badge-font-size:                   75% !default;
+$badge-font-weight:                 $font-weight-bold !default;
+$badge-padding-y:                   .25em !default;
+$badge-padding-x:                   .4em !default;
+$badge-border-radius:               $border-radius !default;
+
+$badge-pill-padding-x:              .6em !default;
+// Use a higher than normal value to ensure completely rounded edges when
+// customizing padding or font-size on labels.
+$badge-pill-border-radius:          10rem !default;
+
+
+// Modals
+
+// Padding applied to the modal body
+$modal-inner-padding:         1rem !default;
+
+$modal-dialog-margin:         .5rem !default;
+$modal-dialog-margin-y-sm-up: 1.75rem !default;
+
+$modal-title-line-height:           $line-height-base !default;
+
+$modal-content-bg:               $white !default;
+$modal-content-border-color:     rgba($black, .2) !default;
+$modal-content-border-width:     $border-width !default;
+$modal-content-box-shadow-xs:    0 .25rem .5rem rgba($black, .5) !default;
+$modal-content-box-shadow-sm-up: 0 .5rem 1rem rgba($black, .5) !default;
+
+$modal-backdrop-bg:           $black !default;
+$modal-backdrop-opacity:      .5 !default;
+$modal-header-border-color:   $gray-200 !default;
+$modal-footer-border-color:   $modal-header-border-color !default;
+$modal-header-border-width:   $modal-content-border-width !default;
+$modal-footer-border-width:   $modal-header-border-width !default;
+$modal-header-padding:        1rem !default;
+
+$modal-lg:                          800px !default;
+$modal-md:                          500px !default;
+$modal-sm:                          300px !default;
+
+$modal-transition:                  transform .3s ease-out !default;
+
+
+// Alerts
+//
+// Define alert colors, border radius, and padding.
+
+$alert-padding-y:                   .75rem !default;
+$alert-padding-x:                   1.25rem !default;
+$alert-margin-bottom:               1rem !default;
+$alert-border-radius:               $border-radius !default;
+$alert-link-font-weight:            $font-weight-bold !default;
+$alert-border-width:                $border-width !default;
+
+
+// Progress bars
+
+$progress-height:                   1rem !default;
+$progress-font-size:                ($font-size-base * .75) !default;
+$progress-bg:                       $gray-200 !default;
+$progress-border-radius:            $border-radius !default;
+$progress-box-shadow:               inset 0 .1rem .1rem rgba($black, .1) !default;
+$progress-bar-color:                $white !default;
+$progress-bar-bg:                   theme-color("primary") !default;
+$progress-bar-animation-timing:     1s linear infinite !default;
+$progress-bar-transition:           width .6s ease !default;
+
+// List group
+
+$list-group-bg:                     $white !default;
+$list-group-border-color:           rgba($black, .125) !default;
+$list-group-border-width:           $border-width !default;
+$list-group-border-radius:          $border-radius !default;
+
+$list-group-item-padding-y:         .75rem !default;
+$list-group-item-padding-x:         1.25rem !default;
+
+$list-group-hover-bg:               $gray-100 !default;
+$list-group-active-color:           $component-active-color !default;
+$list-group-active-bg:              $component-active-bg !default;
+$list-group-active-border-color:    $list-group-active-bg !default;
+
+$list-group-disabled-color:         $gray-600 !default;
+$list-group-disabled-bg:            $list-group-bg !default;
+
+$list-group-action-color:           $gray-700 !default;
+$list-group-action-hover-color:     $list-group-action-color !default;
+
+$list-group-action-active-color:    $body-color !default;
+$list-group-action-active-bg:       $gray-200 !default;
+
+
+// Image thumbnails
+
+$thumbnail-padding:                 .25rem !default;
+$thumbnail-bg:                      $body-bg !default;
+$thumbnail-border-width:            $border-width !default;
+$thumbnail-border-color:            $gray-300 !default;
+$thumbnail-border-radius:           $border-radius !default;
+$thumbnail-box-shadow:              0 1px 2px rgba($black, .075) !default;
+
+
+// Figures
+
+$figure-caption-font-size:          90% !default;
+$figure-caption-color:              $gray-600 !default;
+
+
+// Breadcrumbs
+
+$breadcrumb-padding-y:              .75rem !default;
+$breadcrumb-padding-x:              1rem !default;
+$breadcrumb-item-padding:           .5rem !default;
+
+$breadcrumb-margin-bottom:          1rem !default;
+
+$breadcrumb-bg:                     $gray-200 !default;
+$breadcrumb-divider-color:          $gray-600 !default;
+$breadcrumb-active-color:           $gray-600 !default;
+$breadcrumb-divider:                "/" !default;
+
+
+// Carousel
+
+$carousel-control-color:            $white !default;
+$carousel-control-width:            15% !default;
+$carousel-control-opacity:          .5 !default;
+
+$carousel-indicator-width:          30px !default;
+$carousel-indicator-height:         3px !default;
+$carousel-indicator-spacer:         3px !default;
+$carousel-indicator-active-bg:      $white !default;
+
+$carousel-caption-width:            70% !default;
+$carousel-caption-color:            $white !default;
+
+$carousel-control-icon-width:       20px !default;
+
+$carousel-control-prev-icon-bg:     str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'%3E%3Cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3E%3C/svg%3E"), "#", "%23") !default;
+$carousel-control-next-icon-bg:     str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'%3E%3Cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3E%3C/svg%3E"), "#", "%23") !default;
+
+$carousel-transition:               transform .6s ease !default;
+
+
+// Close
+
+$close-font-size:                   $font-size-base * 1.5 !default;
+$close-font-weight:                 $font-weight-bold !default;
+$close-color:                       $black !default;
+$close-text-shadow:                 0 1px 0 $white !default;
+
+// Code
+
+$code-font-size:                    87.5% !default;
+$code-color:                        $pink !default;
+
+$kbd-padding-y:                     .2rem !default;
+$kbd-padding-x:                     .4rem !default;
+$kbd-font-size:                     $code-font-size !default;
+$kbd-color:                         $white !default;
+$kbd-bg:                            $gray-900 !default;
+
+$pre-color:                         $gray-900 !default;
+$pre-scrollable-max-height:         340px !default;
diff --git a/portal-FE-common/src/styles/bootstrap/bootstrap-grid.scss b/portal-FE-common/src/styles/bootstrap/bootstrap-grid.scss
new file mode 100644 (file)
index 0000000..fec2766
--- /dev/null
@@ -0,0 +1,35 @@
+/*!
+ * Bootstrap Grid v4.0.0-beta.3 (https://getbootstrap.com)
+ * Copyright 2011-2017 The Bootstrap Authors
+ * Copyright 2011-2017 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+
+@at-root {
+  @-ms-viewport { width: device-width; } // stylelint-disable-line at-rule-no-vendor-prefix
+}
+
+html {
+  box-sizing: border-box;
+  -ms-overflow-style: scrollbar;
+}
+
+*,
+*::before,
+*::after {
+  box-sizing: inherit;
+}
+
+@import "functions";
+@import "variables";
+
+//
+// Grid mixins
+//
+
+@import "mixins/breakpoints";
+@import "mixins/grid-framework";
+@import "mixins/grid";
+
+@import "grid";
+@import "utilities/flex";
diff --git a/portal-FE-common/src/styles/bootstrap/bootstrap-reboot.scss b/portal-FE-common/src/styles/bootstrap/bootstrap-reboot.scss
new file mode 100644 (file)
index 0000000..60c0df2
--- /dev/null
@@ -0,0 +1,12 @@
+/*!
+ * Bootstrap Reboot v4.0.0-beta.3 (https://getbootstrap.com)
+ * Copyright 2011-2017 The Bootstrap Authors
+ * Copyright 2011-2017 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
+ */
+
+@import "functions";
+@import "variables";
+@import "mixins";
+@import "reboot";
diff --git a/portal-FE-common/src/styles/bootstrap/bootstrap.scss b/portal-FE-common/src/styles/bootstrap/bootstrap.scss
new file mode 100644 (file)
index 0000000..42b2c1a
--- /dev/null
@@ -0,0 +1,42 @@
+/*!
+ * Bootstrap v4.0.0-beta.3 (https://getbootstrap.com)
+ * Copyright 2011-2017 The Bootstrap Authors
+ * Copyright 2011-2017 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+
+@import "functions";
+@import "variables";
+@import "mixins";
+@import "root";
+@import "reboot";
+@import "type";
+@import "images";
+@import "code";
+@import "grid";
+@import "tables";
+@import "forms";
+@import "buttons";
+@import "transitions";
+@import "dropdown";
+@import "button-group";
+@import "input-group";
+@import "custom-forms";
+@import "nav";
+@import "navbar";
+@import "card";
+@import "breadcrumb";
+@import "pagination";
+@import "badge";
+@import "jumbotron";
+@import "alert";
+@import "progress";
+@import "media";
+@import "list-group";
+@import "close";
+@import "modal";
+@import "tooltip";
+@import "popover";
+@import "carousel";
+@import "utilities";
+@import "print";
diff --git a/portal-FE-common/src/styles/bootstrap/mixins/_alert.scss b/portal-FE-common/src/styles/bootstrap/mixins/_alert.scss
new file mode 100644 (file)
index 0000000..db5a7eb
--- /dev/null
@@ -0,0 +1,13 @@
+@mixin alert-variant($background, $border, $color) {
+  color: $color;
+  @include gradient-bg($background);
+  border-color: $border;
+
+  hr {
+    border-top-color: darken($border, 5%);
+  }
+
+  .alert-link {
+    color: darken($color, 10%);
+  }
+}
diff --git a/portal-FE-common/src/styles/bootstrap/mixins/_background-variant.scss b/portal-FE-common/src/styles/bootstrap/mixins/_background-variant.scss
new file mode 100644 (file)
index 0000000..494439d
--- /dev/null
@@ -0,0 +1,21 @@
+// stylelint-disable declaration-no-important
+
+// Contextual backgrounds
+
+@mixin bg-variant($parent, $color) {
+  #{$parent} {
+    background-color: $color !important;
+  }
+  a#{$parent},
+  button#{$parent} {
+    @include hover-focus {
+      background-color: darken($color, 10%) !important;
+    }
+  }
+}
+
+@mixin bg-gradient-variant($parent, $color) {
+  #{$parent} {
+    background: $color linear-gradient(180deg, mix($body-bg, $color, 15%), $color) repeat-x !important;
+  }
+}
diff --git a/portal-FE-common/src/styles/bootstrap/mixins/_badge.scss b/portal-FE-common/src/styles/bootstrap/mixins/_badge.scss
new file mode 100644 (file)
index 0000000..eeca0b4
--- /dev/null
@@ -0,0 +1,12 @@
+@mixin badge-variant($bg) {
+  color: color-yiq($bg);
+  background-color: $bg;
+
+  &[href] {
+    @include hover-focus {
+      color: color-yiq($bg);
+      text-decoration: none;
+      background-color: darken($bg, 10%);
+    }
+  }
+}
diff --git a/portal-FE-common/src/styles/bootstrap/mixins/_border-radius.scss b/portal-FE-common/src/styles/bootstrap/mixins/_border-radius.scss
new file mode 100644 (file)
index 0000000..2024feb
--- /dev/null
@@ -0,0 +1,35 @@
+// Single side border-radius
+
+@mixin border-radius($radius: $border-radius) {
+  @if $enable-rounded {
+    border-radius: $radius;
+  }
+}
+
+@mixin border-top-radius($radius) {
+  @if $enable-rounded {
+    border-top-left-radius: $radius;
+    border-top-right-radius: $radius;
+  }
+}
+
+@mixin border-right-radius($radius) {
+  @if $enable-rounded {
+    border-top-right-radius: $radius;
+    border-bottom-right-radius: $radius;
+  }
+}
+
+@mixin border-bottom-radius($radius) {
+  @if $enable-rounded {
+    border-bottom-right-radius: $radius;
+    border-bottom-left-radius: $radius;
+  }
+}
+
+@mixin border-left-radius($radius) {
+  @if $enable-rounded {
+    border-top-left-radius: $radius;
+    border-bottom-left-radius: $radius;
+  }
+}
diff --git a/portal-FE-common/src/styles/bootstrap/mixins/_box-shadow.scss b/portal-FE-common/src/styles/bootstrap/mixins/_box-shadow.scss
new file mode 100644 (file)
index 0000000..b2410e5
--- /dev/null
@@ -0,0 +1,5 @@
+@mixin box-shadow($shadow...) {
+  @if $enable-shadows {
+    box-shadow: $shadow;
+  }
+}
diff --git a/portal-FE-common/src/styles/bootstrap/mixins/_breakpoints.scss b/portal-FE-common/src/styles/bootstrap/mixins/_breakpoints.scss
new file mode 100644 (file)
index 0000000..7c95c68
--- /dev/null
@@ -0,0 +1,121 @@
+// Breakpoint viewport sizes and media queries.
+//
+// Breakpoints are defined as a map of (name: minimum width), order from small to large:
+//
+//    (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px)
+//
+// The map defined in the `$grid-breakpoints` global variable is used as the `$breakpoints` argument by default.
+
+// Name of the next breakpoint, or null for the last breakpoint.
+//
+//    >> breakpoint-next(sm)
+//    md
+//    >> breakpoint-next(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))
+//    md
+//    >> breakpoint-next(sm, $breakpoint-names: (xs sm md lg xl))
+//    md
+@function breakpoint-next($name, $breakpoints: $grid-breakpoints, $breakpoint-names: map-keys($breakpoints)) {
+  $n: index($breakpoint-names, $name);
+  @return if($n < length($breakpoint-names), nth($breakpoint-names, $n + 1), null);
+}
+
+// Minimum breakpoint width. Null for the smallest (first) breakpoint.
+//
+//    >> breakpoint-min(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))
+//    576px
+@function breakpoint-min($name, $breakpoints: $grid-breakpoints) {
+  $min: map-get($breakpoints, $name);
+  @return if($min != 0, $min, null);
+}
+
+// Maximum breakpoint width. Null for the largest (last) breakpoint.
+// The maximum value is calculated as the minimum of the next one less 0.01px
+// to work around the limitations of `min-` and `max-` prefixes and viewports with fractional widths.
+// See https://www.w3.org/TR/mediaqueries-4/#mq-min-max
+//
+//    >> breakpoint-max(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))
+//    767px
+@function breakpoint-max($name, $breakpoints: $grid-breakpoints) {
+  $next: breakpoint-next($name, $breakpoints);
+  @return if($next, breakpoint-min($next, $breakpoints) - .01px, null);
+}
+
+// Returns a blank string if smallest breakpoint, otherwise returns the name with a dash infront.
+// Useful for making responsive utilities.
+//
+//    >> breakpoint-infix(xs, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))
+//    ""  (Returns a blank string)
+//    >> breakpoint-infix(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))
+//    "-sm"
+@function breakpoint-infix($name, $breakpoints: $grid-breakpoints) {
+  @return if(breakpoint-min($name, $breakpoints) == null, "", "-#{$name}");
+}
+
+// Media of at least the minimum breakpoint width. No query for the smallest breakpoint.
+// Makes the @content apply to the given breakpoint and wider.
+@mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints) {
+  $min: breakpoint-min($name, $breakpoints);
+  @if $min {
+    @media (min-width: $min) {
+      @content;
+    }
+  } @else {
+    @content;
+  }
+}
+
+// Media of at most the maximum breakpoint width. No query for the largest breakpoint.
+// Makes the @content apply to the given breakpoint and narrower.
+@mixin media-breakpoint-down($name, $breakpoints: $grid-breakpoints) {
+  $max: breakpoint-max($name, $breakpoints);
+  @if $max {
+    @media (max-width: $max) {
+      @content;
+    }
+  } @else {
+    @content;
+  }
+}
+
+// Media that spans multiple breakpoint widths.
+// Makes the @content apply between the min and max breakpoints
+@mixin media-breakpoint-between($lower, $upper, $breakpoints: $grid-breakpoints) {
+  $min: breakpoint-min($lower, $breakpoints);
+  $max: breakpoint-max($upper, $breakpoints);
+
+  @if $min != null and $max != null {
+    @media (min-width: $min) and (max-width: $max) {
+      @content;
+    }
+  } @else if $max == null {
+    @include media-breakpoint-up($lower) {
+      @content;
+    }
+  } @else if $min == null {
+    @include media-breakpoint-down($upper) {
+      @content;
+    }
+  }
+}
+
+// Media between the breakpoint's minimum and maximum widths.
+// No minimum for the smallest breakpoint, and no maximum for the largest one.
+// Makes the @content apply only to the given breakpoint, not viewports any wider or narrower.
+@mixin media-breakpoint-only($name, $breakpoints: $grid-breakpoints) {
+  $min: breakpoint-min($name, $breakpoints);
+  $max: breakpoint-max($name, $breakpoints);
+
+  @if $min != null and $max != null {
+    @media (min-width: $min) and (max-width: $max) {
+      @content;
+    }
+  } @else if $max == null {
+    @include media-breakpoint-up($name) {
+      @content;
+    }
+  } @else if $min == null {
+    @include media-breakpoint-down($name) {
+      @content;
+    }
+  }
+}
diff --git a/portal-FE-common/src/styles/bootstrap/mixins/_buttons.scss b/portal-FE-common/src/styles/bootstrap/mixins/_buttons.scss
new file mode 100644 (file)
index 0000000..252e26a
--- /dev/null
@@ -0,0 +1,101 @@
+// Button variants
+//
+// Easily pump out default styles, as well as :hover, :focus, :active,
+// and disabled options for all buttons
+
+@mixin button-variant($background, $border, $hover-background: darken($background, 7.5%), $hover-border: darken($border, 10%), $active-background: darken($background, 10%), $active-border: darken($border, 12.5%)) {
+  color: color-yiq($background);
+  @include gradient-bg($background);
+  border-color: $border;
+  @include box-shadow($btn-box-shadow);
+
+  @include hover {
+    color: color-yiq($hover-background);
+    @include gradient-bg($hover-background);
+    border-color: $hover-border;
+  }
+
+  &:focus,
+  &.focus {
+    // Avoid using mixin so we can pass custom focus shadow properly
+    @if $enable-shadows {
+      box-shadow: $btn-box-shadow, 0 0 0 $btn-focus-width rgba($border, .5);
+    } @else {
+      box-shadow: 0 0 0 $btn-focus-width rgba($border, .5);
+    }
+  }
+
+  // Disabled comes first so active can properly restyle
+  &.disabled,
+  &:disabled {
+    background-color: $background;
+    border-color: $border;
+  }
+
+  &:not([disabled]):not(.disabled):active,
+  &:not([disabled]):not(.disabled).active,
+  .show > &.dropdown-toggle {
+    color: color-yiq($active-background);
+    background-color: $active-background;
+    @if $enable-gradients {
+      background-image: none; // Remove the gradient for the pressed/active state
+    }
+    border-color: $active-border;
+
+    &:focus {
+      // Avoid using mixin so we can pass custom focus shadow properly
+      @if $enable-shadows {
+        box-shadow: $btn-active-box-shadow, 0 0 0 $btn-focus-width rgba($border, .5);
+      } @else {
+        box-shadow: 0 0 0 $btn-focus-width rgba($border, .5);
+      }
+    }
+  }
+}
+
+@mixin button-outline-variant($color, $color-hover: #fff, $active-background: $color, $active-border: $color) {
+  color: $color;
+  background-color: transparent;
+  background-image: none;
+  border-color: $color;
+
+  &:hover {
+    color: color-yiq($color);
+    background-color: $active-background;
+    border-color: $active-border;
+  }
+
+  &:focus,
+  &.focus {
+    box-shadow: 0 0 0 $btn-focus-width rgba($color, .5);
+  }
+
+  &.disabled,
+  &:disabled {
+    color: $color;
+    background-color: transparent;
+  }
+
+  &:not([disabled]):not(.disabled):active,
+  &:not([disabled]):not(.disabled).active,
+  .show > &.dropdown-toggle {
+    color: color-yiq($color-hover);
+    background-color: $active-background;
+    border-color: $active-border;
+    // Avoid using mixin so we can pass custom focus shadow properly
+    box-shadow: 0 0 0 $btn-focus-width rgba($color, .5);
+  }
+}
+
+// Button sizes
+@mixin button-size($padding-y, $padding-x, $font-size, $line-height, $border-radius) {
+  padding: $padding-y $padding-x;
+  font-size: $font-size;
+  line-height: $line-height;
+  // Manually declare to provide an override to the browser default
+  @if $enable-rounded {
+    border-radius: $border-radius;
+  } @else {
+    border-radius: 0;
+  }
+}
diff --git a/portal-FE-common/src/styles/bootstrap/mixins/_caret.scss b/portal-FE-common/src/styles/bootstrap/mixins/_caret.scss
new file mode 100644 (file)
index 0000000..40478e4
--- /dev/null
@@ -0,0 +1,65 @@
+@mixin caret-down {
+  border-top: $caret-width solid;
+  border-right: $caret-width solid transparent;
+  border-bottom: 0;
+  border-left: $caret-width solid transparent;
+}
+
+@mixin caret-up {
+  border-top: 0;
+  border-right: $caret-width solid transparent;
+  border-bottom: $caret-width solid;
+  border-left: $caret-width solid transparent;
+}
+
+@mixin caret-right {
+  border-top: $caret-width solid transparent;
+  border-bottom: $caret-width solid transparent;
+  border-left: $caret-width solid;
+}
+
+@mixin caret-left {
+  border-top: $caret-width solid transparent;
+  border-right: $caret-width solid;
+  border-bottom: $caret-width solid transparent;
+}
+
+@mixin caret($direction: down) {
+  @if $enable-caret {
+    &::after {
+      display: inline-block;
+      width: 0;
+      height: 0;
+      margin-left: $caret-width * .85;
+      vertical-align: $caret-width * .85;
+      content: "";
+      @if $direction == down {
+        @include caret-down;
+      } @else if $direction == up {
+        @include caret-up;
+      } @else if $direction == right {
+        @include caret-right;
+      }
+    }
+
+    @if $direction == left {
+      &::after {
+        display: none;
+      }
+
+      &::before {
+        display: inline-block;
+        width: 0;
+        height: 0;
+        margin-right: $caret-width * .85;
+        vertical-align: $caret-width * .85;
+        content: "";
+        @include caret-left;
+      }
+    }
+
+    &:empty::after {
+      margin-left: 0;
+    }
+  }
+}
diff --git a/portal-FE-common/src/styles/bootstrap/mixins/_clearfix.scss b/portal-FE-common/src/styles/bootstrap/mixins/_clearfix.scss
new file mode 100644 (file)
index 0000000..11a977b
--- /dev/null
@@ -0,0 +1,7 @@
+@mixin clearfix() {
+  &::after {
+    display: block;
+    clear: both;
+    content: "";
+  }
+}
diff --git a/portal-FE-common/src/styles/bootstrap/mixins/_float.scss b/portal-FE-common/src/styles/bootstrap/mixins/_float.scss
new file mode 100644 (file)
index 0000000..48fa8b6
--- /dev/null
@@ -0,0 +1,11 @@
+// stylelint-disable declaration-no-important
+
+@mixin float-left {
+  float: left !important;
+}
+@mixin float-right {
+  float: right !important;
+}
+@mixin float-none {
+  float: none !important;
+}
diff --git a/portal-FE-common/src/styles/bootstrap/mixins/_forms.scss b/portal-FE-common/src/styles/bootstrap/mixins/_forms.scss
new file mode 100644 (file)
index 0000000..d25df18
--- /dev/null
@@ -0,0 +1,133 @@
+// Form control focus state
+//
+// Generate a customized focus state and for any input with the specified color,
+// which defaults to the `$input-focus-border-color` variable.
+//
+// We highly encourage you to not customize the default value, but instead use
+// this to tweak colors on an as-needed basis. This aesthetic change is based on
+// WebKit's default styles, but applicable to a wider range of browsers. Its
+// usability and accessibility should be taken into account with any change.
+//
+// Example usage: change the default blue border and shadow to white for better
+// contrast against a dark gray background.
+@mixin form-control-focus() {
+  &:focus {
+    color: $input-focus-color;
+    background-color: $input-focus-bg;
+    border-color: $input-focus-border-color;
+    outline: 0;
+    // Avoid using mixin so we can pass custom focus shadow properly
+    @if $enable-shadows {
+      box-shadow: $input-box-shadow, $input-focus-box-shadow;
+    } @else {
+      box-shadow: $input-focus-box-shadow;
+    }
+  }
+}
+
+
+@mixin form-validation-state($state, $color) {
+
+  .#{$state}-feedback {
+    display: none;
+    width: 100%;
+    margin-top: $form-feedback-margin-top;
+    font-size: $form-feedback-font-size;
+    color: $color;
+  }
+
+  .#{$state}-tooltip {
+    position: absolute;
+    top: 100%;
+    z-index: 5;
+    display: none;
+    width: 250px;
+    padding: .5rem;
+    margin-top: .1rem;
+    font-size: .875rem;
+    line-height: 1;
+    color: #fff;
+    background-color: rgba($color, .8);
+    border-radius: .2rem;
+  }
+
+  .form-control,
+  .custom-select {
+    .was-validated &:#{$state},
+    &.is-#{$state} {
+      border-color: $color;
+
+      &:focus {
+        border-color: $color;
+        box-shadow: 0 0 0 $input-focus-width rgba($color, .25);
+      }
+
+      ~ .#{$state}-feedback,
+      ~ .#{$state}-tooltip {
+        display: block;
+      }
+    }
+  }
+
+  .form-check-input {
+    .was-validated &:#{$state},
+    &.is-#{$state} {
+      ~ .form-check-label {
+        color: $color;
+      }
+    }
+  }
+
+  .custom-control-input {
+    .was-validated &:#{$state},
+    &.is-#{$state} {
+      ~ .custom-control-label {
+        color: $color;
+
+        &::before {
+          background-color: lighten($color, 25%);
+        }
+      }
+
+      ~ .#{$state}-feedback,
+      ~ .#{$state}-tooltip {
+        display: block;
+      }
+
+      &:checked {
+        ~ .custom-control-label::before {
+          @include gradient-bg(lighten($color, 10%));
+        }
+      }
+
+      &:focus {
+        ~ .custom-control-label::before {
+          box-shadow: 0 0 0 1px $body-bg, 0 0 0 $input-focus-width rgba($color, .25);
+        }
+      }
+    }
+  }
+
+  // custom file
+  .custom-file-input {
+    .was-validated &:#{$state},
+    &.is-#{$state} {
+      ~ .custom-file-label {
+        border-color: $color;
+
+        &::before { border-color: inherit; }
+      }
+
+      ~ .#{$state}-feedback,
+      ~ .#{$state}-tooltip {
+        display: block;
+      }
+
+      &:focus {
+        ~ .custom-file-label {
+          box-shadow: 0 0 0 $input-focus-width rgba($color, .25);
+        }
+      }
+    }
+  }
+}
diff --git a/portal-FE-common/src/styles/bootstrap/mixins/_gradients.scss b/portal-FE-common/src/styles/bootstrap/mixins/_gradients.scss
new file mode 100644 (file)
index 0000000..ecd01f7
--- /dev/null
@@ -0,0 +1,45 @@
+// Gradients
+
+@mixin gradient-bg($color) {
+  @if $enable-gradients {
+    background: $color linear-gradient(180deg, mix($body-bg, $color, 15%), $color) repeat-x;
+  } @else {
+    background-color: $color;
+  }
+}
+
+// Horizontal gradient, from left to right
+//
+// Creates two color stops, start and end, by specifying a color and position for each color stop.
+@mixin gradient-x($start-color: #555, $end-color: #333, $start-percent: 0%, $end-percent: 100%) {
+  background-image: linear-gradient(to right, $start-color $start-percent, $end-color $end-percent);
+  background-repeat: repeat-x;
+}
+
+// Vertical gradient, from top to bottom
+//
+// Creates two color stops, start and end, by specifying a color and position for each color stop.
+@mixin gradient-y($start-color: #555, $end-color: #333, $start-percent: 0%, $end-percent: 100%) {
+  background-image: linear-gradient(to bottom, $start-color $start-percent, $end-color $end-percent);
+  background-repeat: repeat-x;
+}
+
+@mixin gradient-directional($start-color: #555, $end-color: #333, $deg: 45deg) {
+  background-image: linear-gradient($deg, $start-color, $end-color);
+  background-repeat: repeat-x;
+}
+@mixin gradient-x-three-colors($start-color: #00b3ee, $mid-color: #7a43b6, $color-stop: 50%, $end-color: #c3325f) {
+  background-image: linear-gradient(to right, $start-color, $mid-color $color-stop, $end-color);
+  background-repeat: no-repeat;
+}
+@mixin gradient-y-three-colors($start-color: #00b3ee, $mid-color: #7a43b6, $color-stop: 50%, $end-color: #c3325f) {
+  background-image: linear-gradient($start-color, $mid-color $color-stop, $end-color);
+  background-repeat: no-repeat;
+}
+@mixin gradient-radial($inner-color: #555, $outer-color: #333) {
+  background-image: radial-gradient(circle, $inner-color, $outer-color);
+  background-repeat: no-repeat;
+}
+@mixin gradient-striped($color: rgba(255,255,255,.15), $angle: 45deg) {
+  background-image: linear-gradient($angle, $color 25%, transparent 25%, transparent 50%, $color 50%, $color 75%, transparent 75%, transparent);
+}
diff --git a/portal-FE-common/src/styles/bootstrap/mixins/_grid-framework.scss b/portal-FE-common/src/styles/bootstrap/mixins/_grid-framework.scss
new file mode 100644 (file)
index 0000000..41bdf46
--- /dev/null
@@ -0,0 +1,69 @@
+// Framework grid generation
+//
+// Used only by Bootstrap to generate the correct number of grid classes given
+// any value of `$grid-columns`.
+
+@mixin make-grid-columns($columns: $grid-columns, $gutter: $grid-gutter-width, $breakpoints: $grid-breakpoints) {
+  // Common properties for all breakpoints
+  %grid-column {
+    position: relative;
+    width: 100%;
+    min-height: 1px; // Prevent columns from collapsing when empty
+    padding-right: ($gutter / 2);
+    padding-left: ($gutter / 2);
+  }
+
+  @each $breakpoint in map-keys($breakpoints) {
+    $infix: breakpoint-infix($breakpoint, $breakpoints);
+
+    // Allow columns to stretch full width below their breakpoints
+    @for $i from 1 through $columns {
+      .col#{$infix}-#{$i} {
+        @extend %grid-column;
+      }
+    }
+    .col#{$infix},
+    .col#{$infix}-auto {
+      @extend %grid-column;
+    }
+
+    @include media-breakpoint-up($breakpoint, $breakpoints) {
+      // Provide basic `.col-{bp}` classes for equal-width flexbox columns
+      .col#{$infix} {
+        flex-basis: 0;
+        flex-grow: 1;
+        max-width: 100%;
+      }
+      .col#{$infix}-auto {
+        flex: 0 0 auto;
+        width: auto;
+        max-width: none; // Reset earlier grid tiers
+      }
+
+      @for $i from 1 through $columns {
+        .col#{$infix}-#{$i} {
+          @include make-col($i, $columns);
+        }
+      }
+
+      .order#{$infix}-first {
+        order: -1;
+      }
+
+      @for $i from 1 through $columns {
+        .order#{$infix}-#{$i} {
+          order: $i;
+        }
+      }
+
+      // `$columns - 1` because offsetting by the width of an entire row isn't possible
+      @for $i from 0 through ($columns - 1) {
+        @if not ($infix == "" and $i == 0) { // Avoid emitting useless .offset-0
+          .offset#{$infix}-#{$i} {
+            @include make-col-offset($i, $columns);
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/portal-FE-common/src/styles/bootstrap/mixins/_grid.scss b/portal-FE-common/src/styles/bootstrap/mixins/_grid.scss
new file mode 100644 (file)
index 0000000..b75ebcb
--- /dev/null
@@ -0,0 +1,52 @@
+/// Grid system
+//
+// Generate semantic grid columns with these mixins.
+
+@mixin make-container() {
+  width: 100%;
+  padding-right: ($grid-gutter-width / 2);
+  padding-left: ($grid-gutter-width / 2);
+  margin-right: auto;
+  margin-left: auto;
+}
+
+
+// For each breakpoint, define the maximum width of the container in a media query
+@mixin make-container-max-widths($max-widths: $container-max-widths, $breakpoints: $grid-breakpoints) {
+  @each $breakpoint, $container-max-width in $max-widths {
+    @include media-breakpoint-up($breakpoint, $breakpoints) {
+      max-width: $container-max-width;
+    }
+  }
+}
+
+@mixin make-row() {
+  display: flex;
+  flex-wrap: wrap;
+  margin-right: ($grid-gutter-width / -2);
+  margin-left: ($grid-gutter-width / -2);
+}
+
+@mixin make-col-ready() {
+  position: relative;
+  // Prevent columns from becoming too narrow when at smaller grid tiers by
+  // always setting `width: 100%;`. This works because we use `flex` values
+  // later on to override this initial width.
+  width: 100%;
+  min-height: 1px; // Prevent collapsing
+  padding-right: ($grid-gutter-width / 2);
+  padding-left: ($grid-gutter-width / 2);
+}
+
+@mixin make-col($size, $columns: $grid-columns) {
+  flex: 0 0 percentage($size / $columns);
+  // Add a `max-width` to ensure content within each column does not blow out
+  // the width of the column. Applies to IE10+ and Firefox. Chrome and Safari
+  // do not appear to require this.
+  max-width: percentage($size / $columns);
+}
+
+@mixin make-col-offset($size, $columns: $grid-columns) {
+  $num: $size / $columns;
+  margin-left: if($num == 0, 0, percentage($num));
+}
diff --git a/portal-FE-common/src/styles/bootstrap/mixins/_hover.scss b/portal-FE-common/src/styles/bootstrap/mixins/_hover.scss
new file mode 100644 (file)
index 0000000..fd2f1e2
--- /dev/null
@@ -0,0 +1,61 @@
+// stylelint-disable indentation
+@mixin hover {
+  // TODO: re-enable along with mq4-hover-shim
+//  @if $enable-hover-media-query {
+//    // See Media Queries Level 4: https://drafts.csswg.org/mediaqueries/#hover
+//    // Currently shimmed by https://github.com/twbs/mq4-hover-shim
+//    @media (hover: hover) {
+//      &:hover { @content }
+//    }
+//  }
+//  @else {
+    &:hover { @content; }
+//  }
+}
+
+
+@mixin hover-focus {
+  @if $enable-hover-media-query {
+    &:focus {
+      @content;
+    }
+    @include hover { @content; }
+  } @else {
+    &:focus,
+    &:hover {
+      @content;
+    }
+  }
+}
+
+@mixin plain-hover-focus {
+  @if $enable-hover-media-query {
+    &,
+    &:focus {
+      @content;
+    }
+    @include hover { @content; }
+  } @else {
+    &,
+    &:focus,
+    &:hover {
+      @content;
+    }
+  }
+}
+
+@mixin hover-focus-active {
+  @if $enable-hover-media-query {
+    &:focus,
+    &:active {
+      @content;
+    }
+    @include hover { @content; }
+  } @else {
+    &:focus,
+    &:active,
+    &:hover {
+      @content;
+    }
+  }
+}
diff --git a/portal-FE-common/src/styles/bootstrap/mixins/_image.scss b/portal-FE-common/src/styles/bootstrap/mixins/_image.scss
new file mode 100644 (file)
index 0000000..0544f0d
--- /dev/null
@@ -0,0 +1,36 @@
+// Image Mixins
+// - Responsive image
+// - Retina image
+
+
+// Responsive image
+//
+// Keep images from scaling beyond the width of their parents.
+
+@mixin img-fluid {
+  // Part 1: Set a maximum relative to the parent
+  max-width: 100%;
+  // Part 2: Override the height to auto, otherwise images will be stretched
+  // when setting a width and height attribute on the img element.
+  height: auto;
+}
+
+
+// Retina image
+//
+// Short retina mixin for setting background-image and -size.
+
+// stylelint-disable indentation, media-query-list-comma-newline-after
+@mixin img-retina($file-1x, $file-2x, $width-1x, $height-1x) {
+  background-image: url($file-1x);
+
+  // Autoprefixer takes care of adding -webkit-min-device-pixel-ratio and -o-min-device-pixel-ratio,
+  // but doesn't convert dppx=>dpi.
+  // There's no such thing as unprefixed min-device-pixel-ratio since it's nonstandard.
+  // Compatibility info: https://caniuse.com/#feat=css-media-resolution
+  @media only screen and (min-resolution: 192dpi), // IE9-11 don't support dppx
+  only screen and (min-resolution: 2dppx) { // Standardized
+    background-image: url($file-2x);
+    background-size: $width-1x $height-1x;
+  }
+}
diff --git a/portal-FE-common/src/styles/bootstrap/mixins/_list-group.scss b/portal-FE-common/src/styles/bootstrap/mixins/_list-group.scss
new file mode 100644 (file)
index 0000000..278787b
--- /dev/null
@@ -0,0 +1,24 @@
+// List Groups
+
+@mixin list-group-item-variant($state, $background, $color) {
+  .list-group-item-#{$state} {
+    color: $color;
+    background-color: $background;
+  }
+
+  a.list-group-item-#{$state},
+  button.list-group-item-#{$state} {
+    color: $color;
+
+    @include hover-focus {
+      color: $color;
+      background-color: darken($background, 5%);
+    }
+
+    &.active {
+      color: #fff;
+      background-color: $color;
+      border-color: $color;
+    }
+  }
+}
diff --git a/portal-FE-common/src/styles/bootstrap/mixins/_lists.scss b/portal-FE-common/src/styles/bootstrap/mixins/_lists.scss
new file mode 100644 (file)
index 0000000..2518562
--- /dev/null
@@ -0,0 +1,7 @@
+// Lists
+
+// Unstyled keeps list items block level, just removes default browser padding and list-style
+@mixin list-unstyled {
+  padding-left: 0;
+  list-style: none;
+}
diff --git a/portal-FE-common/src/styles/bootstrap/mixins/_nav-divider.scss b/portal-FE-common/src/styles/bootstrap/mixins/_nav-divider.scss
new file mode 100644 (file)
index 0000000..493de03
--- /dev/null
@@ -0,0 +1,10 @@
+// Horizontal dividers
+//
+// Dividers (basically an hr) within dropdowns and nav lists
+
+@mixin nav-divider($color: #e5e5e5) {
+  height: 0;
+  margin: ($spacer / 2) 0;
+  overflow: hidden;
+  border-top: 1px solid $color;
+}
diff --git a/portal-FE-common/src/styles/bootstrap/mixins/_navbar-align.scss b/portal-FE-common/src/styles/bootstrap/mixins/_navbar-align.scss
new file mode 100644 (file)
index 0000000..b351660
--- /dev/null
@@ -0,0 +1,10 @@
+// Navbar vertical align
+//
+// Vertically center elements in the navbar.
+// Example: an element has a height of 30px, so write out `.navbar-vertical-align(30px);`
+// to calculate the appropriate top margin.
+
+// @mixin navbar-vertical-align($element-height) {
+//   margin-top: (($navbar-height - $element-height) / 2);
+//   margin-bottom: (($navbar-height - $element-height) / 2);
+// }
diff --git a/portal-FE-common/src/styles/bootstrap/mixins/_pagination.scss b/portal-FE-common/src/styles/bootstrap/mixins/_pagination.scss
new file mode 100644 (file)
index 0000000..ff36eb6
--- /dev/null
@@ -0,0 +1,22 @@
+// Pagination
+
+@mixin pagination-size($padding-y, $padding-x, $font-size, $line-height, $border-radius) {
+  .page-link {
+    padding: $padding-y $padding-x;
+    font-size: $font-size;
+    line-height: $line-height;
+  }
+
+  .page-item {
+    &:first-child {
+      .page-link {
+        @include border-left-radius($border-radius);
+      }
+    }
+    &:last-child {
+      .page-link {
+        @include border-right-radius($border-radius);
+      }
+    }
+  }
+}
diff --git a/portal-FE-common/src/styles/bootstrap/mixins/_reset-text.scss b/portal-FE-common/src/styles/bootstrap/mixins/_reset-text.scss
new file mode 100644 (file)
index 0000000..71edb00
--- /dev/null
@@ -0,0 +1,17 @@
+@mixin reset-text {
+  font-family: $font-family-base;
+  // We deliberately do NOT reset font-size or word-wrap.
+  font-style: normal;
+  font-weight: $font-weight-normal;
+  line-height: $line-height-base;
+  text-align: left; // Fallback for where `start` is not supported
+  text-align: start; // stylelint-disable-line declaration-block-no-duplicate-properties
+  text-decoration: none;
+  text-shadow: none;
+  text-transform: none;
+  letter-spacing: normal;
+  word-break: normal;
+  word-spacing: normal;
+  white-space: normal;
+  line-break: auto;
+}
diff --git a/portal-FE-common/src/styles/bootstrap/mixins/_resize.scss b/portal-FE-common/src/styles/bootstrap/mixins/_resize.scss
new file mode 100644 (file)
index 0000000..66f233a
--- /dev/null
@@ -0,0 +1,6 @@
+// Resize anything
+
+@mixin resizable($direction) {
+  overflow: auto; // Per CSS3 UI, `resize` only applies when `overflow` isn't `visible`
+  resize: $direction; // Options: horizontal, vertical, both
+}
diff --git a/portal-FE-common/src/styles/bootstrap/mixins/_screen-reader.scss b/portal-FE-common/src/styles/bootstrap/mixins/_screen-reader.scss
new file mode 100644 (file)
index 0000000..8f3eb1b
--- /dev/null
@@ -0,0 +1,35 @@
+// Only display content to screen readers
+//
+// See: http://a11yproject.com/posts/how-to-hide-content/
+// See: https://hugogiraudel.com/2016/10/13/css-hide-and-seek/
+
+@mixin sr-only {
+  position: absolute;
+  width: 1px;
+  height: 1px;
+  padding: 0;
+  overflow: hidden;
+  clip: rect(0, 0, 0, 0);
+  white-space: nowrap;
+  clip-path: inset(50%);
+  border: 0;
+}
+
+// Use in conjunction with .sr-only to only display content when it's focused.
+//
+// Useful for "Skip to main content" links; see https://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1
+//
+// Credit: HTML5 Boilerplate
+
+@mixin sr-only-focusable {
+  &:active,
+  &:focus {
+    position: static;
+    width: auto;
+    height: auto;
+    overflow: visible;
+    clip: auto;
+    white-space: normal;
+    clip-path: none;
+  }
+}
diff --git a/portal-FE-common/src/styles/bootstrap/mixins/_size.scss b/portal-FE-common/src/styles/bootstrap/mixins/_size.scss
new file mode 100644 (file)
index 0000000..b9dd48e
--- /dev/null
@@ -0,0 +1,6 @@
+// Sizing shortcuts
+
+@mixin size($width, $height: $width) {
+  width: $width;
+  height: $height;
+}
diff --git a/portal-FE-common/src/styles/bootstrap/mixins/_table-row.scss b/portal-FE-common/src/styles/bootstrap/mixins/_table-row.scss
new file mode 100644 (file)
index 0000000..84f1d30
--- /dev/null
@@ -0,0 +1,30 @@
+// Tables
+
+@mixin table-row-variant($state, $background) {
+  // Exact selectors below required to override `.table-striped` and prevent
+  // inheritance to nested tables.
+  .table-#{$state} {
+    &,
+    > th,
+    > td {
+      background-color: $background;
+    }
+  }
+
+  // Hover states for `.table-hover`
+  // Note: this is not available for cells or rows within `thead` or `tfoot`.
+  .table-hover {
+    $hover-background: darken($background, 5%);
+
+    .table-#{$state} {
+      @include hover {
+        background-color: $hover-background;
+
+        > td,
+        > th {
+          background-color: $hover-background;
+        }
+      }
+    }
+  }
+}
diff --git a/portal-FE-common/src/styles/bootstrap/mixins/_text-emphasis.scss b/portal-FE-common/src/styles/bootstrap/mixins/_text-emphasis.scss
new file mode 100644 (file)
index 0000000..58db3e0
--- /dev/null
@@ -0,0 +1,14 @@
+// stylelint-disable declaration-no-important
+
+// Typography
+
+@mixin text-emphasis-variant($parent, $color) {
+  #{$parent} {
+    color: $color !important;
+  }
+  a#{$parent} {
+    @include hover-focus {
+      color: darken($color, 10%) !important;
+    }
+  }
+}
diff --git a/portal-FE-common/src/styles/bootstrap/mixins/_text-hide.scss b/portal-FE-common/src/styles/bootstrap/mixins/_text-hide.scss
new file mode 100644 (file)
index 0000000..aa551fd
--- /dev/null
@@ -0,0 +1,9 @@
+// CSS image replacement
+@mixin text-hide() {
+  // stylelint-disable-next-line font-family-no-missing-generic-family-keyword
+  font: 0/0 a;
+  color: transparent;
+  text-shadow: none;
+  background-color: transparent;
+  border: 0;
+}
diff --git a/portal-FE-common/src/styles/bootstrap/mixins/_text-truncate.scss b/portal-FE-common/src/styles/bootstrap/mixins/_text-truncate.scss
new file mode 100644 (file)
index 0000000..3504bb1
--- /dev/null
@@ -0,0 +1,8 @@
+// Text truncate
+// Requires inline-block or block for proper styling
+
+@mixin text-truncate() {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
diff --git a/portal-FE-common/src/styles/bootstrap/mixins/_transition.scss b/portal-FE-common/src/styles/bootstrap/mixins/_transition.scss
new file mode 100644 (file)
index 0000000..7e33dee
--- /dev/null
@@ -0,0 +1,9 @@
+@mixin transition($transition...) {
+  @if $enable-transitions {
+    @if length($transition) == 0 {
+      transition: $transition-base;
+    } @else {
+      transition: $transition;
+    }
+  }
+}
diff --git a/portal-FE-common/src/styles/bootstrap/mixins/_visibility.scss b/portal-FE-common/src/styles/bootstrap/mixins/_visibility.scss
new file mode 100644 (file)
index 0000000..fe523d0
--- /dev/null
@@ -0,0 +1,7 @@
+// stylelint-disable declaration-no-important
+
+// Visibility
+
+@mixin invisible($visibility) {
+  visibility: $visibility !important;
+}
diff --git a/portal-FE-common/src/styles/bootstrap/utilities/_align.scss b/portal-FE-common/src/styles/bootstrap/utilities/_align.scss
new file mode 100644 (file)
index 0000000..8b7df9f
--- /dev/null
@@ -0,0 +1,8 @@
+// stylelint-disable declaration-no-important
+
+.align-baseline    { vertical-align: baseline !important; } // Browser default
+.align-top         { vertical-align: top !important; }
+.align-middle      { vertical-align: middle !important; }
+.align-bottom      { vertical-align: bottom !important; }
+.align-text-bottom { vertical-align: text-bottom !important; }
+.align-text-top    { vertical-align: text-top !important; }
diff --git a/portal-FE-common/src/styles/bootstrap/utilities/_background.scss b/portal-FE-common/src/styles/bootstrap/utilities/_background.scss
new file mode 100644 (file)
index 0000000..1f18b2f
--- /dev/null
@@ -0,0 +1,19 @@
+// stylelint-disable declaration-no-important
+
+@each $color, $value in $theme-colors {
+  @include bg-variant(".bg-#{$color}", $value);
+}
+
+@if $enable-gradients {
+  @each $color, $value in $theme-colors {
+    @include bg-gradient-variant(".bg-gradient-#{$color}", $value);
+  }
+}
+
+.bg-white {
+  background-color: $white !important;
+}
+
+.bg-transparent {
+  background-color: transparent !important;
+}
diff --git a/portal-FE-common/src/styles/bootstrap/utilities/_borders.scss b/portal-FE-common/src/styles/bootstrap/utilities/_borders.scss
new file mode 100644 (file)
index 0000000..ba02f04
--- /dev/null
@@ -0,0 +1,54 @@
+// stylelint-disable declaration-no-important
+
+//
+// Border
+//
+
+.border          { border: $border-width solid $border-color !important; }
+.border-0        { border: 0 !important; }
+.border-top-0    { border-top: 0 !important; }
+.border-right-0  { border-right: 0 !important; }
+.border-bottom-0 { border-bottom: 0 !important; }
+.border-left-0   { border-left: 0 !important; }
+
+@each $color, $value in $theme-colors {
+  .border-#{$color} {
+    border-color: $value !important;
+  }
+}
+
+.border-white {
+  border-color: $white !important;
+}
+
+//
+// Border-radius
+//
+
+.rounded {
+  border-radius: $border-radius !important;
+}
+.rounded-top {
+  border-top-left-radius: $border-radius !important;
+  border-top-right-radius: $border-radius !important;
+}
+.rounded-right {
+  border-top-right-radius: $border-radius !important;
+  border-bottom-right-radius: $border-radius !important;
+}
+.rounded-bottom {
+  border-bottom-right-radius: $border-radius !important;
+  border-bottom-left-radius: $border-radius !important;
+}
+.rounded-left {
+  border-top-left-radius: $border-radius !important;
+  border-bottom-left-radius: $border-radius !important;
+}
+
+.rounded-circle {
+  border-radius: 50% !important;
+}
+
+.rounded-0 {
+  border-radius: 0 !important;
+}
diff --git a/portal-FE-common/src/styles/bootstrap/utilities/_clearfix.scss b/portal-FE-common/src/styles/bootstrap/utilities/_clearfix.scss
new file mode 100644 (file)
index 0000000..e92522a
--- /dev/null
@@ -0,0 +1,3 @@
+.clearfix {
+  @include clearfix();
+}
diff --git a/portal-FE-common/src/styles/bootstrap/utilities/_display.scss b/portal-FE-common/src/styles/bootstrap/utilities/_display.scss
new file mode 100644 (file)
index 0000000..893b638
--- /dev/null
@@ -0,0 +1,56 @@
+// stylelint-disable declaration-no-important
+
+//
+// Utilities for common `display` values
+//
+
+@each $breakpoint in map-keys($grid-breakpoints) {
+  @include media-breakpoint-up($breakpoint) {
+    $infix: breakpoint-infix($breakpoint, $grid-breakpoints);
+
+    .d#{$infix}-none         { display: none !important; }
+    .d#{$infix}-inline       { display: inline !important; }
+    .d#{$infix}-inline-block { display: inline-block !important; }
+    .d#{$infix}-block        { display: block !important; }
+    .d#{$infix}-table        { display: table !important; }
+    .d#{$infix}-table-row    { display: table-row !important; }
+    .d#{$infix}-table-cell   { display: table-cell !important; }
+    .d#{$infix}-flex         { display: flex !important; }
+    .d#{$infix}-inline-flex  { display: inline-flex !important; }
+  }
+}
+
+
+//
+// Utilities for toggling `display` in print
+//
+
+.d-print-block {
+  display: none !important;
+
+  @media print {
+    display: block !important;
+  }
+}
+
+.d-print-inline {
+  display: none !important;
+
+  @media print {
+    display: inline !important;
+  }
+}
+
+.d-print-inline-block {
+  display: none !important;
+
+  @media print {
+    display: inline-block !important;
+  }
+}
+
+.d-print-none {
+  @media print {
+    display: none !important;
+  }
+}
diff --git a/portal-FE-common/src/styles/bootstrap/utilities/_embed.scss b/portal-FE-common/src/styles/bootstrap/utilities/_embed.scss
new file mode 100644 (file)
index 0000000..d3362b6
--- /dev/null
@@ -0,0 +1,52 @@
+// Credit: Nicolas Gallagher and SUIT CSS.
+
+.embed-responsive {
+  position: relative;
+  display: block;
+  width: 100%;
+  padding: 0;
+  overflow: hidden;
+
+  &::before {
+    display: block;
+    content: "";
+  }
+
+  .embed-responsive-item,
+  iframe,
+  embed,
+  object,
+  video {
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+    border: 0;
+  }
+}
+
+.embed-responsive-21by9 {
+  &::before {
+    padding-top: percentage(9 / 21);
+  }
+}
+
+.embed-responsive-16by9 {
+  &::before {
+    padding-top: percentage(9 / 16);
+  }
+}
+
+.embed-responsive-4by3 {
+  &::before {
+    padding-top: percentage(3 / 4);
+  }
+}
+
+.embed-responsive-1by1 {
+  &::before {
+    padding-top: percentage(1 / 1);
+  }
+}
diff --git a/portal-FE-common/src/styles/bootstrap/utilities/_flex.scss b/portal-FE-common/src/styles/bootstrap/utilities/_flex.scss
new file mode 100644 (file)
index 0000000..8e47038
--- /dev/null
@@ -0,0 +1,46 @@
+// stylelint-disable declaration-no-important
+
+// Flex variation
+//
+// Custom styles for additional flex alignment options.
+
+@each $breakpoint in map-keys($grid-breakpoints) {
+  @include media-breakpoint-up($breakpoint) {
+    $infix: breakpoint-infix($breakpoint, $grid-breakpoints);
+
+    .flex#{$infix}-row            { flex-direction: row !important; }
+    .flex#{$infix}-column         { flex-direction: column !important; }
+    .flex#{$infix}-row-reverse    { flex-direction: row-reverse !important; }
+    .flex#{$infix}-column-reverse { flex-direction: column-reverse !important; }
+
+    .flex#{$infix}-wrap         { flex-wrap: wrap !important; }
+    .flex#{$infix}-nowrap       { flex-wrap: nowrap !important; }
+    .flex#{$infix}-wrap-reverse { flex-wrap: wrap-reverse !important; }
+
+    .justify-content#{$infix}-start   { justify-content: flex-start !important; }
+    .justify-content#{$infix}-end     { justify-content: flex-end !important; }
+    .justify-content#{$infix}-center  { justify-content: center !important; }
+    .justify-content#{$infix}-between { justify-content: space-between !important; }
+    .justify-content#{$infix}-around  { justify-content: space-around !important; }
+
+    .align-items#{$infix}-start    { align-items: flex-start !important; }
+    .align-items#{$infix}-end      { align-items: flex-end !important; }
+    .align-items#{$infix}-center   { align-items: center !important; }
+    .align-items#{$infix}-baseline { align-items: baseline !important; }
+    .align-items#{$infix}-stretch  { align-items: stretch !important; }
+
+    .align-content#{$infix}-start   { align-content: flex-start !important; }
+    .align-content#{$infix}-end     { align-content: flex-end !important; }
+    .align-content#{$infix}-center  { align-content: center !important; }
+    .align-content#{$infix}-between { align-content: space-between !important; }
+    .align-content#{$infix}-around  { align-content: space-around !important; }
+    .align-content#{$infix}-stretch { align-content: stretch !important; }
+
+    .align-self#{$infix}-auto     { align-self: auto !important; }
+    .align-self#{$infix}-start    { align-self: flex-start !important; }
+    .align-self#{$infix}-end      { align-self: flex-end !important; }
+    .align-self#{$infix}-center   { align-self: center !important; }
+    .align-self#{$infix}-baseline { align-self: baseline !important; }
+    .align-self#{$infix}-stretch  { align-self: stretch !important; }
+  }
+}
diff --git a/portal-FE-common/src/styles/bootstrap/utilities/_float.scss b/portal-FE-common/src/styles/bootstrap/utilities/_float.scss
new file mode 100644 (file)
index 0000000..01655e9
--- /dev/null
@@ -0,0 +1,9 @@
+@each $breakpoint in map-keys($grid-breakpoints) {
+  @include media-breakpoint-up($breakpoint) {
+    $infix: breakpoint-infix($breakpoint, $grid-breakpoints);
+
+    .float#{$infix}-left  { @include float-left; }
+    .float#{$infix}-right { @include float-right; }
+    .float#{$infix}-none  { @include float-none; }
+  }
+}
diff --git a/portal-FE-common/src/styles/bootstrap/utilities/_position.scss b/portal-FE-common/src/styles/bootstrap/utilities/_position.scss
new file mode 100644 (file)
index 0000000..ef962ed
--- /dev/null
@@ -0,0 +1,36 @@
+// stylelint-disable declaration-no-important
+
+// Common values
+
+// Sass list not in variables since it's not intended for customization.
+$positions: static, relative, absolute, fixed, sticky;
+
+@each $position in $positions {
+  .position-#{$position} { position: $position !important; }
+}
+
+// Shorthand
+
+.fixed-top {
+  position: fixed;
+  top: 0;
+  right: 0;
+  left: 0;
+  z-index: $zindex-fixed;
+}
+
+.fixed-bottom {
+  position: fixed;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  z-index: $zindex-fixed;
+}
+
+.sticky-top {
+  @supports (position: sticky) {
+    position: sticky;
+    top: 0;
+    z-index: $zindex-sticky;
+  }
+}
diff --git a/portal-FE-common/src/styles/bootstrap/utilities/_screenreaders.scss b/portal-FE-common/src/styles/bootstrap/utilities/_screenreaders.scss
new file mode 100644 (file)
index 0000000..9f26fde
--- /dev/null
@@ -0,0 +1,11 @@
+//
+// Screenreaders
+//
+
+.sr-only {
+  @include sr-only();
+}
+
+.sr-only-focusable {
+  @include sr-only-focusable();
+}
diff --git a/portal-FE-common/src/styles/bootstrap/utilities/_sizing.scss b/portal-FE-common/src/styles/bootstrap/utilities/_sizing.scss
new file mode 100644 (file)
index 0000000..e95a4db
--- /dev/null
@@ -0,0 +1,12 @@
+// stylelint-disable declaration-no-important
+
+// Width and height
+
+@each $prop, $abbrev in (width: w, height: h) {
+  @each $size, $length in $sizes {
+    .#{$abbrev}-#{$size} { #{$prop}: $length !important; }
+  }
+}
+
+.mw-100 { max-width: 100% !important; }
+.mh-100 { max-height: 100% !important; }
diff --git a/portal-FE-common/src/styles/bootstrap/utilities/_spacing.scss b/portal-FE-common/src/styles/bootstrap/utilities/_spacing.scss
new file mode 100644 (file)
index 0000000..b2e2354
--- /dev/null
@@ -0,0 +1,51 @@
+// stylelint-disable declaration-no-important
+
+// Margin and Padding
+
+@each $breakpoint in map-keys($grid-breakpoints) {
+  @include media-breakpoint-up($breakpoint) {
+    $infix: breakpoint-infix($breakpoint, $grid-breakpoints);
+
+    @each $prop, $abbrev in (margin: m, padding: p) {
+      @each $size, $length in $spacers {
+
+        .#{$abbrev}#{$infix}-#{$size} { #{$prop}: $length !important; }
+        .#{$abbrev}t#{$infix}-#{$size},
+        .#{$abbrev}y#{$infix}-#{$size} {
+          #{$prop}-top: $length !important;
+        }
+        .#{$abbrev}r#{$infix}-#{$size},
+        .#{$abbrev}x#{$infix}-#{$size} {
+          #{$prop}-right: $length !important;
+        }
+        .#{$abbrev}b#{$infix}-#{$size},
+        .#{$abbrev}y#{$infix}-#{$size} {
+          #{$prop}-bottom: $length !important;
+        }
+        .#{$abbrev}l#{$infix}-#{$size},
+        .#{$abbrev}x#{$infix}-#{$size} {
+          #{$prop}-left: $length !important;
+        }
+      }
+    }
+
+    // Some special margin utils
+    .m#{$infix}-auto { margin: auto !important; }
+    .mt#{$infix}-auto,
+    .my#{$infix}-auto {
+      margin-top: auto !important;
+    }
+    .mr#{$infix}-auto,
+    .mx#{$infix}-auto {
+      margin-right: auto !important;
+    }
+    .mb#{$infix}-auto,
+    .my#{$infix}-auto {
+      margin-bottom: auto !important;
+    }
+    .ml#{$infix}-auto,
+    .mx#{$infix}-auto {
+      margin-left: auto !important;
+    }
+  }
+}
diff --git a/portal-FE-common/src/styles/bootstrap/utilities/_text.scss b/portal-FE-common/src/styles/bootstrap/utilities/_text.scss
new file mode 100644 (file)
index 0000000..f4b6e65
--- /dev/null
@@ -0,0 +1,52 @@
+// stylelint-disable declaration-no-important
+
+//
+// Text
+//
+
+// Alignment
+
+.text-justify  { text-align: justify !important; }
+.text-nowrap   { white-space: nowrap !important; }
+.text-truncate { @include text-truncate; }
+
+// Responsive alignment
+
+@each $breakpoint in map-keys($grid-breakpoints) {
+  @include media-breakpoint-up($breakpoint) {
+    $infix: breakpoint-infix($breakpoint, $grid-breakpoints);
+
+    .text#{$infix}-left   { text-align: left !important; }
+    .text#{$infix}-right  { text-align: right !important; }
+    .text#{$infix}-center { text-align: center !important; }
+  }
+}
+
+// Transformation
+
+.text-lowercase  { text-transform: lowercase !important; }
+.text-uppercase  { text-transform: uppercase !important; }
+.text-capitalize { text-transform: capitalize !important; }
+
+// Weight and italics
+
+.font-weight-light  { font-weight: $font-weight-light !important; }
+.font-weight-normal { font-weight: $font-weight-normal !important; }
+.font-weight-bold   { font-weight: $font-weight-bold !important; }
+.font-italic        { font-style: italic !important; }
+
+// Contextual colors
+
+.text-white { color: #fff !important; }
+
+@each $color, $value in $theme-colors {
+  @include text-emphasis-variant(".text-#{$color}", $value);
+}
+
+.text-muted { color: $text-muted !important; }
+
+// Misc
+
+.text-hide {
+  @include text-hide();
+}
diff --git a/portal-FE-common/src/styles/bootstrap/utilities/_visibility.scss b/portal-FE-common/src/styles/bootstrap/utilities/_visibility.scss
new file mode 100644 (file)
index 0000000..823406d
--- /dev/null
@@ -0,0 +1,11 @@
+//
+// Visibility utilities
+//
+
+.visible {
+  @include invisible(visible);
+}
+
+.invisible {
+  @include invisible(hidden);
+}
diff --git a/portal-FE-os/.editorconfig b/portal-FE-os/.editorconfig
new file mode 100644 (file)
index 0000000..e89330a
--- /dev/null
@@ -0,0 +1,13 @@
+# Editor configuration, see https://editorconfig.org
+root = true
+
+[*]
+charset = utf-8
+indent_style = space
+indent_size = 2
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.md]
+max_line_length = off
+trim_trailing_whitespace = false
diff --git a/portal-FE-os/.gitignore b/portal-FE-os/.gitignore
new file mode 100644 (file)
index 0000000..ae8fe5e
--- /dev/null
@@ -0,0 +1,45 @@
+# See http://help.github.com/ignore-files/ for more about ignoring files.
+
+# compiled output
+/dist
+/tmp
+/out-tsc
+
+# dependencies
+/node_modules
+
+# IDEs and editors
+/.idea
+.project
+.classpath
+.c9/
+*.launch
+.settings/
+*.sublime-workspace
+
+# IDE - VSCode
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+
+# misc
+/.sass-cache
+/connect.lock
+/coverage
+/libpeerconnection.log
+npm-debug.log
+yarn-error.log
+testem.log
+/typings
+
+# System Files
+.DS_Store
+Thumbs.db
+
+.history/*
+/target/
+/node/node_modules/*
+/node/node.exe
+/.classpath
diff --git a/portal-FE-os/README.md b/portal-FE-os/README.md
new file mode 100644 (file)
index 0000000..6823146
--- /dev/null
@@ -0,0 +1,27 @@
+# PortalFEos
+
+This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 7.0.6.
+
+## Development server
+
+Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
+
+## Code scaffolding
+
+Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
+
+## Build
+
+Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build.
+
+## Running unit tests
+
+Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
+
+## Running end-to-end tests
+
+Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
+
+## Further help
+
+To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
diff --git a/portal-FE-os/angular.json b/portal-FE-os/angular.json
new file mode 100644 (file)
index 0000000..5bcac9e
--- /dev/null
@@ -0,0 +1,162 @@
+{
+  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
+  "version": 1,
+  "newProjectRoot": "projects",
+  "projects": {
+    "portal-FE-os": {
+      "root": "",
+      "sourceRoot": "src",
+      "projectType": "application",
+      "prefix": "app",
+      "schematics": {
+        "@schematics/angular:component": {
+          "prefix": "app",
+          "styleext": "scss"
+        }
+      },
+      "architect": {
+        "build": {
+          "builder": "@angular-devkit/build-angular:browser",
+          "options": {
+            "outputPath": "dist/public",
+            "index": "src/index.html",
+            "main": "src/main.ts",
+            "polyfills": "src/polyfills.ts",
+            "tsConfig": "src/tsconfig.app.json",
+            "assets": [
+              "src/favicon.ico",
+              "src/assets"
+            ],
+            "styles": [
+              "node_modules/ionicons/dist/scss/ionicons.scss",
+              "node_modules/material-design-icons-iconfont/dist/material-design-icons.css",
+"node_modules/jqtree/jqtree.css",
+"src/styles/app.scss"
+            ],
+            "scripts": [
+              "node_modules/jquery/dist/jquery.min.js",
+              "./node_modules/hammerjs/hammer.min.js",
+ "node_modules/jqtree/tree.jquery.js",
+              "node_modules/systemjs/dist/s.js",
+              "node_modules/systemjs/dist/extras/named-register.js",
+              "node_modules/systemjs/dist/extras/amd.js",
+                         "src/app/shared/utils/utils.js"
+            ]
+          },
+          "configurations": {
+            "production": {
+              "fileReplacements": [
+                {
+                  "replace": "src/environments/environment.ts",
+                  "with": "src/environments/environment.prod.ts"
+                }
+              ],
+              "optimization": true,
+              "outputHashing": "all",
+              "sourceMap": false,
+              "extractCss": true,
+              "namedChunks": false,
+              "aot": true,
+              "extractLicenses": true,
+              "vendorChunk": false,
+              "buildOptimizer": true,
+              "budgets": [
+                {
+                  "type": "initial",
+                  "maximumWarning": "2mb",
+                  "maximumError": "5mb"
+                }
+              ]
+            }
+          }
+        },
+        "serve": {
+          "builder": "@angular-devkit/build-angular:dev-server",
+          "options": {
+            "browserTarget": "portal-FE-os:build"
+          },
+          "configurations": {
+            "production": {
+              "browserTarget": "portal-FE-os:build:production"
+            }
+          }
+        },
+        "extract-i18n": {
+          "builder": "@angular-devkit/build-angular:extract-i18n",
+          "options": {
+            "browserTarget": "portal-FE-os:build"
+          }
+        },
+        "test": {
+          "builder": "@angular-devkit/build-angular:karma",
+          "options": {
+            "main": "src/test.ts",
+            "polyfills": "src/polyfills.ts",
+            "tsConfig": "src/tsconfig.spec.json",
+            "karmaConfig": "src/karma.conf.js",
+            "styles": [
+              "node_modules/ionicons/dist/scss/ionicons.scss",
+"node_modules/material-design-icons-iconfont/dist/material-design-icons.css",
+              "node_modules/jqtree/jqtree.css",
+              "src/styles/app.scss"
+            ],
+            "scripts": [
+              "node_modules/jquery/dist/jquery.min.js",
+              "node_modules/hammerjs/hammer.min.js",
+"node_modules/jqtree/tree.jquery.js",
+              "node_modules/systemjs/dist/s.js",
+              "node_modules/systemjs/dist/extras/named-register.js",
+              "node_modules/systemjs/dist/extras/amd.js",
+              "src/app/shared/utils/utils.js"
+            ],
+            "assets": [
+              "src/favicon.ico",
+              "src/assets"
+            ]
+          }
+        },
+        "lint": {
+          "builder": "@angular-devkit/build-angular:tslint",
+          "options": {
+            "tsConfig": [
+              "src/tsconfig.app.json",
+              "src/tsconfig.spec.json"
+            ],
+            "exclude": [
+              "**/node_modules/**"
+            ]
+          }
+        }
+      }
+    },
+    "portal-FE-os-e2e": {
+      "root": "e2e/",
+      "projectType": "application",
+      "prefix": "",
+      "architect": {
+        "e2e": {
+          "builder": "@angular-devkit/build-angular:protractor",
+          "options": {
+            "protractorConfig": "e2e/protractor.conf.js",
+            "devServerTarget": "portal-FE-os:serve"
+          },
+          "configurations": {
+            "production": {
+              "devServerTarget": "portal-FE-os:serve:production"
+            }
+          }
+        },
+        "lint": {
+          "builder": "@angular-devkit/build-angular:tslint",
+          "options": {
+            "tsConfig": "e2e/tsconfig.e2e.json",
+            "exclude": [
+              "**/node_modules/**"
+            ]
+          }
+        }
+      }
+    }
+  },
+  "defaultProject": "portal-FE-os"
+}
\ No newline at end of file
diff --git a/portal-FE-os/e2e/protractor.conf.js b/portal-FE-os/e2e/protractor.conf.js
new file mode 100644 (file)
index 0000000..86776a3
--- /dev/null
@@ -0,0 +1,28 @@
+// Protractor configuration file, see link for more information
+// https://github.com/angular/protractor/blob/master/lib/config.ts
+
+const { SpecReporter } = require('jasmine-spec-reporter');
+
+exports.config = {
+  allScriptsTimeout: 11000,
+  specs: [
+    './src/**/*.e2e-spec.ts'
+  ],
+  capabilities: {
+    'browserName': 'chrome'
+  },
+  directConnect: true,
+  baseUrl: 'http://localhost:4200/',
+  framework: 'jasmine',
+  jasmineNodeOpts: {
+    showColors: true,
+    defaultTimeoutInterval: 30000,
+    print: function() {}
+  },
+  onPrepare() {
+    require('ts-node').register({
+      project: require('path').join(__dirname, './tsconfig.e2e.json')
+    });
+    jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
+  }
+};
\ No newline at end of file
diff --git a/portal-FE-os/e2e/src/app.e2e-spec.ts b/portal-FE-os/e2e/src/app.e2e-spec.ts
new file mode 100644 (file)
index 0000000..5bd4373
--- /dev/null
@@ -0,0 +1,14 @@
+import { AppPage } from './app.po';
+
+describe('workspace-project App', () => {
+  let page: AppPage;
+
+  beforeEach(() => {
+    page = new AppPage();
+  });
+
+  it('should display welcome message', () => {
+    page.navigateTo();
+    expect(page.getTitleText()).toEqual('Welcome to portal-FE-os!');
+  });
+});
diff --git a/portal-FE-os/e2e/src/app.po.ts b/portal-FE-os/e2e/src/app.po.ts
new file mode 100644 (file)
index 0000000..72e463a
--- /dev/null
@@ -0,0 +1,11 @@
+import { browser, by, element } from 'protractor';
+
+export class AppPage {
+  navigateTo() {
+    return browser.get('/');
+  }
+
+  getTitleText() {
+    return element(by.css('app-root h1')).getText();
+  }
+}
diff --git a/portal-FE-os/e2e/tsconfig.e2e.json b/portal-FE-os/e2e/tsconfig.e2e.json
new file mode 100644 (file)
index 0000000..a6dd622
--- /dev/null
@@ -0,0 +1,13 @@
+{
+  "extends": "../tsconfig.json",
+  "compilerOptions": {
+    "outDir": "../out-tsc/app",
+    "module": "commonjs",
+    "target": "es5",
+    "types": [
+      "jasmine",
+      "jasminewd2",
+      "node"
+    ]
+  }
+}
\ No newline at end of file
diff --git a/portal-FE-os/package-lock.json b/portal-FE-os/package-lock.json
new file mode 100644 (file)
index 0000000..eb43846
--- /dev/null
@@ -0,0 +1,10884 @@
+{
+  "name": "portal-fe-os",
+  "version": "7.0.0",
+  "lockfileVersion": 1,
+  "requires": true,
+  "dependencies": {
+    "@angular-devkit/architect": {
+      "version": "0.10.7",
+      "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.10.7.tgz",
+      "integrity": "sha512-S49LSslNRxIflHzrIrEgK7mGQ7HzETr/FU0fyTbB0vubcmfzMoYTsgYdK7SUz583lovc+UvASoUAhPJI3e35ng==",
+      "dev": true,
+      "requires": {
+        "@angular-devkit/core": "7.0.7",
+        "rxjs": "6.3.3"
+      }
+    },
+    "@angular-devkit/build-angular": {
+      "version": "0.10.7",
+      "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-0.10.7.tgz",
+      "integrity": "sha512-wjhlMWWkGSSkdwd9elKfeeEgyig/eZGyF2wY5kZmWPBdeK/GfdBLyO15qh4ppRYI2SjyRvzl0tWDOA2Y0hKL0w==",
+      "dev": true,
+      "requires": {
+        "@angular-devkit/architect": "0.10.7",
+        "@angular-devkit/build-optimizer": "0.10.7",
+        "@angular-devkit/build-webpack": "0.10.7",
+        "@angular-devkit/core": "7.0.7",
+        "@ngtools/webpack": "7.0.7",
+        "ajv": "6.5.3",
+        "autoprefixer": "9.1.5",
+        "circular-dependency-plugin": "5.0.2",
+        "clean-css": "4.2.1",
+        "copy-webpack-plugin": "4.5.4",
+        "file-loader": "2.0.0",
+        "glob": "7.1.3",
+        "istanbul": "0.4.5",
+        "istanbul-instrumenter-loader": "3.0.1",
+        "karma-source-map-support": "1.3.0",
+        "less": "3.8.1",
+        "less-loader": "4.1.0",
+        "license-webpack-plugin": "2.0.2",
+        "loader-utils": "1.1.0",
+        "mini-css-extract-plugin": "0.4.3",
+        "minimatch": "3.0.4",
+        "node-sass": "4.9.3",
+        "opn": "5.3.0",
+        "parse5": "4.0.0",
+        "portfinder": "1.0.17",
+        "postcss": "7.0.5",
+        "postcss-import": "12.0.0",
+        "postcss-loader": "3.0.0",
+        "raw-loader": "0.5.1",
+        "rxjs": "6.3.3",
+        "sass-loader": "7.1.0",
+        "semver": "5.5.1",
+        "source-map-loader": "0.2.4",
+        "source-map-support": "0.5.9",
+        "speed-measure-webpack-plugin": "^1.2.3",
+        "stats-webpack-plugin": "0.7.0",
+        "style-loader": "0.23.0",
+        "stylus": "0.54.5",
+        "stylus-loader": "3.0.2",
+        "terser-webpack-plugin": "1.1.0",
+        "tree-kill": "1.2.0",
+        "webpack": "4.19.1",
+        "webpack-dev-middleware": "3.3.0",
+        "webpack-dev-server": "3.1.8",
+        "webpack-merge": "4.1.4",
+        "webpack-sources": "1.2.0",
+        "webpack-subresource-integrity": "1.1.0-rc.6"
+      }
+    },
+    "@angular-devkit/build-optimizer": {
+      "version": "0.10.7",
+      "resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.10.7.tgz",
+      "integrity": "sha512-Ztj2U21B8zRO2csQS8mLv/+WKPPLePzaqJDk53Ou2r2HV+kh9GzYvgu1UFeGf/RyEeJi+9KnJGG2wPaeNqDNxg==",
+      "dev": true,
+      "requires": {
+        "loader-utils": "1.1.0",
+        "source-map": "0.5.6",
+        "typescript": "3.1.6",
+        "webpack-sources": "1.2.0"
+      },
+      "dependencies": {
+        "source-map": {
+          "version": "0.5.6",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
+          "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=",
+          "dev": true
+        }
+      }
+    },
+    "@angular-devkit/build-webpack": {
+      "version": "0.10.7",
+      "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.10.7.tgz",
+      "integrity": "sha512-sUzgIhm5yWHvRo3GF6mc1J58PCuY5nJDF2vlE8Jhlwkq+/VbJ/NVfTDYRQCeqI1jLcdMaVrVQXnXAWc4KpFNig==",
+      "dev": true,
+      "requires": {
+        "@angular-devkit/architect": "0.10.7",
+        "@angular-devkit/core": "7.0.7",
+        "rxjs": "6.3.3"
+      }
+    },
+    "@angular-devkit/core": {
+      "version": "7.0.7",
+      "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-7.0.7.tgz",
+      "integrity": "sha512-M8tTT9r3nUtWI3YyiyynHIQn+lQQgeKkxVZ+rdxvyvgE3U9+wn0yep5HkFLQETTuJetu9ARRRD94sD2XL3F/3A==",
+      "dev": true,
+      "requires": {
+        "ajv": "6.5.3",
+        "chokidar": "2.0.4",
+        "fast-json-stable-stringify": "2.0.0",
+        "rxjs": "6.3.3",
+        "source-map": "0.7.3"
+      }
+    },
+    "@angular-devkit/schematics": {
+      "version": "7.0.7",
+      "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-7.0.7.tgz",
+      "integrity": "sha512-E6GHu4257PvymRjFDtpGc0ykdcIcpFIfXr73lq8qxo1SBkqH7Y1/C670elDg9nrCte8PhnhJVNiwNgNS/ZTAzQ==",
+      "dev": true,
+      "requires": {
+        "@angular-devkit/core": "7.0.7",
+        "rxjs": "6.3.3"
+      }
+    },
+    "@angular/animations": {
+      "version": "7.0.4",
+      "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-7.0.4.tgz",
+      "integrity": "sha512-QfFikT0FzYNMjdVg0LWTBijdu9JDJyzejnhCFlXxv+KR4zolpRK98/rU7CFW1Fg2jjL3/yL9PT1sf5I0fTJZYA==",
+      "requires": {
+        "tslib": "^1.9.0"
+      }
+    },
+    "@angular/cdk": {
+      "version": "7.0.4",
+      "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-7.0.4.tgz",
+      "integrity": "sha512-4KbuiVLonwNwzwgJqKOvjqXfXKrdboPzFwk4vGruQV/EhGh6L8V4gy+ESS4seUuYYsMA9k+ijEeO9xUX+pAcZw==",
+      "requires": {
+        "parse5": "^5.0.0",
+        "tslib": "^1.7.1"
+      },
+      "dependencies": {
+        "parse5": {
+          "version": "5.1.0",
+          "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz",
+          "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==",
+          "optional": true
+        }
+      }
+    },
+    "@angular/cli": {
+      "version": "7.0.7",
+      "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-7.0.7.tgz",
+      "integrity": "sha512-SV3CcHa2oxDKwhOvHqZtysVRRT9pkO04Kv0Z1HEhlgIwqHyIU201R9/mo1gYmBHTNGxowKdvsGLsHQNpsHmQJw==",
+      "dev": true,
+      "requires": {
+        "@angular-devkit/architect": "0.10.7",
+        "@angular-devkit/core": "7.0.7",
+        "@angular-devkit/schematics": "7.0.7",
+        "@schematics/angular": "7.0.7",
+        "@schematics/update": "0.10.7",
+        "inquirer": "6.2.0",
+        "opn": "5.3.0",
+        "rxjs": "6.3.3",
+        "semver": "5.5.1",
+        "symbol-observable": "1.2.0"
+      }
+    },
+    "@angular/common": {
+      "version": "7.0.4",
+      "resolved": "https://registry.npmjs.org/@angular/common/-/common-7.0.4.tgz",
+      "integrity": "sha512-akQojdqY/RBlItkDWAPI3k0Llk1wnbAp+f47yySi3cgQz9SaZ1/RLNWZV84I/cKrksb4ehorT/lTqRBojsAD1A==",
+      "requires": {
+        "tslib": "^1.9.0"
+      }
+    },
+    "@angular/compiler": {
+      "version": "7.0.4",
+      "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-7.0.4.tgz",
+      "integrity": "sha512-ExDhH1cJkuJkUsgNRZyZBse0a7wWkQyG5O8HONi3Rzig9dalFEuve9jD04zfA1Jx1GTXhovqtGnF72x4kw0V8Q==",
+      "requires": {
+        "tslib": "^1.9.0"
+      }
+    },
+    "@angular/compiler-cli": {
+      "version": "7.0.4",
+      "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-7.0.4.tgz",
+      "integrity": "sha512-kvhWt6OTb1Uduns9Vm+Dwd/UUBNSEU6Jgu+QOPeHr7lg+4NTyr9uQLU0DtfBP0ljOlds8esmfii5IIFTeUQw1Q==",
+      "dev": true,
+      "requires": {
+        "canonical-path": "1.0.0",
+        "chokidar": "^1.4.2",
+        "convert-source-map": "^1.5.1",
+        "dependency-graph": "^0.7.2",
+        "magic-string": "^0.25.0",
+        "minimist": "^1.2.0",
+        "reflect-metadata": "^0.1.2",
+        "shelljs": "^0.8.1",
+        "source-map": "^0.6.1",
+        "tslib": "^1.9.0",
+        "yargs": "9.0.1"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+          "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+          "dev": true
+        },
+        "anymatch": {
+          "version": "1.3.2",
+          "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz",
+          "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==",
+          "dev": true,
+          "requires": {
+            "micromatch": "^2.1.5",
+            "normalize-path": "^2.0.0"
+          }
+        },
+        "arr-diff": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
+          "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=",
+          "dev": true,
+          "requires": {
+            "arr-flatten": "^1.0.1"
+          }
+        },
+        "array-unique": {
+          "version": "0.2.1",
+          "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
+          "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=",
+          "dev": true
+        },
+        "braces": {
+          "version": "1.8.5",
+          "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz",
+          "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=",
+          "dev": true,
+          "requires": {
+            "expand-range": "^1.8.1",
+            "preserve": "^0.2.0",
+            "repeat-element": "^1.1.2"
+          }
+        },
+        "camelcase": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
+          "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=",
+          "dev": true
+        },
+        "chokidar": {
+          "version": "1.7.0",
+          "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz",
+          "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=",
+          "dev": true,
+          "requires": {
+            "anymatch": "^1.3.0",
+            "async-each": "^1.0.0",
+            "fsevents": "^1.0.0",
+            "glob-parent": "^2.0.0",
+            "inherits": "^2.0.1",
+            "is-binary-path": "^1.0.0",
+            "is-glob": "^2.0.0",
+            "path-is-absolute": "^1.0.0",
+            "readdirp": "^2.0.0"
+          }
+        },
+        "cross-spawn": {
+          "version": "5.1.0",
+          "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
+          "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
+          "dev": true,
+          "requires": {
+            "lru-cache": "^4.0.1",
+            "shebang-command": "^1.2.0",
+            "which": "^1.2.9"
+          }
+        },
+        "execa": {
+          "version": "0.7.0",
+          "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz",
+          "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=",
+          "dev": true,
+          "requires": {
+            "cross-spawn": "^5.0.1",
+            "get-stream": "^3.0.0",
+            "is-stream": "^1.1.0",
+            "npm-run-path": "^2.0.0",
+            "p-finally": "^1.0.0",
+            "signal-exit": "^3.0.0",
+            "strip-eof": "^1.0.0"
+          }
+        },
+        "expand-brackets": {
+          "version": "0.1.5",
+          "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
+          "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=",
+          "dev": true,
+          "requires": {
+            "is-posix-bracket": "^0.1.0"
+          }
+        },
+        "extglob": {
+          "version": "0.3.2",
+          "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz",
+          "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=",
+          "dev": true,
+          "requires": {
+            "is-extglob": "^1.0.0"
+          }
+        },
+        "glob-parent": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz",
+          "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=",
+          "dev": true,
+          "requires": {
+            "is-glob": "^2.0.0"
+          }
+        },
+        "is-extglob": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
+          "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
+          "dev": true
+        },
+        "is-fullwidth-code-point": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+          "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+          "dev": true
+        },
+        "is-glob": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
+          "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
+          "dev": true,
+          "requires": {
+            "is-extglob": "^1.0.0"
+          }
+        },
+        "kind-of": {
+          "version": "3.2.2",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+          "dev": true,
+          "requires": {
+            "is-buffer": "^1.1.5"
+          }
+        },
+        "load-json-file": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
+          "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=",
+          "dev": true,
+          "requires": {
+            "graceful-fs": "^4.1.2",
+            "parse-json": "^2.2.0",
+            "pify": "^2.0.0",
+            "strip-bom": "^3.0.0"
+          }
+        },
+        "mem": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz",
+          "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=",
+          "dev": true,
+          "requires": {
+            "mimic-fn": "^1.0.0"
+          }
+        },
+        "micromatch": {
+          "version": "2.3.11",
+          "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
+          "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=",
+          "dev": true,
+          "requires": {
+            "arr-diff": "^2.0.0",
+            "array-unique": "^0.2.1",
+            "braces": "^1.8.2",
+            "expand-brackets": "^0.1.4",
+            "extglob": "^0.3.1",
+            "filename-regex": "^2.0.0",
+            "is-extglob": "^1.0.0",
+            "is-glob": "^2.0.1",
+            "kind-of": "^3.0.2",
+            "normalize-path": "^2.0.1",
+            "object.omit": "^2.0.0",
+            "parse-glob": "^3.0.4",
+            "regex-cache": "^0.4.2"
+          }
+        },
+        "mimic-fn": {
+          "version": "1.2.0",
+          "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
+          "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
+          "dev": true
+        },
+        "minimist": {
+          "version": "1.2.0",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+          "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+          "dev": true
+        },
+        "os-locale": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz",
+          "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==",
+          "dev": true,
+          "requires": {
+            "execa": "^0.7.0",
+            "lcid": "^1.0.0",
+            "mem": "^1.1.0"
+          }
+        },
+        "path-type": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz",
+          "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=",
+          "dev": true,
+          "requires": {
+            "pify": "^2.0.0"
+          }
+        },
+        "pify": {
+          "version": "2.3.0",
+          "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+          "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+          "dev": true
+        },
+        "read-pkg": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz",
+          "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=",
+          "dev": true,
+          "requires": {
+            "load-json-file": "^2.0.0",
+            "normalize-package-data": "^2.3.2",
+            "path-type": "^2.0.0"
+          }
+        },
+        "read-pkg-up": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz",
+          "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=",
+          "dev": true,
+          "requires": {
+            "find-up": "^2.0.0",
+            "read-pkg": "^2.0.0"
+          }
+        },
+        "source-map": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+          "dev": true
+        },
+        "string-width": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+          "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+          "dev": true,
+          "requires": {
+            "is-fullwidth-code-point": "^2.0.0",
+            "strip-ansi": "^4.0.0"
+          }
+        },
+        "strip-ansi": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+          "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^3.0.0"
+          }
+        },
+        "strip-bom": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+          "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+          "dev": true
+        },
+        "which-module": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
+          "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
+          "dev": true
+        },
+        "y18n": {
+          "version": "3.2.1",
+          "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
+          "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=",
+          "dev": true
+        },
+        "yargs": {
+          "version": "9.0.1",
+          "resolved": "https://registry.npmjs.org/yargs/-/yargs-9.0.1.tgz",
+          "integrity": "sha1-UqzCP+7Kw0BCB47njAwAf1CF20w=",
+          "dev": true,
+          "requires": {
+            "camelcase": "^4.1.0",
+            "cliui": "^3.2.0",
+            "decamelize": "^1.1.1",
+            "get-caller-file": "^1.0.1",
+            "os-locale": "^2.0.0",
+            "read-pkg-up": "^2.0.0",
+            "require-directory": "^2.1.1",
+            "require-main-filename": "^1.0.1",
+            "set-blocking": "^2.0.0",
+            "string-width": "^2.0.0",
+            "which-module": "^2.0.0",
+            "y18n": "^3.2.1",
+            "yargs-parser": "^7.0.0"
+          }
+        },
+        "yargs-parser": {
+          "version": "7.0.0",
+          "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz",
+          "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=",
+          "dev": true,
+          "requires": {
+            "camelcase": "^4.1.0"
+          }
+        }
+      }
+    },
+    "@angular/core": {
+      "version": "7.0.4",
+      "resolved": "https://registry.npmjs.org/@angular/core/-/core-7.0.4.tgz",
+      "integrity": "sha512-17SSmCz1wQoZKnVHF/T8UkWYPpDm5kPyoc1okkTTv8ZA2EAMMuZFFnRSAxEL5i7mNB9z5CvRqF2tRx/DbgbIRA==",
+      "requires": {
+        "tslib": "^1.9.0"
+      }
+    },
+    "@angular/forms": {
+      "version": "7.0.4",
+      "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-7.0.4.tgz",
+      "integrity": "sha512-W3nN9n1VY9On9+9f7PDRbzJUg+mMq1bjkhWsk/b7DfaYdmlzpG+Wd6OfArob2edsqGqH1dvTM8q8aGbWiFZ7dA==",
+      "requires": {
+        "tslib": "^1.9.0"
+      }
+    },
+    "@angular/http": {
+      "version": "7.0.4",
+      "resolved": "https://registry.npmjs.org/@angular/http/-/http-7.0.4.tgz",
+      "integrity": "sha512-oUGT7xS7FZYajuHq0DP6MgahacB5sJTRgxiUU4uhQ/mqV7aREODVJJgw7oHDhM7Cnyzzo0B9D0zpEljKmeCLWQ==",
+      "requires": {
+        "tslib": "^1.9.0"
+      }
+    },
+    "@angular/language-service": {
+      "version": "7.0.4",
+      "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-7.0.4.tgz",
+      "integrity": "sha512-CuJ2Ii97sNoN1HOZOLxG1lEHsQFi8K/RSB/k2suWPKzdM53ldSkKoYRac38zW/uqNABYItgvxb7w0Vi7HhxLsg==",
+      "dev": true
+    },
+    "@angular/material": {
+      "version": "7.0.4",
+      "resolved": "https://registry.npmjs.org/@angular/material/-/material-7.0.4.tgz",
+      "integrity": "sha512-LoDtg6srT9WPEn4bsiJqU1uXJ6bd28FtSc7prDYaPb5ogTj1zaur4LWJ7GjPK1haq4rW4W2NMTuayIsqpdGfSA==",
+      "requires": {
+        "tslib": "^1.7.1"
+      }
+    },
+    "@angular/platform-browser": {
+      "version": "7.0.4",
+      "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-7.0.4.tgz",
+      "integrity": "sha512-4brYZZgsCJk1/a6JoSwaiVWO9+/T4iyE27dAgstao1nOf/jrBNKW2HnZtkWZmCCBK0WIk15wlB0Xr87OZbjNVA==",
+      "requires": {
+        "tslib": "^1.9.0"
+      }
+    },
+    "@angular/platform-browser-dynamic": {
+      "version": "7.0.4",
+      "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-7.0.4.tgz",
+      "integrity": "sha512-k1I53zIg8YWhtQizLfq/tWrUUdY5vHV8pGHyt0/UTGDqat5TORd6LDFfzCSux0r3qZujCOGNi9f4/AbyV8B9lw==",
+      "requires": {
+        "tslib": "^1.9.0"
+      }
+    },
+    "@angular/router": {
+      "version": "7.0.4",
+      "resolved": "https://registry.npmjs.org/@angular/router/-/router-7.0.4.tgz",
+      "integrity": "sha512-nt1jJsxN+JmYZ6URamMdULUpH4aHdnNVKjWtjDI0OpdZvPx7PMFD8cfc92q0tavy2KqqexcceIb4BIC965gtpA==",
+      "requires": {
+        "tslib": "^1.9.0"
+      }
+    },
+    "@babel/code-frame": {
+      "version": "7.5.5",
+      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz",
+      "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==",
+      "dev": true,
+      "requires": {
+        "@babel/highlight": "^7.0.0"
+      }
+    },
+    "@babel/generator": {
+      "version": "7.5.5",
+      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.5.5.tgz",
+      "integrity": "sha512-ETI/4vyTSxTzGnU2c49XHv2zhExkv9JHLTwDAFz85kmcwuShvYG2H08FwgIguQf4JC75CBnXAUM5PqeF4fj0nQ==",
+      "dev": true,
+      "requires": {
+        "@babel/types": "^7.5.5",
+        "jsesc": "^2.5.1",
+        "lodash": "^4.17.13",
+        "source-map": "^0.5.0",
+        "trim-right": "^1.0.1"
+      },
+      "dependencies": {
+        "jsesc": {
+          "version": "2.5.2",
+          "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
+          "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+          "dev": true
+        },
+        "source-map": {
+          "version": "0.5.7",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+          "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+          "dev": true
+        }
+      }
+    },
+    "@babel/helper-function-name": {
+      "version": "7.1.0",
+      "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz",
+      "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-get-function-arity": "^7.0.0",
+        "@babel/template": "^7.1.0",
+        "@babel/types": "^7.0.0"
+      }
+    },
+    "@babel/helper-get-function-arity": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz",
+      "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==",
+      "dev": true,
+      "requires": {
+        "@babel/types": "^7.0.0"
+      }
+    },
+    "@babel/helper-split-export-declaration": {
+      "version": "7.4.4",
+      "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz",
+      "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==",
+      "dev": true,
+      "requires": {
+        "@babel/types": "^7.4.4"
+      }
+    },
+    "@babel/highlight": {
+      "version": "7.5.0",
+      "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz",
+      "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==",
+      "dev": true,
+      "requires": {
+        "chalk": "^2.0.0",
+        "esutils": "^2.0.2",
+        "js-tokens": "^4.0.0"
+      },
+      "dependencies": {
+        "js-tokens": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+          "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+          "dev": true
+        }
+      }
+    },
+    "@babel/parser": {
+      "version": "7.5.5",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.5.5.tgz",
+      "integrity": "sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g==",
+      "dev": true
+    },
+    "@babel/template": {
+      "version": "7.4.4",
+      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.4.tgz",
+      "integrity": "sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw==",
+      "dev": true,
+      "requires": {
+        "@babel/code-frame": "^7.0.0",
+        "@babel/parser": "^7.4.4",
+        "@babel/types": "^7.4.4"
+      }
+    },
+    "@babel/traverse": {
+      "version": "7.5.5",
+      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.5.5.tgz",
+      "integrity": "sha512-MqB0782whsfffYfSjH4TM+LMjrJnhCNEDMDIjeTpl+ASaUvxcjoiVCo/sM1GhS1pHOXYfWVCYneLjMckuUxDaQ==",
+      "dev": true,
+      "requires": {
+        "@babel/code-frame": "^7.5.5",
+        "@babel/generator": "^7.5.5",
+        "@babel/helper-function-name": "^7.1.0",
+        "@babel/helper-split-export-declaration": "^7.4.4",
+        "@babel/parser": "^7.5.5",
+        "@babel/types": "^7.5.5",
+        "debug": "^4.1.0",
+        "globals": "^11.1.0",
+        "lodash": "^4.17.13"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "4.1.1",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+          "dev": true,
+          "requires": {
+            "ms": "^2.1.1"
+          }
+        },
+        "globals": {
+          "version": "11.12.0",
+          "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+          "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+          "dev": true
+        },
+        "ms": {
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+          "dev": true
+        }
+      }
+    },
+    "@babel/types": {
+      "version": "7.5.5",
+      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.5.5.tgz",
+      "integrity": "sha512-s63F9nJioLqOlW3UkyMd+BYhXt44YuaFm/VV0VwuteqjYwRrObkU7ra9pY4wAJR3oXi8hJrMcrcJdO/HH33vtw==",
+      "dev": true,
+      "requires": {
+        "esutils": "^2.0.2",
+        "lodash": "^4.17.13",
+        "to-fast-properties": "^2.0.0"
+      },
+      "dependencies": {
+        "to-fast-properties": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
+          "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
+          "dev": true
+        }
+      }
+    },
+    "@ng-bootstrap/ng-bootstrap": {
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/@ng-bootstrap/ng-bootstrap/-/ng-bootstrap-4.2.1.tgz",
+      "integrity": "sha512-7etP9X9jKIkbuDzU3ngI2jQhHQDZxIu0ErvlkHb7u7YH9akIOLVkXvz2mTMvcFABWZhze64UjFuEgR46b6WGSw==",
+      "requires": {
+        "tslib": "^1.9.0"
+      }
+    },
+    "@ngtools/webpack": {
+      "version": "7.0.7",
+      "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-7.0.7.tgz",
+      "integrity": "sha512-ukZv/8vhiVWLsEEWF1uena8GHRVUpwbPJ+8AupW25d2nNpwfsDtTIXKzTzRYeIQFFCnHJxr04lK18CVsn1lFaQ==",
+      "dev": true,
+      "requires": {
+        "@angular-devkit/core": "7.0.7",
+        "enhanced-resolve": "4.1.0",
+        "rxjs": "6.3.3",
+        "tree-kill": "1.2.0",
+        "webpack-sources": "1.2.0"
+      }
+    },
+    "@schematics/angular": {
+      "version": "7.0.7",
+      "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-7.0.7.tgz",
+      "integrity": "sha512-xDSMAtOdKNa5uqsEfbwBVHVCjpNSmIIcadi0Rki+5Nmobf5nnQWPly1/xj5aHzT6SKuV4BIMvsBG9UgI9Ss/Iw==",
+      "dev": true,
+      "requires": {
+        "@angular-devkit/core": "7.0.7",
+        "@angular-devkit/schematics": "7.0.7",
+        "typescript": "3.1.6"
+      }
+    },
+    "@schematics/update": {
+      "version": "0.10.7",
+      "resolved": "https://registry.npmjs.org/@schematics/update/-/update-0.10.7.tgz",
+      "integrity": "sha512-E4txrdnIcNn1K0xFPmY4ywAnVj+hN2QB1wBijoAMezYTEjcKxW0g6thPfUv6qhIPcphxrCOqwl6cIELZjq2dtA==",
+      "dev": true,
+      "requires": {
+        "@angular-devkit/core": "7.0.7",
+        "@angular-devkit/schematics": "7.0.7",
+        "npm-registry-client": "8.6.0",
+        "rxjs": "6.3.3",
+        "semver": "5.5.1",
+        "semver-intersect": "1.4.0"
+      }
+    },
+    "@types/jasmine": {
+      "version": "2.8.16",
+      "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-2.8.16.tgz",
+      "integrity": "sha512-056oRlBBp7MDzr+HoU5su099s/s7wjZ3KcHxLfv+Byqb9MwdLUvsfLgw1VS97hsh3ddxSPyQu+olHMnoVTUY6g==",
+      "dev": true
+    },
+    "@types/jasminewd2": {
+      "version": "2.0.6",
+      "resolved": "https://registry.npmjs.org/@types/jasminewd2/-/jasminewd2-2.0.6.tgz",
+      "integrity": "sha512-2ZOKrxb8bKRmP/po5ObYnRDgFE4i+lQiEB27bAMmtMWLgJSqlIDqlLx6S0IRorpOmOPRQ6O80NujTmQAtBkeNw==",
+      "dev": true,
+      "requires": {
+        "@types/jasmine": "*"
+      }
+    },
+    "@types/jquery": {
+      "version": "3.3.31",
+      "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.3.31.tgz",
+      "integrity": "sha512-Lz4BAJihoFw5nRzKvg4nawXPzutkv7wmfQ5121avptaSIXlDNJCUuxZxX/G+9EVidZGuO0UBlk+YjKbwRKJigg==",
+      "requires": {
+        "@types/sizzle": "*"
+      }
+    },
+    "@types/node": {
+      "version": "8.9.5",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-8.9.5.tgz",
+      "integrity": "sha512-jRHfWsvyMtXdbhnz5CVHxaBgnV6duZnPlQuRSo/dm/GnmikNcmZhxIES4E9OZjUmQ8C+HCl4KJux+cXN/ErGDQ=="
+    },
+    "@types/q": {
+      "version": "0.0.32",
+      "resolved": "https://registry.npmjs.org/@types/q/-/q-0.0.32.tgz",
+      "integrity": "sha1-vShOV8hPEyXacCur/IKlMoGQwMU=",
+      "dev": true
+    },
+    "@types/selenium-webdriver": {
+      "version": "3.0.16",
+      "resolved": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-3.0.16.tgz",
+      "integrity": "sha512-lMC2G0ItF2xv4UCiwbJGbnJlIuUixHrioOhNGHSCsYCJ8l4t9hMCUimCytvFv7qy6AfSzRxhRHoGa+UqaqwyeA==",
+      "dev": true
+    },
+    "@types/sizzle": {
+      "version": "2.3.2",
+      "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.2.tgz",
+      "integrity": "sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg=="
+    },
+    "@types/underscore": {
+      "version": "1.9.3",
+      "resolved": "https://registry.npmjs.org/@types/underscore/-/underscore-1.9.3.tgz",
+      "integrity": "sha512-SwbHKB2DPIDlvYqtK5O+0LFtZAyrUSw4c0q+HWwmH1Ve3KMQ0/5PlV3RX97+3dP7yMrnNQ8/bCWWvQpPl03Mug=="
+    },
+    "@types/uuid": {
+      "version": "3.4.5",
+      "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-3.4.5.tgz",
+      "integrity": "sha512-MNL15wC3EKyw1VLF+RoVO4hJJdk9t/Hlv3rt1OL65Qvuadm4BYo6g9ZJQqoq7X8NBFSsQXgAujWciovh2lpVjA==",
+      "requires": {
+        "@types/node": "*"
+      }
+    },
+    "@webassemblyjs/ast": {
+      "version": "1.7.6",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.7.6.tgz",
+      "integrity": "sha512-8nkZS48EVsMUU0v6F1LCIOw4RYWLm2plMtbhFTjNgeXmsTNLuU3xTRtnljt9BFQB+iPbLRobkNrCWftWnNC7wQ==",
+      "dev": true,
+      "requires": {
+        "@webassemblyjs/helper-module-context": "1.7.6",
+        "@webassemblyjs/helper-wasm-bytecode": "1.7.6",
+        "@webassemblyjs/wast-parser": "1.7.6",
+        "mamacro": "^0.0.3"
+      }
+    },
+    "@webassemblyjs/floating-point-hex-parser": {
+      "version": "1.7.6",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.7.6.tgz",
+      "integrity": "sha512-VBOZvaOyBSkPZdIt5VBMg3vPWxouuM13dPXGWI1cBh3oFLNcFJ8s9YA7S9l4mPI7+Q950QqOmqj06oa83hNWBA==",
+      "dev": true
+    },
+    "@webassemblyjs/helper-api-error": {
+      "version": "1.7.6",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.7.6.tgz",
+      "integrity": "sha512-SCzhcQWHXfrfMSKcj8zHg1/kL9kb3aa5TN4plc/EREOs5Xop0ci5bdVBApbk2yfVi8aL+Ly4Qpp3/TRAUInjrg==",
+      "dev": true
+    },
+    "@webassemblyjs/helper-buffer": {
+      "version": "1.7.6",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.7.6.tgz",
+      "integrity": "sha512-1/gW5NaGsEOZ02fjnFiU8/OEEXU1uVbv2um0pQ9YVL3IHSkyk6xOwokzyqqO1qDZQUAllb+V8irtClPWntbVqw==",
+      "dev": true
+    },
+    "@webassemblyjs/helper-code-frame": {
+      "version": "1.7.6",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.7.6.tgz",
+      "integrity": "sha512-+suMJOkSn9+vEvDvgyWyrJo5vJsWSDXZmJAjtoUq4zS4eqHyXImpktvHOZwXp1XQjO5H+YQwsBgqTQEc0J/5zg==",
+      "dev": true,
+      "requires": {
+        "@webassemblyjs/wast-printer": "1.7.6"
+      }
+    },
+    "@webassemblyjs/helper-fsm": {
+      "version": "1.7.6",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.7.6.tgz",
+      "integrity": "sha512-HCS6KN3wgxUihGBW7WFzEC/o8Eyvk0d56uazusnxXthDPnkWiMv+kGi9xXswL2cvfYfeK5yiM17z2K5BVlwypw==",
+      "dev": true
+    },
+    "@webassemblyjs/helper-module-context": {
+      "version": "1.7.6",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.7.6.tgz",
+      "integrity": "sha512-e8/6GbY7OjLM+6OsN7f2krC2qYVNaSr0B0oe4lWdmq5sL++8dYDD1TFbD1TdAdWMRTYNr/Qq7ovXWzia2EbSjw==",
+      "dev": true,
+      "requires": {
+        "mamacro": "^0.0.3"
+      }
+    },
+    "@webassemblyjs/helper-wasm-bytecode": {
+      "version": "1.7.6",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.7.6.tgz",
+      "integrity": "sha512-PzYFCb7RjjSdAOljyvLWVqd6adAOabJW+8yRT+NWhXuf1nNZWH+igFZCUK9k7Cx7CsBbzIfXjJc7u56zZgFj9Q==",
+      "dev": true
+    },
+    "@webassemblyjs/helper-wasm-section": {
+      "version": "1.7.6",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.7.6.tgz",
+      "integrity": "sha512-3GS628ppDPSuwcYlQ7cDCGr4W2n9c4hLzvnRKeuz+lGsJSmc/ADVoYpm1ts2vlB1tGHkjtQMni+yu8mHoMlKlA==",
+      "dev": true,
+      "requires": {
+        "@webassemblyjs/ast": "1.7.6",
+        "@webassemblyjs/helper-buffer": "1.7.6",
+        "@webassemblyjs/helper-wasm-bytecode": "1.7.6",
+        "@webassemblyjs/wasm-gen": "1.7.6"
+      }
+    },
+    "@webassemblyjs/ieee754": {
+      "version": "1.7.6",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.7.6.tgz",
+      "integrity": "sha512-V4cIp0ruyw+hawUHwQLn6o2mFEw4t50tk530oKsYXQhEzKR+xNGDxs/SFFuyTO7X3NzEu4usA3w5jzhl2RYyzQ==",
+      "dev": true,
+      "requires": {
+        "@xtuc/ieee754": "^1.2.0"
+      }
+    },
+    "@webassemblyjs/leb128": {
+      "version": "1.7.6",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.7.6.tgz",
+      "integrity": "sha512-ojdlG8WpM394lBow4ncTGJoIVZ4aAtNOWHhfAM7m7zprmkVcKK+2kK5YJ9Bmj6/ketTtOn7wGSHCtMt+LzqgYQ==",
+      "dev": true,
+      "requires": {
+        "@xtuc/long": "4.2.1"
+      }
+    },
+    "@webassemblyjs/utf8": {
+      "version": "1.7.6",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.7.6.tgz",
+      "integrity": "sha512-oId+tLxQ+AeDC34ELRYNSqJRaScB0TClUU6KQfpB8rNT6oelYlz8axsPhf6yPTg7PBJ/Z5WcXmUYiHEWgbbHJw==",
+      "dev": true
+    },
+    "@webassemblyjs/wasm-edit": {
+      "version": "1.7.6",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.7.6.tgz",
+      "integrity": "sha512-pTNjLO3o41v/Vz9VFLl+I3YLImpCSpodFW77pNoH4agn5I6GgSxXHXtvWDTvYJFty0jSeXZWLEmbaSIRUDlekg==",
+      "dev": true,
+      "requires": {
+        "@webassemblyjs/ast": "1.7.6",
+        "@webassemblyjs/helper-buffer": "1.7.6",
+        "@webassemblyjs/helper-wasm-bytecode": "1.7.6",
+        "@webassemblyjs/helper-wasm-section": "1.7.6",
+        "@webassemblyjs/wasm-gen": "1.7.6",
+        "@webassemblyjs/wasm-opt": "1.7.6",
+        "@webassemblyjs/wasm-parser": "1.7.6",
+        "@webassemblyjs/wast-printer": "1.7.6"
+      }
+    },
+    "@webassemblyjs/wasm-gen": {
+      "version": "1.7.6",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.7.6.tgz",
+      "integrity": "sha512-mQvFJVumtmRKEUXMohwn8nSrtjJJl6oXwF3FotC5t6e2hlKMh8sIaW03Sck2MDzw9xPogZD7tdP5kjPlbH9EcQ==",
+      "dev": true,
+      "requires": {
+        "@webassemblyjs/ast": "1.7.6",
+        "@webassemblyjs/helper-wasm-bytecode": "1.7.6",
+        "@webassemblyjs/ieee754": "1.7.6",
+        "@webassemblyjs/leb128": "1.7.6",
+        "@webassemblyjs/utf8": "1.7.6"
+      }
+    },
+    "@webassemblyjs/wasm-opt": {
+      "version": "1.7.6",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.7.6.tgz",
+      "integrity": "sha512-go44K90fSIsDwRgtHhX14VtbdDPdK2sZQtZqUcMRvTojdozj5tLI0VVJAzLCfz51NOkFXezPeVTAYFqrZ6rI8Q==",
+      "dev": true,
+      "requires": {
+        "@webassemblyjs/ast": "1.7.6",
+        "@webassemblyjs/helper-buffer": "1.7.6",
+        "@webassemblyjs/wasm-gen": "1.7.6",
+        "@webassemblyjs/wasm-parser": "1.7.6"
+      }
+    },
+    "@webassemblyjs/wasm-parser": {
+      "version": "1.7.6",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.7.6.tgz",
+      "integrity": "sha512-t1T6TfwNY85pDA/HWPA8kB9xA4sp9ajlRg5W7EKikqrynTyFo+/qDzIpvdkOkOGjlS6d4n4SX59SPuIayR22Yg==",
+      "dev": true,
+      "requires": {
+        "@webassemblyjs/ast": "1.7.6",
+        "@webassemblyjs/helper-api-error": "1.7.6",
+        "@webassemblyjs/helper-wasm-bytecode": "1.7.6",
+        "@webassemblyjs/ieee754": "1.7.6",
+        "@webassemblyjs/leb128": "1.7.6",
+        "@webassemblyjs/utf8": "1.7.6"
+      }
+    },
+    "@webassemblyjs/wast-parser": {
+      "version": "1.7.6",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.7.6.tgz",
+      "integrity": "sha512-1MaWTErN0ziOsNUlLdvwS+NS1QWuI/kgJaAGAMHX8+fMJFgOJDmN/xsG4h/A1Gtf/tz5VyXQciaqHZqp2q0vfg==",
+      "dev": true,
+      "requires": {
+        "@webassemblyjs/ast": "1.7.6",
+        "@webassemblyjs/floating-point-hex-parser": "1.7.6",
+        "@webassemblyjs/helper-api-error": "1.7.6",
+        "@webassemblyjs/helper-code-frame": "1.7.6",
+        "@webassemblyjs/helper-fsm": "1.7.6",
+        "@xtuc/long": "4.2.1",
+        "mamacro": "^0.0.3"
+      }
+    },
+    "@webassemblyjs/wast-printer": {
+      "version": "1.7.6",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.7.6.tgz",
+      "integrity": "sha512-vHdHSK1tOetvDcl1IV1OdDeGNe/NDDQ+KzuZHMtqTVP1xO/tZ/IKNpj5BaGk1OYFdsDWQqb31PIwdEyPntOWRQ==",
+      "dev": true,
+      "requires": {
+        "@webassemblyjs/ast": "1.7.6",
+        "@webassemblyjs/wast-parser": "1.7.6",
+        "@xtuc/long": "4.2.1"
+      }
+    },
+    "@xtuc/ieee754": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
+      "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==",
+      "dev": true
+    },
+    "@xtuc/long": {
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.1.tgz",
+      "integrity": "sha512-FZdkNBDqBRHKQ2MEbSC17xnPFOhZxeJ2YGSfr2BKf3sujG49Qe3bB+rGCwQfIaA7WHnGeGkSijX4FuBCdrzW/g==",
+      "dev": true
+    },
+    "abbrev": {
+      "version": "1.0.9",
+      "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz",
+      "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=",
+      "dev": true
+    },
+    "abs-components-bc": {
+      "version": "file:abs-components-bc-1.0.7.tgz",
+      "integrity": "sha512-2Lt/+dTQG8/YMVNcqSCpjy37Ns1WQKRCJ9ihUJzIDTk/7hgOFT7bS5xD7sPPUNZAz0KJfSwj2tCgigLf29sFSQ==",
+      "requires": {
+        "tslib": "^1.7.1"
+      }
+    },
+    "accepts": {
+      "version": "1.3.7",
+      "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
+      "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
+      "dev": true,
+      "requires": {
+        "mime-types": "~2.1.24",
+        "negotiator": "0.6.2"
+      }
+    },
+    "acorn": {
+      "version": "5.7.3",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz",
+      "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==",
+      "dev": true
+    },
+    "acorn-dynamic-import": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz",
+      "integrity": "sha512-zVWV8Z8lislJoOKKqdNMOB+s6+XV5WERty8MnKBeFgwA+19XJjJHs2RP5dzM57FftIs+jQnRToLiWazKr6sSWg==",
+      "dev": true,
+      "requires": {
+        "acorn": "^5.0.0"
+      }
+    },
+    "adm-zip": {
+      "version": "0.4.13",
+      "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.13.tgz",
+      "integrity": "sha512-fERNJX8sOXfel6qCBCMPvZLzENBEhZTzKqg6vrOW5pvoEaQuJhRU4ndTAh6lHOxn1I6jnz2NHra56ZODM751uw==",
+      "dev": true
+    },
+    "after": {
+      "version": "0.8.2",
+      "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz",
+      "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=",
+      "dev": true
+    },
+    "agent-base": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz",
+      "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==",
+      "dev": true,
+      "requires": {
+        "es6-promisify": "^5.0.0"
+      }
+    },
+    "ajv": {
+      "version": "6.5.3",
+      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.3.tgz",
+      "integrity": "sha512-LqZ9wY+fx3UMiiPd741yB2pj3hhil+hQc8taf4o2QGRFpWgZ2V5C8HA165DY9sS3fJwsk7uT7ZlFEyC3Ig3lLg==",
+      "dev": true,
+      "requires": {
+        "fast-deep-equal": "^2.0.1",
+        "fast-json-stable-stringify": "^2.0.0",
+        "json-schema-traverse": "^0.4.1",
+        "uri-js": "^4.2.2"
+      }
+    },
+    "ajv-errors": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz",
+      "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==",
+      "dev": true
+    },
+    "ajv-keywords": {
+      "version": "3.4.1",
+      "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz",
+      "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==",
+      "dev": true
+    },
+    "amdefine": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
+      "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=",
+      "dev": true
+    },
+    "angular-gridster2": {
+      "version": "8.0.0",
+      "resolved": "https://registry.npmjs.org/angular-gridster2/-/angular-gridster2-8.0.0.tgz",
+      "integrity": "sha512-mSgOvRfhEKAERU63SsunI/NWajU2wXVTToR6sA5JM1sRptK6PLoAIi9VqcNETTmdRssflOFwJJqBqEeRgelUvg==",
+      "requires": {
+        "tslib": "^1.9.0"
+      }
+    },
+    "angular2-uuid": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/angular2-uuid/-/angular2-uuid-1.1.1.tgz",
+      "integrity": "sha1-cvA81TK39AAy6x7PufhFc4S+lW4="
+    },
+    "ansi-colors": {
+      "version": "3.2.4",
+      "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz",
+      "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==",
+      "dev": true
+    },
+    "ansi-escapes": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz",
+      "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==",
+      "dev": true
+    },
+    "ansi-html": {
+      "version": "0.0.7",
+      "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz",
+      "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=",
+      "dev": true
+    },
+    "ansi-regex": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+      "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+      "dev": true
+    },
+    "ansi-styles": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+      "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+      "dev": true,
+      "requires": {
+        "color-convert": "^1.9.0"
+      }
+    },
+    "anymatch": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
+      "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
+      "dev": true,
+      "requires": {
+        "micromatch": "^3.1.4",
+        "normalize-path": "^2.1.1"
+      }
+    },
+    "app-root-path": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-2.2.1.tgz",
+      "integrity": "sha512-91IFKeKk7FjfmezPKkwtaRvSpnUc4gDwPAjA1YZ9Gn0q0PPeW+vbeUsZuyDwjI7+QTHhcLen2v25fi/AmhvbJA==",
+      "dev": true
+    },
+    "append-transform": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz",
+      "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==",
+      "dev": true,
+      "requires": {
+        "default-require-extensions": "^2.0.0"
+      }
+    },
+    "aproba": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+      "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
+      "dev": true
+    },
+    "are-we-there-yet": {
+      "version": "1.1.5",
+      "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
+      "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
+      "dev": true,
+      "requires": {
+        "delegates": "^1.0.0",
+        "readable-stream": "^2.0.6"
+      }
+    },
+    "argparse": {
+      "version": "1.0.10",
+      "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+      "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+      "dev": true,
+      "requires": {
+        "sprintf-js": "~1.0.2"
+      }
+    },
+    "arr-diff": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
+      "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=",
+      "dev": true
+    },
+    "arr-flatten": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
+      "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==",
+      "dev": true
+    },
+    "arr-union": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
+      "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=",
+      "dev": true
+    },
+    "array-find-index": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
+      "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=",
+      "dev": true
+    },
+    "array-flatten": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz",
+      "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==",
+      "dev": true
+    },
+    "array-slice": {
+      "version": "0.2.3",
+      "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz",
+      "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=",
+      "dev": true
+    },
+    "array-union": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
+      "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
+      "dev": true,
+      "requires": {
+        "array-uniq": "^1.0.1"
+      }
+    },
+    "array-uniq": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
+      "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=",
+      "dev": true
+    },
+    "array-unique": {
+      "version": "0.3.2",
+      "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
+      "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
+      "dev": true
+    },
+    "arraybuffer.slice": {
+      "version": "0.0.7",
+      "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz",
+      "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==",
+      "dev": true
+    },
+    "arrify": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
+      "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
+      "dev": true
+    },
+    "asap": {
+      "version": "2.0.6",
+      "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
+      "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=",
+      "dev": true,
+      "optional": true
+    },
+    "asn1": {
+      "version": "0.2.4",
+      "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
+      "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
+      "dev": true,
+      "requires": {
+        "safer-buffer": "~2.1.0"
+      }
+    },
+    "asn1.js": {
+      "version": "4.10.1",
+      "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz",
+      "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==",
+      "dev": true,
+      "requires": {
+        "bn.js": "^4.0.0",
+        "inherits": "^2.0.1",
+        "minimalistic-assert": "^1.0.0"
+      }
+    },
+    "assert": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz",
+      "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==",
+      "dev": true,
+      "requires": {
+        "object-assign": "^4.1.1",
+        "util": "0.10.3"
+      },
+      "dependencies": {
+        "inherits": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
+          "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=",
+          "dev": true
+        },
+        "util": {
+          "version": "0.10.3",
+          "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz",
+          "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=",
+          "dev": true,
+          "requires": {
+            "inherits": "2.0.1"
+          }
+        }
+      }
+    },
+    "assert-plus": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+      "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
+      "dev": true
+    },
+    "assign-symbols": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
+      "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=",
+      "dev": true
+    },
+    "async": {
+      "version": "1.5.2",
+      "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
+      "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
+      "dev": true
+    },
+    "async-each": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz",
+      "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==",
+      "dev": true
+    },
+    "async-foreach": {
+      "version": "0.1.3",
+      "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz",
+      "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=",
+      "dev": true,
+      "optional": true
+    },
+    "async-limiter": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
+      "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==",
+      "dev": true
+    },
+    "asynckit": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+      "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
+      "dev": true
+    },
+    "atob": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
+      "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
+      "dev": true
+    },
+    "autoprefixer": {
+      "version": "9.1.5",
+      "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.1.5.tgz",
+      "integrity": "sha512-kk4Zb6RUc58ld7gdosERHMF3DzIYJc2fp5sX46qEsGXQQy5bXsu8qyLjoxuY1NuQ/cJuCYnx99BfjwnRggrYIw==",
+      "dev": true,
+      "requires": {
+        "browserslist": "^4.1.0",
+        "caniuse-lite": "^1.0.30000884",
+        "normalize-range": "^0.1.2",
+        "num2fraction": "^1.2.2",
+        "postcss": "^7.0.2",
+        "postcss-value-parser": "^3.2.3"
+      }
+    },
+    "aws-sign2": {
+      "version": "0.7.0",
+      "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
+      "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
+      "dev": true
+    },
+    "aws4": {
+      "version": "1.8.0",
+      "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
+      "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==",
+      "dev": true
+    },
+    "babel-code-frame": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
+      "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
+      "dev": true,
+      "requires": {
+        "chalk": "^1.1.3",
+        "esutils": "^2.0.2",
+        "js-tokens": "^3.0.2"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "2.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+          "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+          "dev": true
+        },
+        "chalk": {
+          "version": "1.1.3",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^2.2.1",
+            "escape-string-regexp": "^1.0.2",
+            "has-ansi": "^2.0.0",
+            "strip-ansi": "^3.0.0",
+            "supports-color": "^2.0.0"
+          }
+        },
+        "supports-color": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+          "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+          "dev": true
+        }
+      }
+    },
+    "babel-generator": {
+      "version": "6.26.1",
+      "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz",
+      "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==",
+      "dev": true,
+      "requires": {
+        "babel-messages": "^6.23.0",
+        "babel-runtime": "^6.26.0",
+        "babel-types": "^6.26.0",
+        "detect-indent": "^4.0.0",
+        "jsesc": "^1.3.0",
+        "lodash": "^4.17.4",
+        "source-map": "^0.5.7",
+        "trim-right": "^1.0.1"
+      },
+      "dependencies": {
+        "source-map": {
+          "version": "0.5.7",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+          "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+          "dev": true
+        }
+      }
+    },
+    "babel-messages": {
+      "version": "6.23.0",
+      "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz",
+      "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=",
+      "dev": true,
+      "requires": {
+        "babel-runtime": "^6.22.0"
+      }
+    },
+    "babel-runtime": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
+      "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
+      "dev": true,
+      "requires": {
+        "core-js": "^2.4.0",
+        "regenerator-runtime": "^0.11.0"
+      }
+    },
+    "babel-template": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz",
+      "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=",
+      "dev": true,
+      "requires": {
+        "babel-runtime": "^6.26.0",
+        "babel-traverse": "^6.26.0",
+        "babel-types": "^6.26.0",
+        "babylon": "^6.18.0",
+        "lodash": "^4.17.4"
+      }
+    },
+    "babel-traverse": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz",
+      "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=",
+      "dev": true,
+      "requires": {
+        "babel-code-frame": "^6.26.0",
+        "babel-messages": "^6.23.0",
+        "babel-runtime": "^6.26.0",
+        "babel-types": "^6.26.0",
+        "babylon": "^6.18.0",
+        "debug": "^2.6.8",
+        "globals": "^9.18.0",
+        "invariant": "^2.2.2",
+        "lodash": "^4.17.4"
+      }
+    },
+    "babel-types": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz",
+      "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=",
+      "dev": true,
+      "requires": {
+        "babel-runtime": "^6.26.0",
+        "esutils": "^2.0.2",
+        "lodash": "^4.17.4",
+        "to-fast-properties": "^1.0.3"
+      }
+    },
+    "babylon": {
+      "version": "6.18.0",
+      "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz",
+      "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==",
+      "dev": true
+    },
+    "backo2": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz",
+      "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=",
+      "dev": true
+    },
+    "balanced-match": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+      "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
+      "dev": true
+    },
+    "base": {
+      "version": "0.11.2",
+      "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
+      "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==",
+      "dev": true,
+      "requires": {
+        "cache-base": "^1.0.1",
+        "class-utils": "^0.3.5",
+        "component-emitter": "^1.2.1",
+        "define-property": "^1.0.0",
+        "isobject": "^3.0.1",
+        "mixin-deep": "^1.2.0",
+        "pascalcase": "^0.1.1"
+      },
+      "dependencies": {
+        "define-property": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+          "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+          "dev": true,
+          "requires": {
+            "is-descriptor": "^1.0.0"
+          }
+        },
+        "is-accessor-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+          "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+          "dev": true,
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-data-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+          "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+          "dev": true,
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-descriptor": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+          "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+          "dev": true,
+          "requires": {
+            "is-accessor-descriptor": "^1.0.0",
+            "is-data-descriptor": "^1.0.0",
+            "kind-of": "^6.0.2"
+          }
+        }
+      }
+    },
+    "base64-arraybuffer": {
+      "version": "0.1.5",
+      "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz",
+      "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=",
+      "dev": true
+    },
+    "base64-js": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz",
+      "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==",
+      "dev": true
+    },
+    "base64id": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz",
+      "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=",
+      "dev": true
+    },
+    "batch": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
+      "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=",
+      "dev": true
+    },
+    "bcrypt-pbkdf": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
+      "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
+      "dev": true,
+      "requires": {
+        "tweetnacl": "^0.14.3"
+      }
+    },
+    "better-assert": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz",
+      "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=",
+      "dev": true,
+      "requires": {
+        "callsite": "1.0.0"
+      }
+    },
+    "big.js": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz",
+      "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==",
+      "dev": true
+    },
+    "binary-extensions": {
+      "version": "1.13.1",
+      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz",
+      "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==",
+      "dev": true
+    },
+    "blob": {
+      "version": "0.0.5",
+      "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz",
+      "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==",
+      "dev": true
+    },
+    "block-stream": {
+      "version": "0.0.9",
+      "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
+      "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "inherits": "~2.0.0"
+      }
+    },
+    "blocking-proxy": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/blocking-proxy/-/blocking-proxy-1.0.1.tgz",
+      "integrity": "sha512-KE8NFMZr3mN2E0HcvCgRtX7DjhiIQrwle+nSVJVC/yqFb9+xznHl2ZcoBp2L9qzkI4t4cBFJ1efXF8Dwi132RA==",
+      "dev": true,
+      "requires": {
+        "minimist": "^1.2.0"
+      },
+      "dependencies": {
+        "minimist": {
+          "version": "1.2.0",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+          "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+          "dev": true
+        }
+      }
+    },
+    "bluebird": {
+      "version": "3.5.5",
+      "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.5.tgz",
+      "integrity": "sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==",
+      "dev": true
+    },
+    "bn.js": {
+      "version": "4.11.8",
+      "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz",
+      "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==",
+      "dev": true
+    },
+    "body-parser": {
+      "version": "1.19.0",
+      "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
+      "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
+      "dev": true,
+      "requires": {
+        "bytes": "3.1.0",
+        "content-type": "~1.0.4",
+        "debug": "2.6.9",
+        "depd": "~1.1.2",
+        "http-errors": "1.7.2",
+        "iconv-lite": "0.4.24",
+        "on-finished": "~2.3.0",
+        "qs": "6.7.0",
+        "raw-body": "2.4.0",
+        "type-is": "~1.6.17"
+      },
+      "dependencies": {
+        "bytes": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
+          "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==",
+          "dev": true
+        },
+        "qs": {
+          "version": "6.7.0",
+          "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
+          "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==",
+          "dev": true
+        }
+      }
+    },
+    "bonjour": {
+      "version": "3.5.0",
+      "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz",
+      "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=",
+      "dev": true,
+      "requires": {
+        "array-flatten": "^2.1.0",
+        "deep-equal": "^1.0.1",
+        "dns-equal": "^1.0.0",
+        "dns-txt": "^2.0.2",
+        "multicast-dns": "^6.0.1",
+        "multicast-dns-service-types": "^1.1.0"
+      }
+    },
+    "brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "dev": true,
+      "requires": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
+    "braces": {
+      "version": "2.3.2",
+      "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
+      "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+      "dev": true,
+      "requires": {
+        "arr-flatten": "^1.1.0",
+        "array-unique": "^0.3.2",
+        "extend-shallow": "^2.0.1",
+        "fill-range": "^4.0.0",
+        "isobject": "^3.0.1",
+        "repeat-element": "^1.1.2",
+        "snapdragon": "^0.8.1",
+        "snapdragon-node": "^2.0.1",
+        "split-string": "^3.0.2",
+        "to-regex": "^3.0.1"
+      },
+      "dependencies": {
+        "extend-shallow": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+          "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+          "dev": true,
+          "requires": {
+            "is-extendable": "^0.1.0"
+          }
+        }
+      }
+    },
+    "brorand": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
+      "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=",
+      "dev": true
+    },
+    "browserify-aes": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
+      "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==",
+      "dev": true,
+      "requires": {
+        "buffer-xor": "^1.0.3",
+        "cipher-base": "^1.0.0",
+        "create-hash": "^1.1.0",
+        "evp_bytestokey": "^1.0.3",
+        "inherits": "^2.0.1",
+        "safe-buffer": "^5.0.1"
+      }
+    },
+    "browserify-cipher": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz",
+      "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==",
+      "dev": true,
+      "requires": {
+        "browserify-aes": "^1.0.4",
+        "browserify-des": "^1.0.0",
+        "evp_bytestokey": "^1.0.0"
+      }
+    },
+    "browserify-des": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz",
+      "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==",
+      "dev": true,
+      "requires": {
+        "cipher-base": "^1.0.1",
+        "des.js": "^1.0.0",
+        "inherits": "^2.0.1",
+        "safe-buffer": "^5.1.2"
+      }
+    },
+    "browserify-rsa": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
+      "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
+      "dev": true,
+      "requires": {
+        "bn.js": "^4.1.0",
+        "randombytes": "^2.0.1"
+      }
+    },
+    "browserify-sign": {
+      "version": "4.0.4",
+      "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz",
+      "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=",
+      "dev": true,
+      "requires": {
+        "bn.js": "^4.1.1",
+        "browserify-rsa": "^4.0.0",
+        "create-hash": "^1.1.0",
+        "create-hmac": "^1.1.2",
+        "elliptic": "^6.0.0",
+        "inherits": "^2.0.1",
+        "parse-asn1": "^5.0.0"
+      }
+    },
+    "browserify-zlib": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz",
+      "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==",
+      "dev": true,
+      "requires": {
+        "pako": "~1.0.5"
+      }
+    },
+    "browserslist": {
+      "version": "4.6.6",
+      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.6.6.tgz",
+      "integrity": "sha512-D2Nk3W9JL9Fp/gIcWei8LrERCS+eXu9AM5cfXA8WEZ84lFks+ARnZ0q/R69m2SV3Wjma83QDDPxsNKXUwdIsyA==",
+      "dev": true,
+      "requires": {
+        "caniuse-lite": "^1.0.30000984",
+        "electron-to-chromium": "^1.3.191",
+        "node-releases": "^1.1.25"
+      }
+    },
+    "browserstack": {
+      "version": "1.5.2",
+      "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.5.2.tgz",
+      "integrity": "sha512-+6AFt9HzhKykcPF79W6yjEUJcdvZOV0lIXdkORXMJftGrDl0OKWqRF4GHqpDNkxiceDT/uB7Fb/aDwktvXX7dg==",
+      "dev": true,
+      "requires": {
+        "https-proxy-agent": "^2.2.1"
+      }
+    },
+    "buffer": {
+      "version": "4.9.1",
+      "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
+      "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=",
+      "dev": true,
+      "requires": {
+        "base64-js": "^1.0.2",
+        "ieee754": "^1.1.4",
+        "isarray": "^1.0.0"
+      }
+    },
+    "buffer-alloc": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz",
+      "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==",
+      "dev": true,
+      "requires": {
+        "buffer-alloc-unsafe": "^1.1.0",
+        "buffer-fill": "^1.0.0"
+      }
+    },
+    "buffer-alloc-unsafe": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz",
+      "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==",
+      "dev": true
+    },
+    "buffer-fill": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz",
+      "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=",
+      "dev": true
+    },
+    "buffer-from": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
+      "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
+      "dev": true
+    },
+    "buffer-indexof": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz",
+      "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==",
+      "dev": true
+    },
+    "buffer-xor": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
+      "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=",
+      "dev": true
+    },
+    "builtin-modules": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
+      "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
+      "dev": true
+    },
+    "builtin-status-codes": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz",
+      "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=",
+      "dev": true
+    },
+    "builtins": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz",
+      "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=",
+      "dev": true
+    },
+    "bytes": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
+      "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=",
+      "dev": true
+    },
+    "cacache": {
+      "version": "10.0.4",
+      "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz",
+      "integrity": "sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==",
+      "dev": true,
+      "requires": {
+        "bluebird": "^3.5.1",
+        "chownr": "^1.0.1",
+        "glob": "^7.1.2",
+        "graceful-fs": "^4.1.11",
+        "lru-cache": "^4.1.1",
+        "mississippi": "^2.0.0",
+        "mkdirp": "^0.5.1",
+        "move-concurrently": "^1.0.1",
+        "promise-inflight": "^1.0.1",
+        "rimraf": "^2.6.2",
+        "ssri": "^5.2.4",
+        "unique-filename": "^1.1.0",
+        "y18n": "^4.0.0"
+      }
+    },
+    "cache-base": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
+      "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==",
+      "dev": true,
+      "requires": {
+        "collection-visit": "^1.0.0",
+        "component-emitter": "^1.2.1",
+        "get-value": "^2.0.6",
+        "has-value": "^1.0.0",
+        "isobject": "^3.0.1",
+        "set-value": "^2.0.0",
+        "to-object-path": "^0.3.0",
+        "union-value": "^1.0.0",
+        "unset-value": "^1.0.0"
+      }
+    },
+    "caller-callsite": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz",
+      "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=",
+      "dev": true,
+      "requires": {
+        "callsites": "^2.0.0"
+      }
+    },
+    "caller-path": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz",
+      "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=",
+      "dev": true,
+      "requires": {
+        "caller-callsite": "^2.0.0"
+      }
+    },
+    "callsite": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz",
+      "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=",
+      "dev": true
+    },
+    "callsites": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz",
+      "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=",
+      "dev": true
+    },
+    "camelcase": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
+      "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=",
+      "dev": true,
+      "optional": true
+    },
+    "camelcase-keys": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
+      "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "camelcase": "^2.0.0",
+        "map-obj": "^1.0.0"
+      }
+    },
+    "caniuse-lite": {
+      "version": "1.0.30000984",
+      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000984.tgz",
+      "integrity": "sha512-n5tKOjMaZ1fksIpQbjERuqCyfgec/m9pferkFQbLmWtqLUdmt12hNhjSwsmPdqeiG2NkITOQhr1VYIwWSAceiA==",
+      "dev": true
+    },
+    "canonical-path": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/canonical-path/-/canonical-path-1.0.0.tgz",
+      "integrity": "sha512-feylzsbDxi1gPZ1IjystzIQZagYYLvfKrSuygUCgf7z6x790VEzze5QEkdSV1U58RA7Hi0+v6fv4K54atOzATg==",
+      "dev": true
+    },
+    "caseless": {
+      "version": "0.12.0",
+      "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
+      "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
+      "dev": true
+    },
+    "chalk": {
+      "version": "2.4.2",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+      "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+      "dev": true,
+      "requires": {
+        "ansi-styles": "^3.2.1",
+        "escape-string-regexp": "^1.0.5",
+        "supports-color": "^5.3.0"
+      }
+    },
+    "chardet": {
+      "version": "0.7.0",
+      "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
+      "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
+      "dev": true
+    },
+    "chokidar": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz",
+      "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==",
+      "dev": true,
+      "requires": {
+        "anymatch": "^2.0.0",
+        "async-each": "^1.0.0",
+        "braces": "^2.3.0",
+        "fsevents": "^1.2.2",
+        "glob-parent": "^3.1.0",
+        "inherits": "^2.0.1",
+        "is-binary-path": "^1.0.0",
+        "is-glob": "^4.0.0",
+        "lodash.debounce": "^4.0.8",
+        "normalize-path": "^2.1.1",
+        "path-is-absolute": "^1.0.0",
+        "readdirp": "^2.0.0",
+        "upath": "^1.0.5"
+      }
+    },
+    "chownr": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.2.tgz",
+      "integrity": "sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A==",
+      "dev": true
+    },
+    "chrome-trace-event": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz",
+      "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==",
+      "dev": true,
+      "requires": {
+        "tslib": "^1.9.0"
+      }
+    },
+    "cipher-base": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
+      "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
+      "dev": true,
+      "requires": {
+        "inherits": "^2.0.1",
+        "safe-buffer": "^5.0.1"
+      }
+    },
+    "circular-dependency-plugin": {
+      "version": "5.0.2",
+      "resolved": "https://registry.npmjs.org/circular-dependency-plugin/-/circular-dependency-plugin-5.0.2.tgz",
+      "integrity": "sha512-oC7/DVAyfcY3UWKm0sN/oVoDedQDQiw/vIiAnuTWTpE5s0zWf7l3WY417Xw/Fbi/QbAjctAkxgMiS9P0s3zkmA==",
+      "dev": true
+    },
+    "circular-json": {
+      "version": "0.5.9",
+      "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz",
+      "integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==",
+      "dev": true
+    },
+    "class-utils": {
+      "version": "0.3.6",
+      "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
+      "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==",
+      "dev": true,
+      "requires": {
+        "arr-union": "^3.1.0",
+        "define-property": "^0.2.5",
+        "isobject": "^3.0.0",
+        "static-extend": "^0.1.1"
+      },
+      "dependencies": {
+        "define-property": {
+          "version": "0.2.5",
+          "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+          "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+          "dev": true,
+          "requires": {
+            "is-descriptor": "^0.1.0"
+          }
+        }
+      }
+    },
+    "classlist.js": {
+      "version": "1.1.20150312",
+      "resolved": "https://registry.npmjs.org/classlist.js/-/classlist.js-1.1.20150312.tgz",
+      "integrity": "sha1-HXCEL3Ai8I2awIbOaeWyUPLFd4k="
+    },
+    "clean-css": {
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz",
+      "integrity": "sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==",
+      "dev": true,
+      "requires": {
+        "source-map": "~0.6.0"
+      },
+      "dependencies": {
+        "source-map": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+          "dev": true
+        }
+      }
+    },
+    "cli-cursor": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
+      "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=",
+      "dev": true,
+      "requires": {
+        "restore-cursor": "^2.0.0"
+      }
+    },
+    "cli-width": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
+      "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=",
+      "dev": true
+    },
+    "cliui": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
+      "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=",
+      "dev": true,
+      "requires": {
+        "string-width": "^1.0.1",
+        "strip-ansi": "^3.0.1",
+        "wrap-ansi": "^2.0.0"
+      }
+    },
+    "clone": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
+      "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=",
+      "dev": true
+    },
+    "clone-deep": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-2.0.2.tgz",
+      "integrity": "sha512-SZegPTKjCgpQH63E+eN6mVEEPdQBOUzjyJm5Pora4lrwWRFS8I0QAxV/KD6vV/i0WuijHZWQC1fMsPEdxfdVCQ==",
+      "dev": true,
+      "requires": {
+        "for-own": "^1.0.0",
+        "is-plain-object": "^2.0.4",
+        "kind-of": "^6.0.0",
+        "shallow-clone": "^1.0.0"
+      }
+    },
+    "co": {
+      "version": "4.6.0",
+      "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+      "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
+      "dev": true
+    },
+    "code-point-at": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
+      "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
+      "dev": true
+    },
+    "codelyzer": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmjs.org/codelyzer/-/codelyzer-4.5.0.tgz",
+      "integrity": "sha512-oO6vCkjqsVrEsmh58oNlnJkRXuA30hF8cdNAQV9DytEalDwyOFRvHMnlKFzmOStNerOmPGZU9GAHnBo4tGvtiQ==",
+      "dev": true,
+      "requires": {
+        "app-root-path": "^2.1.0",
+        "css-selector-tokenizer": "^0.7.0",
+        "cssauron": "^1.4.0",
+        "semver-dsl": "^1.0.1",
+        "source-map": "^0.5.7",
+        "sprintf-js": "^1.1.1"
+      },
+      "dependencies": {
+        "source-map": {
+          "version": "0.5.7",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+          "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+          "dev": true
+        },
+        "sprintf-js": {
+          "version": "1.1.2",
+          "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz",
+          "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==",
+          "dev": true
+        }
+      }
+    },
+    "collection-visit": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
+      "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=",
+      "dev": true,
+      "requires": {
+        "map-visit": "^1.0.0",
+        "object-visit": "^1.0.0"
+      }
+    },
+    "color-convert": {
+      "version": "1.9.3",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+      "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+      "dev": true,
+      "requires": {
+        "color-name": "1.1.3"
+      }
+    },
+    "color-name": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+      "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+      "dev": true
+    },
+    "colors": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz",
+      "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=",
+      "dev": true
+    },
+    "combine-lists": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/combine-lists/-/combine-lists-1.0.1.tgz",
+      "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=",
+      "dev": true,
+      "requires": {
+        "lodash": "^4.5.0"
+      }
+    },
+    "combined-stream": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+      "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+      "dev": true,
+      "requires": {
+        "delayed-stream": "~1.0.0"
+      }
+    },
+    "commander": {
+      "version": "2.20.0",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz",
+      "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==",
+      "dev": true
+    },
+    "commondir": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
+      "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
+      "dev": true
+    },
+    "compare-versions": {
+      "version": "3.5.0",
+      "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.5.0.tgz",
+      "integrity": "sha512-hX+4kt2Rcwu+x1U0SsEFCn1quURjEjPEGH/cPBlpME/IidGimAdwfMU+B+xDr7et/KTR7VH2+ZqWGerv4NGs2w==",
+      "dev": true
+    },
+    "component-bind": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz",
+      "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=",
+      "dev": true
+    },
+    "component-emitter": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
+      "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==",
+      "dev": true
+    },
+    "component-inherit": {
+      "version": "0.0.3",
+      "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz",
+      "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=",
+      "dev": true
+    },
+    "compressible": {
+      "version": "2.0.17",
+      "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.17.tgz",
+      "integrity": "sha512-BGHeLCK1GV7j1bSmQQAi26X+GgWcTjLr/0tzSvMCl3LH1w1IJ4PFSPoV5316b30cneTziC+B1a+3OjoSUcQYmw==",
+      "dev": true,
+      "requires": {
+        "mime-db": ">= 1.40.0 < 2"
+      }
+    },
+    "compression": {
+      "version": "1.7.4",
+      "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz",
+      "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==",
+      "dev": true,
+      "requires": {
+        "accepts": "~1.3.5",
+        "bytes": "3.0.0",
+        "compressible": "~2.0.16",
+        "debug": "2.6.9",
+        "on-headers": "~1.0.2",
+        "safe-buffer": "5.1.2",
+        "vary": "~1.1.2"
+      }
+    },
+    "concat-map": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+      "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+      "dev": true
+    },
+    "concat-stream": {
+      "version": "1.6.2",
+      "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
+      "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
+      "dev": true,
+      "requires": {
+        "buffer-from": "^1.0.0",
+        "inherits": "^2.0.3",
+        "readable-stream": "^2.2.2",
+        "typedarray": "^0.0.6"
+      }
+    },
+    "connect": {
+      "version": "3.7.0",
+      "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz",
+      "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==",
+      "dev": true,
+      "requires": {
+        "debug": "2.6.9",
+        "finalhandler": "1.1.2",
+        "parseurl": "~1.3.3",
+        "utils-merge": "1.0.1"
+      }
+    },
+    "connect-history-api-fallback": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz",
+      "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==",
+      "dev": true
+    },
+    "console-browserify": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz",
+      "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=",
+      "dev": true,
+      "requires": {
+        "date-now": "^0.1.4"
+      }
+    },
+    "console-control-strings": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
+      "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
+      "dev": true
+    },
+    "constants-browserify": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz",
+      "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=",
+      "dev": true
+    },
+    "content-disposition": {
+      "version": "0.5.3",
+      "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
+      "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
+      "dev": true,
+      "requires": {
+        "safe-buffer": "5.1.2"
+      }
+    },
+    "content-type": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
+      "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
+      "dev": true
+    },
+    "convert-source-map": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz",
+      "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==",
+      "dev": true,
+      "requires": {
+        "safe-buffer": "~5.1.1"
+      }
+    },
+    "cookie": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
+      "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==",
+      "dev": true
+    },
+    "cookie-signature": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+      "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=",
+      "dev": true
+    },
+    "copy-concurrently": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz",
+      "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==",
+      "dev": true,
+      "requires": {
+        "aproba": "^1.1.1",
+        "fs-write-stream-atomic": "^1.0.8",
+        "iferr": "^0.1.5",
+        "mkdirp": "^0.5.1",
+        "rimraf": "^2.5.4",
+        "run-queue": "^1.0.0"
+      }
+    },
+    "copy-descriptor": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
+      "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=",
+      "dev": true
+    },
+    "copy-webpack-plugin": {
+      "version": "4.5.4",
+      "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-4.5.4.tgz",
+      "integrity": "sha512-0lstlEyj74OAtYMrDxlNZsU7cwFijAI3Ofz2fD6Mpo9r4xCv4yegfa3uHIKvZY1NSuOtE9nvG6TAhJ+uz9gDaQ==",
+      "dev": true,
+      "requires": {
+        "cacache": "^10.0.4",
+        "find-cache-dir": "^1.0.0",
+        "globby": "^7.1.1",
+        "is-glob": "^4.0.0",
+        "loader-utils": "^1.1.0",
+        "minimatch": "^3.0.4",
+        "p-limit": "^1.0.0",
+        "serialize-javascript": "^1.4.0"
+      }
+    },
+    "core-js": {
+      "version": "2.6.9",
+      "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.9.tgz",
+      "integrity": "sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A=="
+    },
+    "core-util-is": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+      "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
+      "dev": true
+    },
+    "cosmiconfig": {
+      "version": "5.2.1",
+      "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz",
+      "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==",
+      "dev": true,
+      "requires": {
+        "import-fresh": "^2.0.0",
+        "is-directory": "^0.3.1",
+        "js-yaml": "^3.13.1",
+        "parse-json": "^4.0.0"
+      },
+      "dependencies": {
+        "parse-json": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+          "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
+          "dev": true,
+          "requires": {
+            "error-ex": "^1.3.1",
+            "json-parse-better-errors": "^1.0.1"
+          }
+        }
+      }
+    },
+    "create-ecdh": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz",
+      "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==",
+      "dev": true,
+      "requires": {
+        "bn.js": "^4.1.0",
+        "elliptic": "^6.0.0"
+      }
+    },
+    "create-hash": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
+      "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
+      "dev": true,
+      "requires": {
+        "cipher-base": "^1.0.1",
+        "inherits": "^2.0.1",
+        "md5.js": "^1.3.4",
+        "ripemd160": "^2.0.1",
+        "sha.js": "^2.4.0"
+      }
+    },
+    "create-hmac": {
+      "version": "1.1.7",
+      "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
+      "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==",
+      "dev": true,
+      "requires": {
+        "cipher-base": "^1.0.3",
+        "create-hash": "^1.1.0",
+        "inherits": "^2.0.1",
+        "ripemd160": "^2.0.0",
+        "safe-buffer": "^5.0.1",
+        "sha.js": "^2.4.8"
+      }
+    },
+    "cross-spawn": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz",
+      "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "lru-cache": "^4.0.1",
+        "which": "^1.2.9"
+      }
+    },
+    "crypto-browserify": {
+      "version": "3.12.0",
+      "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz",
+      "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==",
+      "dev": true,
+      "requires": {
+        "browserify-cipher": "^1.0.0",
+        "browserify-sign": "^4.0.0",
+        "create-ecdh": "^4.0.0",
+        "create-hash": "^1.1.0",
+        "create-hmac": "^1.1.0",
+        "diffie-hellman": "^5.0.0",
+        "inherits": "^2.0.1",
+        "pbkdf2": "^3.0.3",
+        "public-encrypt": "^4.0.0",
+        "randombytes": "^2.0.0",
+        "randomfill": "^1.0.3"
+      }
+    },
+    "css-parse": {
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-1.7.0.tgz",
+      "integrity": "sha1-Mh9s9zeCpv91ERE5D8BeLGV9jJs=",
+      "dev": true
+    },
+    "css-selector-tokenizer": {
+      "version": "0.7.1",
+      "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.1.tgz",
+      "integrity": "sha512-xYL0AMZJ4gFzJQsHUKa5jiWWi2vH77WVNg7JYRyewwj6oPh4yb/y6Y9ZCw9dsj/9UauMhtuxR+ogQd//EdEVNA==",
+      "dev": true,
+      "requires": {
+        "cssesc": "^0.1.0",
+        "fastparse": "^1.1.1",
+        "regexpu-core": "^1.0.0"
+      }
+    },
+    "cssauron": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/cssauron/-/cssauron-1.4.0.tgz",
+      "integrity": "sha1-pmAt/34EqDBtwNuaVR6S6LVmKtg=",
+      "dev": true,
+      "requires": {
+        "through": "X.X.X"
+      }
+    },
+    "cssesc": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-0.1.0.tgz",
+      "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=",
+      "dev": true
+    },
+    "currently-unhandled": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
+      "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
+      "dev": true,
+      "requires": {
+        "array-find-index": "^1.0.1"
+      }
+    },
+    "custom-event": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz",
+      "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=",
+      "dev": true
+    },
+    "cyclist": {
+      "version": "0.2.2",
+      "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz",
+      "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=",
+      "dev": true
+    },
+    "dashdash": {
+      "version": "1.14.1",
+      "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
+      "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
+      "dev": true,
+      "requires": {
+        "assert-plus": "^1.0.0"
+      }
+    },
+    "date-format": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz",
+      "integrity": "sha1-YV6CjiM90aubua4JUODOzPpuytg=",
+      "dev": true
+    },
+    "date-now": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz",
+      "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=",
+      "dev": true
+    },
+    "debug": {
+      "version": "2.6.9",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+      "dev": true,
+      "requires": {
+        "ms": "2.0.0"
+      }
+    },
+    "decamelize": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+      "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
+      "dev": true
+    },
+    "decode-uri-component": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
+      "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
+      "dev": true
+    },
+    "deep-equal": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
+      "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=",
+      "dev": true
+    },
+    "deep-is": {
+      "version": "0.1.3",
+      "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
+      "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
+      "dev": true
+    },
+    "default-gateway": {
+      "version": "2.7.2",
+      "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-2.7.2.tgz",
+      "integrity": "sha512-lAc4i9QJR0YHSDFdzeBQKfZ1SRDG3hsJNEkrpcZa8QhBfidLAilT60BDEIVUUGqosFp425KOgB3uYqcnQrWafQ==",
+      "dev": true,
+      "requires": {
+        "execa": "^0.10.0",
+        "ip-regex": "^2.1.0"
+      }
+    },
+    "default-require-extensions": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz",
+      "integrity": "sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=",
+      "dev": true,
+      "requires": {
+        "strip-bom": "^3.0.0"
+      },
+      "dependencies": {
+        "strip-bom": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+          "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+          "dev": true
+        }
+      }
+    },
+    "define-property": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
+      "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==",
+      "dev": true,
+      "requires": {
+        "is-descriptor": "^1.0.2",
+        "isobject": "^3.0.1"
+      },
+      "dependencies": {
+        "is-accessor-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+          "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+          "dev": true,
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-data-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+          "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+          "dev": true,
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-descriptor": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+          "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+          "dev": true,
+          "requires": {
+            "is-accessor-descriptor": "^1.0.0",
+            "is-data-descriptor": "^1.0.0",
+            "kind-of": "^6.0.2"
+          }
+        }
+      }
+    },
+    "del": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz",
+      "integrity": "sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=",
+      "dev": true,
+      "requires": {
+        "globby": "^6.1.0",
+        "is-path-cwd": "^1.0.0",
+        "is-path-in-cwd": "^1.0.0",
+        "p-map": "^1.1.1",
+        "pify": "^3.0.0",
+        "rimraf": "^2.2.8"
+      },
+      "dependencies": {
+        "globby": {
+          "version": "6.1.0",
+          "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz",
+          "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=",
+          "dev": true,
+          "requires": {
+            "array-union": "^1.0.1",
+            "glob": "^7.0.3",
+            "object-assign": "^4.0.1",
+            "pify": "^2.0.0",
+            "pinkie-promise": "^2.0.0"
+          },
+          "dependencies": {
+            "pify": {
+              "version": "2.3.0",
+              "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+              "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+              "dev": true
+            }
+          }
+        }
+      }
+    },
+    "delayed-stream": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+      "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
+      "dev": true
+    },
+    "delegates": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
+      "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
+      "dev": true
+    },
+    "depd": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+      "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
+      "dev": true
+    },
+    "dependency-graph": {
+      "version": "0.7.2",
+      "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.7.2.tgz",
+      "integrity": "sha512-KqtH4/EZdtdfWX0p6MGP9jljvxSY6msy/pRUD4jgNwVpv3v1QmNLlsB3LDSSUg79BRVSn7jI1QPRtArGABovAQ==",
+      "dev": true
+    },
+    "des.js": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz",
+      "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=",
+      "dev": true,
+      "requires": {
+        "inherits": "^2.0.1",
+        "minimalistic-assert": "^1.0.0"
+      }
+    },
+    "destroy": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
+      "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=",
+      "dev": true
+    },
+    "detect-indent": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz",
+      "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=",
+      "dev": true,
+      "requires": {
+        "repeating": "^2.0.0"
+      }
+    },
+    "detect-node": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz",
+      "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==",
+      "dev": true
+    },
+    "di": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz",
+      "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=",
+      "dev": true
+    },
+    "diff": {
+      "version": "3.5.0",
+      "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
+      "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
+      "dev": true
+    },
+    "diffie-hellman": {
+      "version": "5.0.3",
+      "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
+      "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==",
+      "dev": true,
+      "requires": {
+        "bn.js": "^4.1.0",
+        "miller-rabin": "^4.0.0",
+        "randombytes": "^2.0.0"
+      }
+    },
+    "dir-glob": {
+      "version": "2.2.2",
+      "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz",
+      "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==",
+      "dev": true,
+      "requires": {
+        "path-type": "^3.0.0"
+      }
+    },
+    "dns-equal": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz",
+      "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=",
+      "dev": true
+    },
+    "dns-packet": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz",
+      "integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==",
+      "dev": true,
+      "requires": {
+        "ip": "^1.1.0",
+        "safe-buffer": "^5.0.1"
+      }
+    },
+    "dns-txt": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz",
+      "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=",
+      "dev": true,
+      "requires": {
+        "buffer-indexof": "^1.0.0"
+      }
+    },
+    "dom-serialize": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz",
+      "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=",
+      "dev": true,
+      "requires": {
+        "custom-event": "~1.0.0",
+        "ent": "~2.2.0",
+        "extend": "^3.0.0",
+        "void-elements": "^2.0.0"
+      }
+    },
+    "domain-browser": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz",
+      "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==",
+      "dev": true
+    },
+    "duplexify": {
+      "version": "3.7.1",
+      "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz",
+      "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==",
+      "dev": true,
+      "requires": {
+        "end-of-stream": "^1.0.0",
+        "inherits": "^2.0.1",
+        "readable-stream": "^2.0.0",
+        "stream-shift": "^1.0.0"
+      }
+    },
+    "ecc-jsbn": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
+      "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
+      "dev": true,
+      "requires": {
+        "jsbn": "~0.1.0",
+        "safer-buffer": "^2.1.0"
+      }
+    },
+    "ee-first": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+      "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=",
+      "dev": true
+    },
+    "electron-to-chromium": {
+      "version": "1.3.194",
+      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.194.tgz",
+      "integrity": "sha512-w0LHR2YD9Ex1o+Sz4IN2hYzCB8vaFtMNW+yJcBf6SZlVqgFahkne/4rGVJdk4fPF98Gch9snY7PiabOh+vqHNg==",
+      "dev": true
+    },
+    "elliptic": {
+      "version": "6.5.0",
+      "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.0.tgz",
+      "integrity": "sha512-eFOJTMyCYb7xtE/caJ6JJu+bhi67WCYNbkGSknu20pmM8Ke/bqOfdnZWxyoGN26JgfxTbXrsCkEw4KheCT/KGg==",
+      "dev": true,
+      "requires": {
+        "bn.js": "^4.4.0",
+        "brorand": "^1.0.1",
+        "hash.js": "^1.0.0",
+        "hmac-drbg": "^1.0.0",
+        "inherits": "^2.0.1",
+        "minimalistic-assert": "^1.0.0",
+        "minimalistic-crypto-utils": "^1.0.0"
+      }
+    },
+    "emojis-list": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz",
+      "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=",
+      "dev": true
+    },
+    "encodeurl": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+      "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
+      "dev": true
+    },
+    "end-of-stream": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz",
+      "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==",
+      "dev": true,
+      "requires": {
+        "once": "^1.4.0"
+      }
+    },
+    "engine.io": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz",
+      "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==",
+      "dev": true,
+      "requires": {
+        "accepts": "~1.3.4",
+        "base64id": "1.0.0",
+        "cookie": "0.3.1",
+        "debug": "~3.1.0",
+        "engine.io-parser": "~2.1.0",
+        "ws": "~3.3.1"
+      },
+      "dependencies": {
+        "cookie": {
+          "version": "0.3.1",
+          "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
+          "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=",
+          "dev": true
+        },
+        "debug": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        }
+      }
+    },
+    "engine.io-client": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz",
+      "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==",
+      "dev": true,
+      "requires": {
+        "component-emitter": "1.2.1",
+        "component-inherit": "0.0.3",
+        "debug": "~3.1.0",
+        "engine.io-parser": "~2.1.1",
+        "has-cors": "1.1.0",
+        "indexof": "0.0.1",
+        "parseqs": "0.0.5",
+        "parseuri": "0.0.5",
+        "ws": "~3.3.1",
+        "xmlhttprequest-ssl": "~1.5.4",
+        "yeast": "0.1.2"
+      },
+      "dependencies": {
+        "component-emitter": {
+          "version": "1.2.1",
+          "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
+          "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=",
+          "dev": true
+        },
+        "debug": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        }
+      }
+    },
+    "engine.io-parser": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz",
+      "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==",
+      "dev": true,
+      "requires": {
+        "after": "0.8.2",
+        "arraybuffer.slice": "~0.0.7",
+        "base64-arraybuffer": "0.1.5",
+        "blob": "0.0.5",
+        "has-binary2": "~1.0.2"
+      }
+    },
+    "enhanced-resolve": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz",
+      "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "^4.1.2",
+        "memory-fs": "^0.4.0",
+        "tapable": "^1.0.0"
+      }
+    },
+    "ent": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz",
+      "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=",
+      "dev": true
+    },
+    "errno": {
+      "version": "0.1.7",
+      "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
+      "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==",
+      "dev": true,
+      "requires": {
+        "prr": "~1.0.1"
+      }
+    },
+    "error-ex": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+      "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+      "dev": true,
+      "requires": {
+        "is-arrayish": "^0.2.1"
+      }
+    },
+    "es6-promise": {
+      "version": "4.2.8",
+      "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
+      "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==",
+      "dev": true
+    },
+    "es6-promisify": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
+      "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=",
+      "dev": true,
+      "requires": {
+        "es6-promise": "^4.0.3"
+      }
+    },
+    "escape-html": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+      "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=",
+      "dev": true
+    },
+    "escape-string-regexp": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+      "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+      "dev": true
+    },
+    "escodegen": {
+      "version": "1.8.1",
+      "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz",
+      "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=",
+      "dev": true,
+      "requires": {
+        "esprima": "^2.7.1",
+        "estraverse": "^1.9.1",
+        "esutils": "^2.0.2",
+        "optionator": "^0.8.1",
+        "source-map": "~0.2.0"
+      },
+      "dependencies": {
+        "source-map": {
+          "version": "0.2.0",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz",
+          "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "amdefine": ">=0.0.4"
+          }
+        }
+      }
+    },
+    "eslint-scope": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz",
+      "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==",
+      "dev": true,
+      "requires": {
+        "esrecurse": "^4.1.0",
+        "estraverse": "^4.1.1"
+      },
+      "dependencies": {
+        "estraverse": {
+          "version": "4.2.0",
+          "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz",
+          "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=",
+          "dev": true
+        }
+      }
+    },
+    "esprima": {
+      "version": "2.7.3",
+      "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz",
+      "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=",
+      "dev": true
+    },
+    "esrecurse": {
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
+      "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==",
+      "dev": true,
+      "requires": {
+        "estraverse": "^4.1.0"
+      },
+      "dependencies": {
+        "estraverse": {
+          "version": "4.2.0",
+          "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz",
+          "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=",
+          "dev": true
+        }
+      }
+    },
+    "estraverse": {
+      "version": "1.9.3",
+      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz",
+      "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=",
+      "dev": true
+    },
+    "esutils": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
+      "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
+      "dev": true
+    },
+    "etag": {
+      "version": "1.8.1",
+      "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+      "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=",
+      "dev": true
+    },
+    "eventemitter3": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz",
+      "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==",
+      "dev": true
+    },
+    "events": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/events/-/events-3.0.0.tgz",
+      "integrity": "sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA==",
+      "dev": true
+    },
+    "eventsource": {
+      "version": "0.1.6",
+      "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-0.1.6.tgz",
+      "integrity": "sha1-Cs7ehJ7X3RzMMsgRuxG5RNTykjI=",
+      "dev": true,
+      "requires": {
+        "original": ">=0.0.5"
+      }
+    },
+    "evp_bytestokey": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
+      "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==",
+      "dev": true,
+      "requires": {
+        "md5.js": "^1.3.4",
+        "safe-buffer": "^5.1.1"
+      }
+    },
+    "execa": {
+      "version": "0.10.0",
+      "resolved": "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz",
+      "integrity": "sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==",
+      "dev": true,
+      "requires": {
+        "cross-spawn": "^6.0.0",
+        "get-stream": "^3.0.0",
+        "is-stream": "^1.1.0",
+        "npm-run-path": "^2.0.0",
+        "p-finally": "^1.0.0",
+        "signal-exit": "^3.0.0",
+        "strip-eof": "^1.0.0"
+      },
+      "dependencies": {
+        "cross-spawn": {
+          "version": "6.0.5",
+          "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+          "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+          "dev": true,
+          "requires": {
+            "nice-try": "^1.0.4",
+            "path-key": "^2.0.1",
+            "semver": "^5.5.0",
+            "shebang-command": "^1.2.0",
+            "which": "^1.2.9"
+          }
+        }
+      }
+    },
+    "exit": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
+      "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=",
+      "dev": true
+    },
+    "expand-braces": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz",
+      "integrity": "sha1-SIsdHSRRyz06axks/AMPRMWFX+o=",
+      "dev": true,
+      "requires": {
+        "array-slice": "^0.2.3",
+        "array-unique": "^0.2.1",
+        "braces": "^0.1.2"
+      },
+      "dependencies": {
+        "array-unique": {
+          "version": "0.2.1",
+          "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
+          "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=",
+          "dev": true
+        },
+        "braces": {
+          "version": "0.1.5",
+          "resolved": "https://registry.npmjs.org/braces/-/braces-0.1.5.tgz",
+          "integrity": "sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=",
+          "dev": true,
+          "requires": {
+            "expand-range": "^0.1.0"
+          }
+        },
+        "expand-range": {
+          "version": "0.1.1",
+          "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz",
+          "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=",
+          "dev": true,
+          "requires": {
+            "is-number": "^0.1.1",
+            "repeat-string": "^0.2.2"
+          }
+        },
+        "is-number": {
+          "version": "0.1.1",
+          "resolved": "https://registry.npmjs.org/is-number/-/is-number-0.1.1.tgz",
+          "integrity": "sha1-aaevEWlj1HIG7JvZtIoUIW8eOAY=",
+          "dev": true
+        },
+        "repeat-string": {
+          "version": "0.2.2",
+          "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-0.2.2.tgz",
+          "integrity": "sha1-x6jTI2BoNiBZp+RlH8aITosftK4=",
+          "dev": true
+        }
+      }
+    },
+    "expand-brackets": {
+      "version": "2.1.4",
+      "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
+      "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
+      "dev": true,
+      "requires": {
+        "debug": "^2.3.3",
+        "define-property": "^0.2.5",
+        "extend-shallow": "^2.0.1",
+        "posix-character-classes": "^0.1.0",
+        "regex-not": "^1.0.0",
+        "snapdragon": "^0.8.1",
+        "to-regex": "^3.0.1"
+      },
+      "dependencies": {
+        "define-property": {
+          "version": "0.2.5",
+          "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+          "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+          "dev": true,
+          "requires": {
+            "is-descriptor": "^0.1.0"
+          }
+        },
+        "extend-shallow": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+          "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+          "dev": true,
+          "requires": {
+            "is-extendable": "^0.1.0"
+          }
+        }
+      }
+    },
+    "expand-range": {
+      "version": "1.8.2",
+      "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz",
+      "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=",
+      "dev": true,
+      "requires": {
+        "fill-range": "^2.1.0"
+      },
+      "dependencies": {
+        "fill-range": {
+          "version": "2.2.4",
+          "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz",
+          "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==",
+          "dev": true,
+          "requires": {
+            "is-number": "^2.1.0",
+            "isobject": "^2.0.0",
+            "randomatic": "^3.0.0",
+            "repeat-element": "^1.1.2",
+            "repeat-string": "^1.5.2"
+          }
+        },
+        "is-number": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz",
+          "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=",
+          "dev": true,
+          "requires": {
+            "kind-of": "^3.0.2"
+          }
+        },
+        "isobject": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
+          "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
+          "dev": true,
+          "requires": {
+            "isarray": "1.0.0"
+          }
+        },
+        "kind-of": {
+          "version": "3.2.2",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+          "dev": true,
+          "requires": {
+            "is-buffer": "^1.1.5"
+          }
+        }
+      }
+    },
+    "express": {
+      "version": "4.17.1",
+      "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
+      "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==",
+      "dev": true,
+      "requires": {
+        "accepts": "~1.3.7",
+        "array-flatten": "1.1.1",
+        "body-parser": "1.19.0",
+        "content-disposition": "0.5.3",
+        "content-type": "~1.0.4",
+        "cookie": "0.4.0",
+        "cookie-signature": "1.0.6",
+        "debug": "2.6.9",
+        "depd": "~1.1.2",
+        "encodeurl": "~1.0.2",
+        "escape-html": "~1.0.3",
+        "etag": "~1.8.1",
+        "finalhandler": "~1.1.2",
+        "fresh": "0.5.2",
+        "merge-descriptors": "1.0.1",
+        "methods": "~1.1.2",
+        "on-finished": "~2.3.0",
+        "parseurl": "~1.3.3",
+        "path-to-regexp": "0.1.7",
+        "proxy-addr": "~2.0.5",
+        "qs": "6.7.0",
+        "range-parser": "~1.2.1",
+        "safe-buffer": "5.1.2",
+        "send": "0.17.1",
+        "serve-static": "1.14.1",
+        "setprototypeof": "1.1.1",
+        "statuses": "~1.5.0",
+        "type-is": "~1.6.18",
+        "utils-merge": "1.0.1",
+        "vary": "~1.1.2"
+      },
+      "dependencies": {
+        "array-flatten": {
+          "version": "1.1.1",
+          "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+          "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=",
+          "dev": true
+        },
+        "qs": {
+          "version": "6.7.0",
+          "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
+          "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==",
+          "dev": true
+        }
+      }
+    },
+    "extend": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+      "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
+      "dev": true
+    },
+    "extend-shallow": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
+      "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
+      "dev": true,
+      "requires": {
+        "assign-symbols": "^1.0.0",
+        "is-extendable": "^1.0.1"
+      },
+      "dependencies": {
+        "is-extendable": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+          "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+          "dev": true,
+          "requires": {
+            "is-plain-object": "^2.0.4"
+          }
+        }
+      }
+    },
+    "external-editor": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
+      "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==",
+      "dev": true,
+      "requires": {
+        "chardet": "^0.7.0",
+        "iconv-lite": "^0.4.24",
+        "tmp": "^0.0.33"
+      }
+    },
+    "extglob": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
+      "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
+      "dev": true,
+      "requires": {
+        "array-unique": "^0.3.2",
+        "define-property": "^1.0.0",
+        "expand-brackets": "^2.1.4",
+        "extend-shallow": "^2.0.1",
+        "fragment-cache": "^0.2.1",
+        "regex-not": "^1.0.0",
+        "snapdragon": "^0.8.1",
+        "to-regex": "^3.0.1"
+      },
+      "dependencies": {
+        "define-property": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+          "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+          "dev": true,
+          "requires": {
+            "is-descriptor": "^1.0.0"
+          }
+        },
+        "extend-shallow": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+          "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+          "dev": true,
+          "requires": {
+            "is-extendable": "^0.1.0"
+          }
+        },
+        "is-accessor-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+          "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+          "dev": true,
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-data-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+          "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+          "dev": true,
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-descriptor": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+          "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+          "dev": true,
+          "requires": {
+            "is-accessor-descriptor": "^1.0.0",
+            "is-data-descriptor": "^1.0.0",
+            "kind-of": "^6.0.2"
+          }
+        }
+      }
+    },
+    "extsprintf": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
+      "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
+      "dev": true
+    },
+    "fast-deep-equal": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
+      "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
+      "dev": true
+    },
+    "fast-json-stable-stringify": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
+      "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=",
+      "dev": true
+    },
+    "fast-levenshtein": {
+      "version": "2.0.6",
+      "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+      "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
+      "dev": true
+    },
+    "fastparse": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz",
+      "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==",
+      "dev": true
+    },
+    "faye-websocket": {
+      "version": "0.10.0",
+      "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz",
+      "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=",
+      "dev": true,
+      "requires": {
+        "websocket-driver": ">=0.5.1"
+      }
+    },
+    "figgy-pudding": {
+      "version": "3.5.1",
+      "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz",
+      "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==",
+      "dev": true
+    },
+    "figures": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
+      "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
+      "dev": true,
+      "requires": {
+        "escape-string-regexp": "^1.0.5"
+      }
+    },
+    "file-loader": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-2.0.0.tgz",
+      "integrity": "sha512-YCsBfd1ZGCyonOKLxPiKPdu+8ld9HAaMEvJewzz+b2eTF7uL5Zm/HdBF6FjCrpCMRq25Mi0U1gl4pwn2TlH7hQ==",
+      "dev": true,
+      "requires": {
+        "loader-utils": "^1.0.2",
+        "schema-utils": "^1.0.0"
+      }
+    },
+    "filename-regex": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz",
+      "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=",
+      "dev": true
+    },
+    "fileset": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz",
+      "integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=",
+      "dev": true,
+      "requires": {
+        "glob": "^7.0.3",
+        "minimatch": "^3.0.3"
+      }
+    },
+    "fill-range": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
+      "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+      "dev": true,
+      "requires": {
+        "extend-shallow": "^2.0.1",
+        "is-number": "^3.0.0",
+        "repeat-string": "^1.6.1",
+        "to-regex-range": "^2.1.0"
+      },
+      "dependencies": {
+        "extend-shallow": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+          "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+          "dev": true,
+          "requires": {
+            "is-extendable": "^0.1.0"
+          }
+        }
+      }
+    },
+    "finalhandler": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
+      "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
+      "dev": true,
+      "requires": {
+        "debug": "2.6.9",
+        "encodeurl": "~1.0.2",
+        "escape-html": "~1.0.3",
+        "on-finished": "~2.3.0",
+        "parseurl": "~1.3.3",
+        "statuses": "~1.5.0",
+        "unpipe": "~1.0.0"
+      }
+    },
+    "find-cache-dir": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz",
+      "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=",
+      "dev": true,
+      "requires": {
+        "commondir": "^1.0.1",
+        "make-dir": "^1.0.0",
+        "pkg-dir": "^2.0.0"
+      }
+    },
+    "find-up": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
+      "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
+      "dev": true,
+      "requires": {
+        "locate-path": "^2.0.0"
+      }
+    },
+    "flush-write-stream": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz",
+      "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==",
+      "dev": true,
+      "requires": {
+        "inherits": "^2.0.3",
+        "readable-stream": "^2.3.6"
+      }
+    },
+    "follow-redirects": {
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.7.0.tgz",
+      "integrity": "sha512-m/pZQy4Gj287eNy94nivy5wchN3Kp+Q5WgUPNy5lJSZ3sgkVKSYV/ZChMAQVIgx1SqfZ2zBZtPA2YlXIWxxJOQ==",
+      "dev": true,
+      "requires": {
+        "debug": "^3.2.6"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "3.2.6",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+          "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+          "dev": true,
+          "requires": {
+            "ms": "^2.1.1"
+          }
+        },
+        "ms": {
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+          "dev": true
+        }
+      }
+    },
+    "font-awesome": {
+      "version": "4.7.0",
+      "resolved": "https://registry.npmjs.org/font-awesome/-/font-awesome-4.7.0.tgz",
+      "integrity": "sha1-j6jPBBGhoxr9B7BtKQK7n8gVoTM="
+    },
+    "for-in": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
+      "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
+      "dev": true
+    },
+    "for-own": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz",
+      "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=",
+      "dev": true,
+      "requires": {
+        "for-in": "^1.0.1"
+      }
+    },
+    "forever-agent": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
+      "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=",
+      "dev": true
+    },
+    "form-data": {
+      "version": "2.3.3",
+      "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
+      "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
+      "dev": true,
+      "requires": {
+        "asynckit": "^0.4.0",
+        "combined-stream": "^1.0.6",
+        "mime-types": "^2.1.12"
+      }
+    },
+    "forwarded": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
+      "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=",
+      "dev": true
+    },
+    "fragment-cache": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
+      "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
+      "dev": true,
+      "requires": {
+        "map-cache": "^0.2.2"
+      }
+    },
+    "fresh": {
+      "version": "0.5.2",
+      "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+      "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=",
+      "dev": true
+    },
+    "from2": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz",
+      "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=",
+      "dev": true,
+      "requires": {
+        "inherits": "^2.0.1",
+        "readable-stream": "^2.0.0"
+      }
+    },
+    "fs-access": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/fs-access/-/fs-access-1.0.1.tgz",
+      "integrity": "sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o=",
+      "dev": true,
+      "requires": {
+        "null-check": "^1.0.0"
+      }
+    },
+    "fs-write-stream-atomic": {
+      "version": "1.0.10",
+      "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz",
+      "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "^4.1.2",
+        "iferr": "^0.1.5",
+        "imurmurhash": "^0.1.4",
+        "readable-stream": "1 || 2"
+      }
+    },
+    "fs.realpath": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+      "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+      "dev": true
+    },
+    "fsevents": {
+      "version": "1.2.9",
+      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz",
+      "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "nan": "^2.12.1",
+        "node-pre-gyp": "^0.12.0"
+      },
+      "dependencies": {
+        "abbrev": {
+          "version": "1.1.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "ansi-regex": {
+          "version": "2.1.1",
+          "bundled": true,
+          "dev": true
+        },
+        "aproba": {
+          "version": "1.2.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "are-we-there-yet": {
+          "version": "1.1.5",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "delegates": "^1.0.0",
+            "readable-stream": "^2.0.6"
+          }
+        },
+        "balanced-match": {
+          "version": "1.0.0",
+          "bundled": true,
+          "dev": true
+        },
+        "brace-expansion": {
+          "version": "1.1.11",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "balanced-match": "^1.0.0",
+            "concat-map": "0.0.1"
+          }
+        },
+        "chownr": {
+          "version": "1.1.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "code-point-at": {
+          "version": "1.1.0",
+          "bundled": true,
+          "dev": true
+        },
+        "concat-map": {
+          "version": "0.0.1",
+          "bundled": true,
+          "dev": true
+        },
+        "console-control-strings": {
+          "version": "1.1.0",
+          "bundled": true,
+          "dev": true
+        },
+        "core-util-is": {
+          "version": "1.0.2",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "debug": {
+          "version": "4.1.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "ms": "^2.1.1"
+          }
+        },
+        "deep-extend": {
+          "version": "0.6.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "delegates": {
+          "version": "1.0.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "detect-libc": {
+          "version": "1.0.3",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "fs-minipass": {
+          "version": "1.2.5",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "minipass": "^2.2.1"
+          }
+        },
+        "fs.realpath": {
+          "version": "1.0.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "gauge": {
+          "version": "2.7.4",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "aproba": "^1.0.3",
+            "console-control-strings": "^1.0.0",
+            "has-unicode": "^2.0.0",
+            "object-assign": "^4.1.0",
+            "signal-exit": "^3.0.0",
+            "string-width": "^1.0.1",
+            "strip-ansi": "^3.0.1",
+            "wide-align": "^1.1.0"
+          }
+        },
+        "glob": {
+          "version": "7.1.3",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "fs.realpath": "^1.0.0",
+            "inflight": "^1.0.4",
+            "inherits": "2",
+            "minimatch": "^3.0.4",
+            "once": "^1.3.0",
+            "path-is-absolute": "^1.0.0"
+          }
+        },
+        "has-unicode": {
+          "version": "2.0.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "iconv-lite": {
+          "version": "0.4.24",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "safer-buffer": ">= 2.1.2 < 3"
+          }
+        },
+        "ignore-walk": {
+          "version": "3.0.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "minimatch": "^3.0.4"
+          }
+        },
+        "inflight": {
+          "version": "1.0.6",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "once": "^1.3.0",
+            "wrappy": "1"
+          }
+        },
+        "inherits": {
+          "version": "2.0.3",
+          "bundled": true,
+          "dev": true
+        },
+        "ini": {
+          "version": "1.3.5",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "is-fullwidth-code-point": {
+          "version": "1.0.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "number-is-nan": "^1.0.0"
+          }
+        },
+        "isarray": {
+          "version": "1.0.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "minimatch": {
+          "version": "3.0.4",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "brace-expansion": "^1.1.7"
+          }
+        },
+        "minimist": {
+          "version": "0.0.8",
+          "bundled": true,
+          "dev": true
+        },
+        "minipass": {
+          "version": "2.3.5",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "safe-buffer": "^5.1.2",
+            "yallist": "^3.0.0"
+          }
+        },
+        "minizlib": {
+          "version": "1.2.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "minipass": "^2.2.1"
+          }
+        },
+        "mkdirp": {
+          "version": "0.5.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "minimist": "0.0.8"
+          }
+        },
+        "ms": {
+          "version": "2.1.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "needle": {
+          "version": "2.3.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "debug": "^4.1.0",
+            "iconv-lite": "^0.4.4",
+            "sax": "^1.2.4"
+          }
+        },
+        "node-pre-gyp": {
+          "version": "0.12.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "detect-libc": "^1.0.2",
+            "mkdirp": "^0.5.1",
+            "needle": "^2.2.1",
+            "nopt": "^4.0.1",
+            "npm-packlist": "^1.1.6",
+            "npmlog": "^4.0.2",
+            "rc": "^1.2.7",
+            "rimraf": "^2.6.1",
+            "semver": "^5.3.0",
+            "tar": "^4"
+          }
+        },
+        "nopt": {
+          "version": "4.0.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "abbrev": "1",
+            "osenv": "^0.1.4"
+          }
+        },
+        "npm-bundled": {
+          "version": "1.0.6",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "npm-packlist": {
+          "version": "1.4.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "ignore-walk": "^3.0.1",
+            "npm-bundled": "^1.0.1"
+          }
+        },
+        "npmlog": {
+          "version": "4.1.2",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "are-we-there-yet": "~1.1.2",
+            "console-control-strings": "~1.1.0",
+            "gauge": "~2.7.3",
+            "set-blocking": "~2.0.0"
+          }
+        },
+        "number-is-nan": {
+          "version": "1.0.1",
+          "bundled": true,
+          "dev": true
+        },
+        "object-assign": {
+          "version": "4.1.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "once": {
+          "version": "1.4.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "wrappy": "1"
+          }
+        },
+        "os-homedir": {
+          "version": "1.0.2",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "os-tmpdir": {
+          "version": "1.0.2",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "osenv": {
+          "version": "0.1.5",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "os-homedir": "^1.0.0",
+            "os-tmpdir": "^1.0.0"
+          }
+        },
+        "path-is-absolute": {
+          "version": "1.0.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "process-nextick-args": {
+          "version": "2.0.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "rc": {
+          "version": "1.2.8",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "deep-extend": "^0.6.0",
+            "ini": "~1.3.0",
+            "minimist": "^1.2.0",
+            "strip-json-comments": "~2.0.1"
+          },
+          "dependencies": {
+            "minimist": {
+              "version": "1.2.0",
+              "bundled": true,
+              "dev": true,
+              "optional": true
+            }
+          }
+        },
+        "readable-stream": {
+          "version": "2.3.6",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "core-util-is": "~1.0.0",
+            "inherits": "~2.0.3",
+            "isarray": "~1.0.0",
+            "process-nextick-args": "~2.0.0",
+            "safe-buffer": "~5.1.1",
+            "string_decoder": "~1.1.1",
+            "util-deprecate": "~1.0.1"
+          }
+        },
+        "rimraf": {
+          "version": "2.6.3",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "glob": "^7.1.3"
+          }
+        },
+        "safe-buffer": {
+          "version": "5.1.2",
+          "bundled": true,
+          "dev": true
+        },
+        "safer-buffer": {
+          "version": "2.1.2",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "sax": {
+          "version": "1.2.4",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "semver": {
+          "version": "5.7.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "set-blocking": {
+          "version": "2.0.0",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "signal-exit": {
+          "version": "3.0.2",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "string-width": {
+          "version": "1.0.2",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "code-point-at": "^1.0.0",
+            "is-fullwidth-code-point": "^1.0.0",
+            "strip-ansi": "^3.0.0"
+          }
+        },
+        "string_decoder": {
+          "version": "1.1.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "safe-buffer": "~5.1.0"
+          }
+        },
+        "strip-ansi": {
+          "version": "3.0.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^2.0.0"
+          }
+        },
+        "strip-json-comments": {
+          "version": "2.0.1",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "tar": {
+          "version": "4.4.8",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "chownr": "^1.1.1",
+            "fs-minipass": "^1.2.5",
+            "minipass": "^2.3.4",
+            "minizlib": "^1.1.1",
+            "mkdirp": "^0.5.0",
+            "safe-buffer": "^5.1.2",
+            "yallist": "^3.0.2"
+          }
+        },
+        "util-deprecate": {
+          "version": "1.0.2",
+          "bundled": true,
+          "dev": true,
+          "optional": true
+        },
+        "wide-align": {
+          "version": "1.1.3",
+          "bundled": true,
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "string-width": "^1.0.2 || 2"
+          }
+        },
+        "wrappy": {
+          "version": "1.0.2",
+          "bundled": true,
+          "dev": true
+        },
+        "yallist": {
+          "version": "3.0.3",
+          "bundled": true,
+          "dev": true
+        }
+      }
+    },
+    "fstream": {
+      "version": "1.0.12",
+      "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz",
+      "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "^4.1.2",
+        "inherits": "~2.0.0",
+        "mkdirp": ">=0.5 0",
+        "rimraf": "2"
+      }
+    },
+    "gauge": {
+      "version": "2.7.4",
+      "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
+      "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
+      "dev": true,
+      "requires": {
+        "aproba": "^1.0.3",
+        "console-control-strings": "^1.0.0",
+        "has-unicode": "^2.0.0",
+        "object-assign": "^4.1.0",
+        "signal-exit": "^3.0.0",
+        "string-width": "^1.0.1",
+        "strip-ansi": "^3.0.1",
+        "wide-align": "^1.1.0"
+      }
+    },
+    "gaze": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz",
+      "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "globule": "^1.0.0"
+      }
+    },
+    "get-caller-file": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
+      "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==",
+      "dev": true
+    },
+    "get-stdin": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
+      "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=",
+      "dev": true
+    },
+    "get-stream": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
+      "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
+      "dev": true
+    },
+    "get-value": {
+      "version": "2.0.6",
+      "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
+      "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=",
+      "dev": true
+    },
+    "getpass": {
+      "version": "0.1.7",
+      "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
+      "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
+      "dev": true,
+      "requires": {
+        "assert-plus": "^1.0.0"
+      }
+    },
+    "glob": {
+      "version": "7.1.3",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
+      "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
+      "dev": true,
+      "requires": {
+        "fs.realpath": "^1.0.0",
+        "inflight": "^1.0.4",
+        "inherits": "2",
+        "minimatch": "^3.0.4",
+        "once": "^1.3.0",
+        "path-is-absolute": "^1.0.0"
+      }
+    },
+    "glob-base": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz",
+      "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=",
+      "dev": true,
+      "requires": {
+        "glob-parent": "^2.0.0",
+        "is-glob": "^2.0.0"
+      },
+      "dependencies": {
+        "glob-parent": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz",
+          "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=",
+          "dev": true,
+          "requires": {
+            "is-glob": "^2.0.0"
+          }
+        },
+        "is-extglob": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
+          "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
+          "dev": true
+        },
+        "is-glob": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
+          "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
+          "dev": true,
+          "requires": {
+            "is-extglob": "^1.0.0"
+          }
+        }
+      }
+    },
+    "glob-parent": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
+      "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
+      "dev": true,
+      "requires": {
+        "is-glob": "^3.1.0",
+        "path-dirname": "^1.0.0"
+      },
+      "dependencies": {
+        "is-glob": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
+          "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
+          "dev": true,
+          "requires": {
+            "is-extglob": "^2.1.0"
+          }
+        }
+      }
+    },
+    "globals": {
+      "version": "9.18.0",
+      "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz",
+      "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==",
+      "dev": true
+    },
+    "globby": {
+      "version": "7.1.1",
+      "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz",
+      "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=",
+      "dev": true,
+      "requires": {
+        "array-union": "^1.0.1",
+        "dir-glob": "^2.0.0",
+        "glob": "^7.1.2",
+        "ignore": "^3.3.5",
+        "pify": "^3.0.0",
+        "slash": "^1.0.0"
+      }
+    },
+    "globule": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz",
+      "integrity": "sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "glob": "~7.1.1",
+        "lodash": "~4.17.10",
+        "minimatch": "~3.0.2"
+      }
+    },
+    "graceful-fs": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.0.tgz",
+      "integrity": "sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg==",
+      "dev": true
+    },
+    "hammerjs": {
+      "version": "2.0.8",
+      "resolved": "https://registry.npmjs.org/hammerjs/-/hammerjs-2.0.8.tgz",
+      "integrity": "sha1-BO93hiz/K7edMPdpIJWTAiK/YPE="
+    },
+    "handle-thing": {
+      "version": "1.2.5",
+      "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz",
+      "integrity": "sha1-/Xqtcmvxpf0W38KbL3pmAdJxOcQ=",
+      "dev": true
+    },
+    "handlebars": {
+      "version": "4.1.2",
+      "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz",
+      "integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==",
+      "dev": true,
+      "requires": {
+        "neo-async": "^2.6.0",
+        "optimist": "^0.6.1",
+        "source-map": "^0.6.1",
+        "uglify-js": "^3.1.4"
+      },
+      "dependencies": {
+        "source-map": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+          "dev": true
+        }
+      }
+    },
+    "har-schema": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
+      "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
+      "dev": true
+    },
+    "har-validator": {
+      "version": "5.1.3",
+      "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz",
+      "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==",
+      "dev": true,
+      "requires": {
+        "ajv": "^6.5.5",
+        "har-schema": "^2.0.0"
+      },
+      "dependencies": {
+        "ajv": {
+          "version": "6.10.2",
+          "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
+          "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==",
+          "dev": true,
+          "requires": {
+            "fast-deep-equal": "^2.0.1",
+            "fast-json-stable-stringify": "^2.0.0",
+            "json-schema-traverse": "^0.4.1",
+            "uri-js": "^4.2.2"
+          }
+        }
+      }
+    },
+    "has-ansi": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+      "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+      "dev": true,
+      "requires": {
+        "ansi-regex": "^2.0.0"
+      }
+    },
+    "has-binary2": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz",
+      "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==",
+      "dev": true,
+      "requires": {
+        "isarray": "2.0.1"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
+          "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=",
+          "dev": true
+        }
+      }
+    },
+    "has-cors": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz",
+      "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=",
+      "dev": true
+    },
+    "has-flag": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+      "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+      "dev": true
+    },
+    "has-unicode": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
+      "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=",
+      "dev": true
+    },
+    "has-value": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
+      "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=",
+      "dev": true,
+      "requires": {
+        "get-value": "^2.0.6",
+        "has-values": "^1.0.0",
+        "isobject": "^3.0.0"
+      }
+    },
+    "has-values": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz",
+      "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=",
+      "dev": true,
+      "requires": {
+        "is-number": "^3.0.0",
+        "kind-of": "^4.0.0"
+      },
+      "dependencies": {
+        "kind-of": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
+          "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
+          "dev": true,
+          "requires": {
+            "is-buffer": "^1.1.5"
+          }
+        }
+      }
+    },
+    "hash-base": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz",
+      "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=",
+      "dev": true,
+      "requires": {
+        "inherits": "^2.0.1",
+        "safe-buffer": "^5.0.1"
+      }
+    },
+    "hash.js": {
+      "version": "1.1.7",
+      "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz",
+      "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==",
+      "dev": true,
+      "requires": {
+        "inherits": "^2.0.3",
+        "minimalistic-assert": "^1.0.1"
+      }
+    },
+    "hmac-drbg": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
+      "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=",
+      "dev": true,
+      "requires": {
+        "hash.js": "^1.0.3",
+        "minimalistic-assert": "^1.0.0",
+        "minimalistic-crypto-utils": "^1.0.1"
+      }
+    },
+    "hosted-git-info": {
+      "version": "2.7.1",
+      "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz",
+      "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==",
+      "dev": true
+    },
+    "hpack.js": {
+      "version": "2.1.6",
+      "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz",
+      "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=",
+      "dev": true,
+      "requires": {
+        "inherits": "^2.0.1",
+        "obuf": "^1.0.0",
+        "readable-stream": "^2.0.1",
+        "wbuf": "^1.1.0"
+      }
+    },
+    "html-entities": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz",
+      "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=",
+      "dev": true
+    },
+    "http-deceiver": {
+      "version": "1.2.7",
+      "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz",
+      "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=",
+      "dev": true
+    },
+    "http-errors": {
+      "version": "1.7.2",
+      "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
+      "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
+      "dev": true,
+      "requires": {
+        "depd": "~1.1.2",
+        "inherits": "2.0.3",
+        "setprototypeof": "1.1.1",
+        "statuses": ">= 1.5.0 < 2",
+        "toidentifier": "1.0.0"
+      },
+      "dependencies": {
+        "inherits": {
+          "version": "2.0.3",
+          "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+          "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
+          "dev": true
+        }
+      }
+    },
+    "http-parser-js": {
+      "version": "0.4.10",
+      "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.10.tgz",
+      "integrity": "sha1-ksnBN0w1CF912zWexWzCV8u5P6Q=",
+      "dev": true
+    },
+    "http-proxy": {
+      "version": "1.17.0",
+      "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz",
+      "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==",
+      "dev": true,
+      "requires": {
+        "eventemitter3": "^3.0.0",
+        "follow-redirects": "^1.0.0",
+        "requires-port": "^1.0.0"
+      }
+    },
+    "http-proxy-middleware": {
+      "version": "0.18.0",
+      "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.18.0.tgz",
+      "integrity": "sha512-Fs25KVMPAIIcgjMZkVHJoKg9VcXcC1C8yb9JUgeDvVXY0S/zgVIhMb+qVswDIgtJe2DfckMSY2d6TuTEutlk6Q==",
+      "dev": true,
+      "requires": {
+        "http-proxy": "^1.16.2",
+        "is-glob": "^4.0.0",
+        "lodash": "^4.17.5",
+        "micromatch": "^3.1.9"
+      }
+    },
+    "http-signature": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
+      "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
+      "dev": true,
+      "requires": {
+        "assert-plus": "^1.0.0",
+        "jsprim": "^1.2.2",
+        "sshpk": "^1.7.0"
+      }
+    },
+    "https-browserify": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz",
+      "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=",
+      "dev": true
+    },
+    "https-proxy-agent": {
+      "version": "2.2.2",
+      "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.2.tgz",
+      "integrity": "sha512-c8Ndjc9Bkpfx/vCJueCPy0jlP4ccCCSNDp8xwCZzPjKJUm+B+u9WX2x98Qx4n1PiMNTWo3D7KK5ifNV/yJyRzg==",
+      "dev": true,
+      "requires": {
+        "agent-base": "^4.3.0",
+        "debug": "^3.1.0"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "3.2.6",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+          "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+          "dev": true,
+          "requires": {
+            "ms": "^2.1.1"
+          }
+        },
+        "ms": {
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+          "dev": true
+        }
+      }
+    },
+    "iconv-lite": {
+      "version": "0.4.24",
+      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+      "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+      "dev": true,
+      "requires": {
+        "safer-buffer": ">= 2.1.2 < 3"
+      }
+    },
+    "ieee754": {
+      "version": "1.1.13",
+      "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz",
+      "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==",
+      "dev": true
+    },
+    "iferr": {
+      "version": "0.1.5",
+      "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz",
+      "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=",
+      "dev": true
+    },
+    "ignore": {
+      "version": "3.3.10",
+      "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz",
+      "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==",
+      "dev": true
+    },
+    "image-size": {
+      "version": "0.5.5",
+      "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz",
+      "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=",
+      "dev": true,
+      "optional": true
+    },
+    "immediate": {
+      "version": "3.0.6",
+      "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
+      "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=",
+      "dev": true
+    },
+    "import-cwd": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz",
+      "integrity": "sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=",
+      "dev": true,
+      "requires": {
+        "import-from": "^2.1.0"
+      }
+    },
+    "import-fresh": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz",
+      "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=",
+      "dev": true,
+      "requires": {
+        "caller-path": "^2.0.0",
+        "resolve-from": "^3.0.0"
+      }
+    },
+    "import-from": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/import-from/-/import-from-2.1.0.tgz",
+      "integrity": "sha1-M1238qev/VOqpHHUuAId7ja387E=",
+      "dev": true,
+      "requires": {
+        "resolve-from": "^3.0.0"
+      }
+    },
+    "import-local": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz",
+      "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==",
+      "dev": true,
+      "requires": {
+        "pkg-dir": "^3.0.0",
+        "resolve-cwd": "^2.0.0"
+      },
+      "dependencies": {
+        "find-up": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+          "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+          "dev": true,
+          "requires": {
+            "locate-path": "^3.0.0"
+          }
+        },
+        "locate-path": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+          "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+          "dev": true,
+          "requires": {
+            "p-locate": "^3.0.0",
+            "path-exists": "^3.0.0"
+          }
+        },
+        "p-limit": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz",
+          "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==",
+          "dev": true,
+          "requires": {
+            "p-try": "^2.0.0"
+          }
+        },
+        "p-locate": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+          "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+          "dev": true,
+          "requires": {
+            "p-limit": "^2.0.0"
+          }
+        },
+        "p-try": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+          "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+          "dev": true
+        },
+        "pkg-dir": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz",
+          "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==",
+          "dev": true,
+          "requires": {
+            "find-up": "^3.0.0"
+          }
+        }
+      }
+    },
+    "imurmurhash": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+      "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+      "dev": true
+    },
+    "in-publish": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.0.tgz",
+      "integrity": "sha1-4g/146KvwmkDILbcVSaCqcf631E=",
+      "dev": true,
+      "optional": true
+    },
+    "indent-string": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
+      "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "repeating": "^2.0.0"
+      }
+    },
+    "indexof": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz",
+      "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=",
+      "dev": true
+    },
+    "inflight": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+      "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+      "dev": true,
+      "requires": {
+        "once": "^1.3.0",
+        "wrappy": "1"
+      }
+    },
+    "inherits": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+      "dev": true
+    },
+    "ini": {
+      "version": "1.3.5",
+      "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
+      "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
+      "dev": true
+    },
+    "inquirer": {
+      "version": "6.2.0",
+      "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.0.tgz",
+      "integrity": "sha512-QIEQG4YyQ2UYZGDC4srMZ7BjHOmNk1lR2JQj5UknBapklm6WHA+VVH7N+sUdX3A7NeCfGF8o4X1S3Ao7nAcIeg==",
+      "dev": true,
+      "requires": {
+        "ansi-escapes": "^3.0.0",
+        "chalk": "^2.0.0",
+        "cli-cursor": "^2.1.0",
+        "cli-width": "^2.0.0",
+        "external-editor": "^3.0.0",
+        "figures": "^2.0.0",
+        "lodash": "^4.17.10",
+        "mute-stream": "0.0.7",
+        "run-async": "^2.2.0",
+        "rxjs": "^6.1.0",
+        "string-width": "^2.1.0",
+        "strip-ansi": "^4.0.0",
+        "through": "^2.3.6"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+          "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+          "dev": true
+        },
+        "is-fullwidth-code-point": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+          "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+          "dev": true
+        },
+        "string-width": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+          "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+          "dev": true,
+          "requires": {
+            "is-fullwidth-code-point": "^2.0.0",
+            "strip-ansi": "^4.0.0"
+          }
+        },
+        "strip-ansi": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+          "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^3.0.0"
+          }
+        }
+      }
+    },
+    "internal-ip": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-3.0.1.tgz",
+      "integrity": "sha512-NXXgESC2nNVtU+pqmC9e6R8B1GpKxzsAQhffvh5AL79qKnodd+L7tnEQmTiUAVngqLalPbSqRA7XGIEL5nCd0Q==",
+      "dev": true,
+      "requires": {
+        "default-gateway": "^2.6.0",
+        "ipaddr.js": "^1.5.2"
+      }
+    },
+    "interpret": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz",
+      "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==",
+      "dev": true
+    },
+    "invariant": {
+      "version": "2.2.4",
+      "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
+      "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
+      "dev": true,
+      "requires": {
+        "loose-envify": "^1.0.0"
+      }
+    },
+    "invert-kv": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz",
+      "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=",
+      "dev": true
+    },
+    "ionicons": {
+      "version": "4.6.2",
+      "resolved": "https://registry.npmjs.org/ionicons/-/ionicons-4.6.2.tgz",
+      "integrity": "sha512-OGQO/GCKFwHh5lX9wYzgfLjuj2rnQavixVgK3iv8nm7tcgYQVHw7MNNwNHY4H97ZlKiVx3qj4X5Txv9fx95oBw=="
+    },
+    "ip": {
+      "version": "1.1.5",
+      "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
+      "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=",
+      "dev": true
+    },
+    "ip-regex": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz",
+      "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=",
+      "dev": true
+    },
+    "ipaddr.js": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz",
+      "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==",
+      "dev": true
+    },
+    "is-accessor-descriptor": {
+      "version": "0.1.6",
+      "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
+      "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
+      "dev": true,
+      "requires": {
+        "kind-of": "^3.0.2"
+      },
+      "dependencies": {
+        "kind-of": {
+          "version": "3.2.2",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+          "dev": true,
+          "requires": {
+            "is-buffer": "^1.1.5"
+          }
+        }
+      }
+    },
+    "is-arrayish": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+      "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
+      "dev": true
+    },
+    "is-binary-path": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
+      "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
+      "dev": true,
+      "requires": {
+        "binary-extensions": "^1.0.0"
+      }
+    },
+    "is-buffer": {
+      "version": "1.1.6",
+      "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+      "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+      "dev": true
+    },
+    "is-data-descriptor": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
+      "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
+      "dev": true,
+      "requires": {
+        "kind-of": "^3.0.2"
+      },
+      "dependencies": {
+        "kind-of": {
+          "version": "3.2.2",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+          "dev": true,
+          "requires": {
+            "is-buffer": "^1.1.5"
+          }
+        }
+      }
+    },
+    "is-descriptor": {
+      "version": "0.1.6",
+      "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
+      "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
+      "dev": true,
+      "requires": {
+        "is-accessor-descriptor": "^0.1.6",
+        "is-data-descriptor": "^0.1.4",
+        "kind-of": "^5.0.0"
+      },
+      "dependencies": {
+        "kind-of": {
+          "version": "5.1.0",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+          "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+          "dev": true
+        }
+      }
+    },
+    "is-directory": {
+      "version": "0.3.1",
+      "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz",
+      "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=",
+      "dev": true
+    },
+    "is-dotfile": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz",
+      "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=",
+      "dev": true
+    },
+    "is-equal-shallow": {
+      "version": "0.1.3",
+      "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz",
+      "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=",
+      "dev": true,
+      "requires": {
+        "is-primitive": "^2.0.0"
+      }
+    },
+    "is-extendable": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+      "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
+      "dev": true
+    },
+    "is-extglob": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+      "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+      "dev": true
+    },
+    "is-finite": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz",
+      "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=",
+      "dev": true,
+      "requires": {
+        "number-is-nan": "^1.0.0"
+      }
+    },
+    "is-fullwidth-code-point": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+      "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+      "dev": true,
+      "requires": {
+        "number-is-nan": "^1.0.0"
+      }
+    },
+    "is-glob": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
+      "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+      "dev": true,
+      "requires": {
+        "is-extglob": "^2.1.1"
+      }
+    },
+    "is-number": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+      "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+      "dev": true,
+      "requires": {
+        "kind-of": "^3.0.2"
+      },
+      "dependencies": {
+        "kind-of": {
+          "version": "3.2.2",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+          "dev": true,
+          "requires": {
+            "is-buffer": "^1.1.5"
+          }
+        }
+      }
+    },
+    "is-path-cwd": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz",
+      "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=",
+      "dev": true
+    },
+    "is-path-in-cwd": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz",
+      "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==",
+      "dev": true,
+      "requires": {
+        "is-path-inside": "^1.0.0"
+      }
+    },
+    "is-path-inside": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz",
+      "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=",
+      "dev": true,
+      "requires": {
+        "path-is-inside": "^1.0.1"
+      }
+    },
+    "is-plain-object": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
+      "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
+      "dev": true,
+      "requires": {
+        "isobject": "^3.0.1"
+      }
+    },
+    "is-posix-bracket": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz",
+      "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=",
+      "dev": true
+    },
+    "is-primitive": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz",
+      "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=",
+      "dev": true
+    },
+    "is-promise": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
+      "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=",
+      "dev": true
+    },
+    "is-stream": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+      "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
+      "dev": true
+    },
+    "is-typedarray": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+      "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
+      "dev": true
+    },
+    "is-utf8": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
+      "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=",
+      "dev": true
+    },
+    "is-windows": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
+      "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
+      "dev": true
+    },
+    "is-wsl": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz",
+      "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=",
+      "dev": true
+    },
+    "isarray": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+      "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+      "dev": true
+    },
+    "isbinaryfile": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz",
+      "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==",
+      "dev": true,
+      "requires": {
+        "buffer-alloc": "^1.2.0"
+      }
+    },
+    "isexe": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+      "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+      "dev": true
+    },
+    "isobject": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+      "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+      "dev": true
+    },
+    "isstream": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
+      "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
+      "dev": true
+    },
+    "istanbul": {
+      "version": "0.4.5",
+      "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz",
+      "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=",
+      "dev": true,
+      "requires": {
+        "abbrev": "1.0.x",
+        "async": "1.x",
+        "escodegen": "1.8.x",
+        "esprima": "2.7.x",
+        "glob": "^5.0.15",
+        "handlebars": "^4.0.1",
+        "js-yaml": "3.x",
+        "mkdirp": "0.5.x",
+        "nopt": "3.x",
+        "once": "1.x",
+        "resolve": "1.1.x",
+        "supports-color": "^3.1.0",
+        "which": "^1.1.1",
+        "wordwrap": "^1.0.0"
+      },
+      "dependencies": {
+        "glob": {
+          "version": "5.0.15",
+          "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz",
+          "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=",
+          "dev": true,
+          "requires": {
+            "inflight": "^1.0.4",
+            "inherits": "2",
+            "minimatch": "2 || 3",
+            "once": "^1.3.0",
+            "path-is-absolute": "^1.0.0"
+          }
+        },
+        "has-flag": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
+          "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
+          "dev": true
+        },
+        "supports-color": {
+          "version": "3.2.3",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
+          "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
+          "dev": true,
+          "requires": {
+            "has-flag": "^1.0.0"
+          }
+        }
+      }
+    },
+    "istanbul-api": {
+      "version": "2.1.6",
+      "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-2.1.6.tgz",
+      "integrity": "sha512-x0Eicp6KsShG1k1rMgBAi/1GgY7kFGEBwQpw3PXGEmu+rBcBNhqU8g2DgY9mlepAsLPzrzrbqSgCGANnki4POA==",
+      "dev": true,
+      "requires": {
+        "async": "^2.6.2",
+        "compare-versions": "^3.4.0",
+        "fileset": "^2.0.3",
+        "istanbul-lib-coverage": "^2.0.5",
+        "istanbul-lib-hook": "^2.0.7",
+        "istanbul-lib-instrument": "^3.3.0",
+        "istanbul-lib-report": "^2.0.8",
+        "istanbul-lib-source-maps": "^3.0.6",
+        "istanbul-reports": "^2.2.4",
+        "js-yaml": "^3.13.1",
+        "make-dir": "^2.1.0",
+        "minimatch": "^3.0.4",
+        "once": "^1.4.0"
+      },
+      "dependencies": {
+        "async": {
+          "version": "2.6.3",
+          "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
+          "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
+          "dev": true,
+          "requires": {
+            "lodash": "^4.17.14"
+          }
+        },
+        "istanbul-lib-coverage": {
+          "version": "2.0.5",
+          "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz",
+          "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==",
+          "dev": true
+        },
+        "istanbul-lib-instrument": {
+          "version": "3.3.0",
+          "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz",
+          "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==",
+          "dev": true,
+          "requires": {
+            "@babel/generator": "^7.4.0",
+            "@babel/parser": "^7.4.3",
+            "@babel/template": "^7.4.0",
+            "@babel/traverse": "^7.4.3",
+            "@babel/types": "^7.4.0",
+            "istanbul-lib-coverage": "^2.0.5",
+            "semver": "^6.0.0"
+          }
+        },
+        "make-dir": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
+          "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
+          "dev": true,
+          "requires": {
+            "pify": "^4.0.1",
+            "semver": "^5.6.0"
+          },
+          "dependencies": {
+            "semver": {
+              "version": "5.7.0",
+              "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
+              "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==",
+              "dev": true
+            }
+          }
+        },
+        "pify": {
+          "version": "4.0.1",
+          "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
+          "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+          "dev": true
+        },
+        "semver": {
+          "version": "6.2.0",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-6.2.0.tgz",
+          "integrity": "sha512-jdFC1VdUGT/2Scgbimf7FSx9iJLXoqfglSF+gJeuNWVpiE37OIbc1jywR/GJyFdz3mnkz2/id0L0J/cr0izR5A==",
+          "dev": true
+        }
+      }
+    },
+    "istanbul-instrumenter-loader": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/istanbul-instrumenter-loader/-/istanbul-instrumenter-loader-3.0.1.tgz",
+      "integrity": "sha512-a5SPObZgS0jB/ixaKSMdn6n/gXSrK2S6q/UfRJBT3e6gQmVjwZROTODQsYW5ZNwOu78hG62Y3fWlebaVOL0C+w==",
+      "dev": true,
+      "requires": {
+        "convert-source-map": "^1.5.0",
+        "istanbul-lib-instrument": "^1.7.3",
+        "loader-utils": "^1.1.0",
+        "schema-utils": "^0.3.0"
+      },
+      "dependencies": {
+        "ajv": {
+          "version": "5.5.2",
+          "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
+          "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
+          "dev": true,
+          "requires": {
+            "co": "^4.6.0",
+            "fast-deep-equal": "^1.0.0",
+            "fast-json-stable-stringify": "^2.0.0",
+            "json-schema-traverse": "^0.3.0"
+          }
+        },
+        "fast-deep-equal": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
+          "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=",
+          "dev": true
+        },
+        "json-schema-traverse": {
+          "version": "0.3.1",
+          "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
+          "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=",
+          "dev": true
+        },
+        "schema-utils": {
+          "version": "0.3.0",
+          "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz",
+          "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=",
+          "dev": true,
+          "requires": {
+            "ajv": "^5.0.0"
+          }
+        }
+      }
+    },
+    "istanbul-lib-coverage": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz",
+      "integrity": "sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==",
+      "dev": true
+    },
+    "istanbul-lib-hook": {
+      "version": "2.0.7",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz",
+      "integrity": "sha512-vrRztU9VRRFDyC+aklfLoeXyNdTfga2EI3udDGn4cZ6fpSXpHLV9X6CHvfoMCPtggg8zvDDmC4b9xfu0z6/llA==",
+      "dev": true,
+      "requires": {
+        "append-transform": "^1.0.0"
+      }
+    },
+    "istanbul-lib-instrument": {
+      "version": "1.10.2",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz",
+      "integrity": "sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==",
+      "dev": true,
+      "requires": {
+        "babel-generator": "^6.18.0",
+        "babel-template": "^6.16.0",
+        "babel-traverse": "^6.18.0",
+        "babel-types": "^6.18.0",
+        "babylon": "^6.18.0",
+        "istanbul-lib-coverage": "^1.2.1",
+        "semver": "^5.3.0"
+      }
+    },
+    "istanbul-lib-report": {
+      "version": "2.0.8",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz",
+      "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==",
+      "dev": true,
+      "requires": {
+        "istanbul-lib-coverage": "^2.0.5",
+        "make-dir": "^2.1.0",
+        "supports-color": "^6.1.0"
+      },
+      "dependencies": {
+        "istanbul-lib-coverage": {
+          "version": "2.0.5",
+          "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz",
+          "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==",
+          "dev": true
+        },
+        "make-dir": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
+          "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
+          "dev": true,
+          "requires": {
+            "pify": "^4.0.1",
+            "semver": "^5.6.0"
+          }
+        },
+        "pify": {
+          "version": "4.0.1",
+          "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
+          "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+          "dev": true
+        },
+        "semver": {
+          "version": "5.7.0",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
+          "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==",
+          "dev": true
+        },
+        "supports-color": {
+          "version": "6.1.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+          "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^3.0.0"
+          }
+        }
+      }
+    },
+    "istanbul-lib-source-maps": {
+      "version": "3.0.6",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz",
+      "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==",
+      "dev": true,
+      "requires": {
+        "debug": "^4.1.1",
+        "istanbul-lib-coverage": "^2.0.5",
+        "make-dir": "^2.1.0",
+        "rimraf": "^2.6.3",
+        "source-map": "^0.6.1"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "4.1.1",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+          "dev": true,
+          "requires": {
+            "ms": "^2.1.1"
+          }
+        },
+        "istanbul-lib-coverage": {
+          "version": "2.0.5",
+          "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz",
+          "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==",
+          "dev": true
+        },
+        "make-dir": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
+          "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
+          "dev": true,
+          "requires": {
+            "pify": "^4.0.1",
+            "semver": "^5.6.0"
+          }
+        },
+        "ms": {
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+          "dev": true
+        },
+        "pify": {
+          "version": "4.0.1",
+          "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
+          "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+          "dev": true
+        },
+        "semver": {
+          "version": "5.7.0",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
+          "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==",
+          "dev": true
+        },
+        "source-map": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+          "dev": true
+        }
+      }
+    },
+    "istanbul-reports": {
+      "version": "2.2.6",
+      "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.6.tgz",
+      "integrity": "sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA==",
+      "dev": true,
+      "requires": {
+        "handlebars": "^4.1.2"
+      }
+    },
+    "jasmine": {
+      "version": "2.8.0",
+      "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-2.8.0.tgz",
+      "integrity": "sha1-awicChFXax8W3xG4AUbZHU6Lij4=",
+      "dev": true,
+      "requires": {
+        "exit": "^0.1.2",
+        "glob": "^7.0.6",
+        "jasmine-core": "~2.8.0"
+      },
+      "dependencies": {
+        "jasmine-core": {
+          "version": "2.8.0",
+          "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.8.0.tgz",
+          "integrity": "sha1-vMl5rh+f0FcB5F5S5l06XWPxok4=",
+          "dev": true
+        }
+      }
+    },
+    "jasmine-core": {
+      "version": "2.99.1",
+      "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.99.1.tgz",
+      "integrity": "sha1-5kAN8ea1bhMLYcS80JPap/boyhU=",
+      "dev": true
+    },
+    "jasmine-spec-reporter": {
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/jasmine-spec-reporter/-/jasmine-spec-reporter-4.2.1.tgz",
+      "integrity": "sha512-FZBoZu7VE5nR7Nilzy+Np8KuVIOxF4oXDPDknehCYBDE080EnlPu0afdZNmpGDBRCUBv3mj5qgqCRmk6W/K8vg==",
+      "dev": true,
+      "requires": {
+        "colors": "1.1.2"
+      }
+    },
+    "jasminewd2": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/jasminewd2/-/jasminewd2-2.2.0.tgz",
+      "integrity": "sha1-43zwsX8ZnM4jvqcbIDk5Uka07E4=",
+      "dev": true
+    },
+    "jquery": {
+      "version": "3.4.1",
+      "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.4.1.tgz",
+      "integrity": "sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw=="
+    },
+    "js-base64": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.1.tgz",
+      "integrity": "sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw==",
+      "dev": true,
+      "optional": true
+    },
+    "js-tokens": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
+      "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
+      "dev": true
+    },
+    "js-yaml": {
+      "version": "3.13.1",
+      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
+      "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
+      "dev": true,
+      "requires": {
+        "argparse": "^1.0.7",
+        "esprima": "^4.0.0"
+      },
+      "dependencies": {
+        "esprima": {
+          "version": "4.0.1",
+          "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+          "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+          "dev": true
+        }
+      }
+    },
+    "jsbn": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
+      "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
+      "dev": true
+    },
+    "jsesc": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz",
+      "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=",
+      "dev": true
+    },
+    "json-parse-better-errors": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
+      "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
+      "dev": true
+    },
+    "json-schema": {
+      "version": "0.2.3",
+      "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
+      "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=",
+      "dev": true
+    },
+    "json-schema-traverse": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+      "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+      "dev": true
+    },
+    "json-stringify-safe": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+      "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
+      "dev": true
+    },
+    "json3": {
+      "version": "3.3.3",
+      "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.3.tgz",
+      "integrity": "sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA==",
+      "dev": true
+    },
+    "json5": {
+      "version": "0.5.1",
+      "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
+      "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=",
+      "dev": true
+    },
+    "jsprim": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
+      "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
+      "dev": true,
+      "requires": {
+        "assert-plus": "1.0.0",
+        "extsprintf": "1.3.0",
+        "json-schema": "0.2.3",
+        "verror": "1.10.0"
+      }
+    },
+    "jszip": {
+      "version": "3.2.2",
+      "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.2.2.tgz",
+      "integrity": "sha512-NmKajvAFQpbg3taXQXr/ccS2wcucR1AZ+NtyWp2Nq7HHVsXhcJFR8p0Baf32C2yVvBylFWVeKf+WI2AnvlPhpA==",
+      "dev": true,
+      "requires": {
+        "lie": "~3.3.0",
+        "pako": "~1.0.2",
+        "readable-stream": "~2.3.6",
+        "set-immediate-shim": "~1.0.1"
+      }
+    },
+    "karma": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/karma/-/karma-3.0.0.tgz",
+      "integrity": "sha512-ZTjyuDXVXhXsvJ1E4CnZzbCjSxD6sEdzEsFYogLuZM0yqvg/mgz+O+R1jb0J7uAQeuzdY8kJgx6hSNXLwFuHIQ==",
+      "dev": true,
+      "requires": {
+        "bluebird": "^3.3.0",
+        "body-parser": "^1.16.1",
+        "chokidar": "^2.0.3",
+        "colors": "^1.1.0",
+        "combine-lists": "^1.0.0",
+        "connect": "^3.6.0",
+        "core-js": "^2.2.0",
+        "di": "^0.0.1",
+        "dom-serialize": "^2.2.0",
+        "expand-braces": "^0.1.1",
+        "glob": "^7.1.1",
+        "graceful-fs": "^4.1.2",
+        "http-proxy": "^1.13.0",
+        "isbinaryfile": "^3.0.0",
+        "lodash": "^4.17.4",
+        "log4js": "^3.0.0",
+        "mime": "^2.3.1",
+        "minimatch": "^3.0.2",
+        "optimist": "^0.6.1",
+        "qjobs": "^1.1.4",
+        "range-parser": "^1.2.0",
+        "rimraf": "^2.6.0",
+        "safe-buffer": "^5.0.1",
+        "socket.io": "2.1.1",
+        "source-map": "^0.6.1",
+        "tmp": "0.0.33",
+        "useragent": "2.2.1"
+      },
+      "dependencies": {
+        "mime": {
+          "version": "2.4.4",
+          "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",
+          "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==",
+          "dev": true
+        },
+        "source-map": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+          "dev": true
+        }
+      }
+    },
+    "karma-chrome-launcher": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz",
+      "integrity": "sha512-uf/ZVpAabDBPvdPdveyk1EPgbnloPvFFGgmRhYLTDH7gEB4nZdSBk8yTU47w1g/drLSx5uMOkjKk7IWKfWg/+w==",
+      "dev": true,
+      "requires": {
+        "fs-access": "^1.0.0",
+        "which": "^1.2.1"
+      }
+    },
+    "karma-coverage-istanbul-reporter": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-2.0.5.tgz",
+      "integrity": "sha512-yPvAlKtY3y+rKKWbOo0CzBMVTvJEeMOgbMXuVv3yWvS8YtYKC98AU9vFF0mVBZ2RP1E9SgS90+PT6Kf14P3S4w==",
+      "dev": true,
+      "requires": {
+        "istanbul-api": "^2.1.1",
+        "minimatch": "^3.0.4"
+      }
+    },
+    "karma-jasmine": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-1.1.2.tgz",
+      "integrity": "sha1-OU8rJf+0pkS5rabyLUQ+L9CIhsM=",
+      "dev": true
+    },
+    "karma-jasmine-html-reporter": {
+      "version": "0.2.2",
+      "resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-0.2.2.tgz",
+      "integrity": "sha1-SKjl7xiAdhfuK14zwRlMNbQ5Ukw=",
+      "dev": true,
+      "requires": {
+        "karma-jasmine": "^1.0.2"
+      }
+    },
+    "karma-source-map-support": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/karma-source-map-support/-/karma-source-map-support-1.3.0.tgz",
+      "integrity": "sha512-HcPqdAusNez/ywa+biN4EphGz62MmQyPggUsDfsHqa7tSe4jdsxgvTKuDfIazjL+IOxpVWyT7Pr4dhAV+sxX5Q==",
+      "dev": true,
+      "requires": {
+        "source-map-support": "^0.5.5"
+      }
+    },
+    "killable": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz",
+      "integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==",
+      "dev": true
+    },
+    "kind-of": {
+      "version": "6.0.2",
+      "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
+      "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
+      "dev": true
+    },
+    "lcid": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz",
+      "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=",
+      "dev": true,
+      "requires": {
+        "invert-kv": "^1.0.0"
+      }
+    },
+    "less": {
+      "version": "3.8.1",
+      "resolved": "https://registry.npmjs.org/less/-/less-3.8.1.tgz",
+      "integrity": "sha512-8HFGuWmL3FhQR0aH89escFNBQH/nEiYPP2ltDFdQw2chE28Yx2E3lhAIq9Y2saYwLSwa699s4dBVEfCY8Drf7Q==",
+      "dev": true,
+      "requires": {
+        "clone": "^2.1.2",
+        "errno": "^0.1.1",
+        "graceful-fs": "^4.1.2",
+        "image-size": "~0.5.0",
+        "mime": "^1.4.1",
+        "mkdirp": "^0.5.0",
+        "promise": "^7.1.1",
+        "request": "^2.83.0",
+        "source-map": "~0.6.0"
+      },
+      "dependencies": {
+        "source-map": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+          "dev": true,
+          "optional": true
+        }
+      }
+    },
+    "less-loader": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-4.1.0.tgz",
+      "integrity": "sha512-KNTsgCE9tMOM70+ddxp9yyt9iHqgmSs0yTZc5XH5Wo+g80RWRIYNqE58QJKm/yMud5wZEvz50ugRDuzVIkyahg==",
+      "dev": true,
+      "requires": {
+        "clone": "^2.1.1",
+        "loader-utils": "^1.1.0",
+        "pify": "^3.0.0"
+      }
+    },
+    "levn": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
+      "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
+      "dev": true,
+      "requires": {
+        "prelude-ls": "~1.1.2",
+        "type-check": "~0.3.2"
+      }
+    },
+    "license-webpack-plugin": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-2.0.2.tgz",
+      "integrity": "sha512-GsomZw5VoT20ST8qH2tOjBgbyhn6Pgs9M94g0mbvfBIV1VXufm1iKY+4dbgfTObj1Mp6nSRE3Zf74deOZr0KwA==",
+      "dev": true,
+      "requires": {
+        "webpack-sources": "^1.2.0"
+      }
+    },
+    "lie": {
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
+      "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
+      "dev": true,
+      "requires": {
+        "immediate": "~3.0.5"
+      }
+    },
+    "load-json-file": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
+      "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "^4.1.2",
+        "parse-json": "^2.2.0",
+        "pify": "^2.0.0",
+        "pinkie-promise": "^2.0.0",
+        "strip-bom": "^2.0.0"
+      },
+      "dependencies": {
+        "pify": {
+          "version": "2.3.0",
+          "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+          "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+          "dev": true
+        }
+      }
+    },
+    "loader-runner": {
+      "version": "2.4.0",
+      "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz",
+      "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==",
+      "dev": true
+    },
+    "loader-utils": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz",
+      "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=",
+      "dev": true,
+      "requires": {
+        "big.js": "^3.1.3",
+        "emojis-list": "^2.0.0",
+        "json5": "^0.5.0"
+      }
+    },
+    "locate-path": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
+      "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
+      "dev": true,
+      "requires": {
+        "p-locate": "^2.0.0",
+        "path-exists": "^3.0.0"
+      }
+    },
+    "lodash": {
+      "version": "4.17.14",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.14.tgz",
+      "integrity": "sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw==",
+      "dev": true
+    },
+    "lodash.assign": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz",
+      "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=",
+      "dev": true,
+      "optional": true
+    },
+    "lodash.clonedeep": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
+      "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=",
+      "dev": true
+    },
+    "lodash.debounce": {
+      "version": "4.0.8",
+      "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
+      "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=",
+      "dev": true
+    },
+    "lodash.mergewith": {
+      "version": "4.6.2",
+      "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz",
+      "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==",
+      "dev": true,
+      "optional": true
+    },
+    "lodash.tail": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/lodash.tail/-/lodash.tail-4.1.1.tgz",
+      "integrity": "sha1-0jM6NtnncXyK0vfKyv7HwytERmQ=",
+      "dev": true
+    },
+    "log4js": {
+      "version": "3.0.6",
+      "resolved": "https://registry.npmjs.org/log4js/-/log4js-3.0.6.tgz",
+      "integrity": "sha512-ezXZk6oPJCWL483zj64pNkMuY/NcRX5MPiB0zE6tjZM137aeusrOnW1ecxgF9cmwMWkBMhjteQxBPoZBh9FDxQ==",
+      "dev": true,
+      "requires": {
+        "circular-json": "^0.5.5",
+        "date-format": "^1.2.0",
+        "debug": "^3.1.0",
+        "rfdc": "^1.1.2",
+        "streamroller": "0.7.0"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "3.2.6",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+          "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+          "dev": true,
+          "requires": {
+            "ms": "^2.1.1"
+          }
+        },
+        "ms": {
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+          "dev": true
+        }
+      }
+    },
+    "loglevel": {
+      "version": "1.6.3",
+      "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.3.tgz",
+      "integrity": "sha512-LoEDv5pgpvWgPF4kNYuIp0qqSJVWak/dML0RY74xlzMZiT9w77teNAwKYKWBTYjlokMirg+o3jBwp+vlLrcfAA==",
+      "dev": true
+    },
+    "loose-envify": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+      "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+      "dev": true,
+      "requires": {
+        "js-tokens": "^3.0.0 || ^4.0.0"
+      }
+    },
+    "loud-rejection": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
+      "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=",
+      "dev": true,
+      "requires": {
+        "currently-unhandled": "^0.4.1",
+        "signal-exit": "^3.0.0"
+      }
+    },
+    "lru-cache": {
+      "version": "4.1.5",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
+      "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
+      "dev": true,
+      "requires": {
+        "pseudomap": "^1.0.2",
+        "yallist": "^2.1.2"
+      }
+    },
+    "magic-string": {
+      "version": "0.25.3",
+      "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.3.tgz",
+      "integrity": "sha512-6QK0OpF/phMz0Q2AxILkX2mFhi7m+WMwTRg0LQKq/WBB0cDP4rYH3Wp4/d3OTXlrPLVJT/RFqj8tFeAR4nk8AA==",
+      "dev": true,
+      "requires": {
+        "sourcemap-codec": "^1.4.4"
+      }
+    },
+    "make-dir": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
+      "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==",
+      "dev": true,
+      "requires": {
+        "pify": "^3.0.0"
+      }
+    },
+    "make-error": {
+      "version": "1.3.5",
+      "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz",
+      "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==",
+      "dev": true
+    },
+    "mamacro": {
+      "version": "0.0.3",
+      "resolved": "https://registry.npmjs.org/mamacro/-/mamacro-0.0.3.tgz",
+      "integrity": "sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA==",
+      "dev": true
+    },
+    "map-age-cleaner": {
+      "version": "0.1.3",
+      "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz",
+      "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==",
+      "dev": true,
+      "requires": {
+        "p-defer": "^1.0.0"
+      }
+    },
+    "map-cache": {
+      "version": "0.2.2",
+      "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
+      "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=",
+      "dev": true
+    },
+    "map-obj": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
+      "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=",
+      "dev": true
+    },
+    "map-visit": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
+      "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=",
+      "dev": true,
+      "requires": {
+        "object-visit": "^1.0.0"
+      }
+    },
+    "material-design-icons-iconfont": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/material-design-icons-iconfont/-/material-design-icons-iconfont-5.0.1.tgz",
+      "integrity": "sha512-Xg6rIdGrfySTqiTZ6d+nQbcFepS6R4uKbJP0oAqyeZXJY/bX6mZDnOmmUJusqLXfhIwirs0c++a6JpqVa8RFvA=="
+    },
+    "math-random": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz",
+      "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==",
+      "dev": true
+    },
+    "md5.js": {
+      "version": "1.3.5",
+      "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
+      "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==",
+      "dev": true,
+      "requires": {
+        "hash-base": "^3.0.0",
+        "inherits": "^2.0.1",
+        "safe-buffer": "^5.1.2"
+      }
+    },
+    "media-typer": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+      "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=",
+      "dev": true
+    },
+    "mem": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz",
+      "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==",
+      "dev": true,
+      "requires": {
+        "map-age-cleaner": "^0.1.1",
+        "mimic-fn": "^2.0.0",
+        "p-is-promise": "^2.0.0"
+      }
+    },
+    "memory-fs": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
+      "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=",
+      "dev": true,
+      "requires": {
+        "errno": "^0.1.3",
+        "readable-stream": "^2.0.1"
+      }
+    },
+    "meow": {
+      "version": "3.7.0",
+      "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
+      "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "camelcase-keys": "^2.0.0",
+        "decamelize": "^1.1.2",
+        "loud-rejection": "^1.0.0",
+        "map-obj": "^1.0.1",
+        "minimist": "^1.1.3",
+        "normalize-package-data": "^2.3.4",
+        "object-assign": "^4.0.1",
+        "read-pkg-up": "^1.0.1",
+        "redent": "^1.0.0",
+        "trim-newlines": "^1.0.0"
+      },
+      "dependencies": {
+        "minimist": {
+          "version": "1.2.0",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+          "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+          "dev": true,
+          "optional": true
+        }
+      }
+    },
+    "merge-descriptors": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
+      "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=",
+      "dev": true
+    },
+    "methods": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+      "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=",
+      "dev": true
+    },
+    "micromatch": {
+      "version": "3.1.10",
+      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
+      "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
+      "dev": true,
+      "requires": {
+        "arr-diff": "^4.0.0",
+        "array-unique": "^0.3.2",
+        "braces": "^2.3.1",
+        "define-property": "^2.0.2",
+        "extend-shallow": "^3.0.2",
+        "extglob": "^2.0.4",
+        "fragment-cache": "^0.2.1",
+        "kind-of": "^6.0.2",
+        "nanomatch": "^1.2.9",
+        "object.pick": "^1.3.0",
+        "regex-not": "^1.0.0",
+        "snapdragon": "^0.8.1",
+        "to-regex": "^3.0.2"
+      }
+    },
+    "miller-rabin": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz",
+      "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==",
+      "dev": true,
+      "requires": {
+        "bn.js": "^4.0.0",
+        "brorand": "^1.0.1"
+      }
+    },
+    "mime": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+      "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+      "dev": true
+    },
+    "mime-db": {
+      "version": "1.40.0",
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz",
+      "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==",
+      "dev": true
+    },
+    "mime-types": {
+      "version": "2.1.24",
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz",
+      "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==",
+      "dev": true,
+      "requires": {
+        "mime-db": "1.40.0"
+      }
+    },
+    "mimic-fn": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+      "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+      "dev": true
+    },
+    "mini-css-extract-plugin": {
+      "version": "0.4.3",
+      "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.4.3.tgz",
+      "integrity": "sha512-Mxs0nxzF1kxPv4TRi2NimewgXlJqh0rGE30vviCU2WHrpbta6wklnUV9dr9FUtoAHmB3p3LeXEC+ZjgHvB0Dzg==",
+      "dev": true,
+      "requires": {
+        "loader-utils": "^1.1.0",
+        "schema-utils": "^1.0.0",
+        "webpack-sources": "^1.1.0"
+      }
+    },
+    "minimalistic-assert": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
+      "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==",
+      "dev": true
+    },
+    "minimalistic-crypto-utils": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
+      "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=",
+      "dev": true
+    },
+    "minimatch": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+      "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+      "dev": true,
+      "requires": {
+        "brace-expansion": "^1.1.7"
+      }
+    },
+    "minimist": {
+      "version": "0.0.8",
+      "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+      "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
+      "dev": true
+    },
+    "mississippi": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-2.0.0.tgz",
+      "integrity": "sha512-zHo8v+otD1J10j/tC+VNoGK9keCuByhKovAvdn74dmxJl9+mWHnx6EMsDN4lgRoMI/eYo2nchAxniIbUPb5onw==",
+      "dev": true,
+      "requires": {
+        "concat-stream": "^1.5.0",
+        "duplexify": "^3.4.2",
+        "end-of-stream": "^1.1.0",
+        "flush-write-stream": "^1.0.0",
+        "from2": "^2.1.0",
+        "parallel-transform": "^1.1.0",
+        "pump": "^2.0.1",
+        "pumpify": "^1.3.3",
+        "stream-each": "^1.1.0",
+        "through2": "^2.0.0"
+      }
+    },
+    "mixin-deep": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
+      "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==",
+      "dev": true,
+      "requires": {
+        "for-in": "^1.0.2",
+        "is-extendable": "^1.0.1"
+      },
+      "dependencies": {
+        "is-extendable": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+          "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+          "dev": true,
+          "requires": {
+            "is-plain-object": "^2.0.4"
+          }
+        }
+      }
+    },
+    "mixin-object": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz",
+      "integrity": "sha1-T7lJRB2rGCVA8f4DW6YOGUel5X4=",
+      "dev": true,
+      "requires": {
+        "for-in": "^0.1.3",
+        "is-extendable": "^0.1.1"
+      },
+      "dependencies": {
+        "for-in": {
+          "version": "0.1.8",
+          "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz",
+          "integrity": "sha1-2Hc5COMSVhCZUrH9ubP6hn0ndeE=",
+          "dev": true
+        }
+      }
+    },
+    "mkdirp": {
+      "version": "0.5.1",
+      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+      "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
+      "dev": true,
+      "requires": {
+        "minimist": "0.0.8"
+      }
+    },
+    "move-concurrently": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
+      "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=",
+      "dev": true,
+      "requires": {
+        "aproba": "^1.1.1",
+        "copy-concurrently": "^1.0.0",
+        "fs-write-stream-atomic": "^1.0.8",
+        "mkdirp": "^0.5.1",
+        "rimraf": "^2.5.4",
+        "run-queue": "^1.0.3"
+      }
+    },
+    "ms": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+      "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+      "dev": true
+    },
+    "multicast-dns": {
+      "version": "6.2.3",
+      "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz",
+      "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==",
+      "dev": true,
+      "requires": {
+        "dns-packet": "^1.3.1",
+        "thunky": "^1.0.2"
+      }
+    },
+    "multicast-dns-service-types": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz",
+      "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=",
+      "dev": true
+    },
+    "mute-stream": {
+      "version": "0.0.7",
+      "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz",
+      "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=",
+      "dev": true
+    },
+    "nan": {
+      "version": "2.14.0",
+      "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz",
+      "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==",
+      "dev": true,
+      "optional": true
+    },
+    "nanomatch": {
+      "version": "1.2.13",
+      "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
+      "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==",
+      "dev": true,
+      "requires": {
+        "arr-diff": "^4.0.0",
+        "array-unique": "^0.3.2",
+        "define-property": "^2.0.2",
+        "extend-shallow": "^3.0.2",
+        "fragment-cache": "^0.2.1",
+        "is-windows": "^1.0.2",
+        "kind-of": "^6.0.2",
+        "object.pick": "^1.3.0",
+        "regex-not": "^1.0.0",
+        "snapdragon": "^0.8.1",
+        "to-regex": "^3.0.1"
+      }
+    },
+    "negotiator": {
+      "version": "0.6.2",
+      "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
+      "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==",
+      "dev": true
+    },
+    "neo-async": {
+      "version": "2.6.1",
+      "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz",
+      "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==",
+      "dev": true
+    },
+    "ng-click-outside": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/ng-click-outside/-/ng-click-outside-5.0.0.tgz",
+      "integrity": "sha512-b6US9O35XdwOQZFAB8mH2eu+U/9PRTF24Hjn21GNZ+T2CLUCKC2wNGxJstT8rEDEqGbcomQQGczHTyr07PF+6g=="
+    },
+    "ngx-cookie-service": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/ngx-cookie-service/-/ngx-cookie-service-2.2.0.tgz",
+      "integrity": "sha512-2kaC1itlEMxiMAPJ320hOpcwU9vhvjbKQCZ1Go6bGhYjJtqG7eYvhNP7mM9IhFz1/afG2tBryJPySWmFUGhRpA=="
+    },
+    "nice-try": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
+      "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
+      "dev": true
+    },
+    "node-forge": {
+      "version": "0.7.5",
+      "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.5.tgz",
+      "integrity": "sha512-MmbQJ2MTESTjt3Gi/3yG1wGpIMhUfcIypUCGtTizFR9IiccFwxSpfp0vtIZlkFclEqERemxfnSdZEMR9VqqEFQ==",
+      "dev": true
+    },
+    "node-gyp": {
+      "version": "3.8.0",
+      "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz",
+      "integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "fstream": "^1.0.0",
+        "glob": "^7.0.3",
+        "graceful-fs": "^4.1.2",
+        "mkdirp": "^0.5.0",
+        "nopt": "2 || 3",
+        "npmlog": "0 || 1 || 2 || 3 || 4",
+        "osenv": "0",
+        "request": "^2.87.0",
+        "rimraf": "2",
+        "semver": "~5.3.0",
+        "tar": "^2.0.0",
+        "which": "1"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "5.3.0",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
+          "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=",
+          "dev": true,
+          "optional": true
+        }
+      }
+    },
+    "node-libs-browser": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz",
+      "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==",
+      "dev": true,
+      "requires": {
+        "assert": "^1.1.1",
+        "browserify-zlib": "^0.2.0",
+        "buffer": "^4.3.0",
+        "console-browserify": "^1.1.0",
+        "constants-browserify": "^1.0.0",
+        "crypto-browserify": "^3.11.0",
+        "domain-browser": "^1.1.1",
+        "events": "^3.0.0",
+        "https-browserify": "^1.0.0",
+        "os-browserify": "^0.3.0",
+        "path-browserify": "0.0.1",
+        "process": "^0.11.10",
+        "punycode": "^1.2.4",
+        "querystring-es3": "^0.2.0",
+        "readable-stream": "^2.3.3",
+        "stream-browserify": "^2.0.1",
+        "stream-http": "^2.7.2",
+        "string_decoder": "^1.0.0",
+        "timers-browserify": "^2.0.4",
+        "tty-browserify": "0.0.0",
+        "url": "^0.11.0",
+        "util": "^0.11.0",
+        "vm-browserify": "^1.0.1"
+      },
+      "dependencies": {
+        "punycode": {
+          "version": "1.4.1",
+          "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+          "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
+          "dev": true
+        }
+      }
+    },
+    "node-releases": {
+      "version": "1.1.25",
+      "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.25.tgz",
+      "integrity": "sha512-fI5BXuk83lKEoZDdH3gRhtsNgh05/wZacuXkgbiYkceE7+QIMXOg98n9ZV7mz27B+kFHnqHcUpscZZlGRSmTpQ==",
+      "dev": true,
+      "requires": {
+        "semver": "^5.3.0"
+      }
+    },
+    "node-sass": {
+      "version": "4.9.3",
+      "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.9.3.tgz",
+      "integrity": "sha512-XzXyGjO+84wxyH7fV6IwBOTrEBe2f0a6SBze9QWWYR/cL74AcQUks2AsqcCZenl/Fp/JVbuEaLpgrLtocwBUww==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "async-foreach": "^0.1.3",
+        "chalk": "^1.1.1",
+        "cross-spawn": "^3.0.0",
+        "gaze": "^1.0.0",
+        "get-stdin": "^4.0.1",
+        "glob": "^7.0.3",
+        "in-publish": "^2.0.0",
+        "lodash.assign": "^4.2.0",
+        "lodash.clonedeep": "^4.3.2",
+        "lodash.mergewith": "^4.6.0",
+        "meow": "^3.7.0",
+        "mkdirp": "^0.5.1",
+        "nan": "^2.10.0",
+        "node-gyp": "^3.8.0",
+        "npmlog": "^4.0.0",
+        "request": "2.87.0",
+        "sass-graph": "^2.2.4",
+        "stdout-stream": "^1.4.0",
+        "true-case-path": "^1.0.2"
+      },
+      "dependencies": {
+        "ajv": {
+          "version": "5.5.2",
+          "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
+          "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "co": "^4.6.0",
+            "fast-deep-equal": "^1.0.0",
+            "fast-json-stable-stringify": "^2.0.0",
+            "json-schema-traverse": "^0.3.0"
+          }
+        },
+        "ansi-styles": {
+          "version": "2.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+          "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+          "dev": true,
+          "optional": true
+        },
+        "chalk": {
+          "version": "1.1.3",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "ansi-styles": "^2.2.1",
+            "escape-string-regexp": "^1.0.2",
+            "has-ansi": "^2.0.0",
+            "strip-ansi": "^3.0.0",
+            "supports-color": "^2.0.0"
+          }
+        },
+        "fast-deep-equal": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
+          "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=",
+          "dev": true,
+          "optional": true
+        },
+        "har-validator": {
+          "version": "5.0.3",
+          "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz",
+          "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "ajv": "^5.1.0",
+            "har-schema": "^2.0.0"
+          }
+        },
+        "json-schema-traverse": {
+          "version": "0.3.1",
+          "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
+          "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=",
+          "dev": true,
+          "optional": true
+        },
+        "oauth-sign": {
+          "version": "0.8.2",
+          "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz",
+          "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=",
+          "dev": true,
+          "optional": true
+        },
+        "punycode": {
+          "version": "1.4.1",
+          "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+          "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
+          "dev": true,
+          "optional": true
+        },
+        "request": {
+          "version": "2.87.0",
+          "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz",
+          "integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "aws-sign2": "~0.7.0",
+            "aws4": "^1.6.0",
+            "caseless": "~0.12.0",
+            "combined-stream": "~1.0.5",
+            "extend": "~3.0.1",
+            "forever-agent": "~0.6.1",
+            "form-data": "~2.3.1",
+            "har-validator": "~5.0.3",
+            "http-signature": "~1.2.0",
+            "is-typedarray": "~1.0.0",
+            "isstream": "~0.1.2",
+            "json-stringify-safe": "~5.0.1",
+            "mime-types": "~2.1.17",
+            "oauth-sign": "~0.8.2",
+            "performance-now": "^2.1.0",
+            "qs": "~6.5.1",
+            "safe-buffer": "^5.1.1",
+            "tough-cookie": "~2.3.3",
+            "tunnel-agent": "^0.6.0",
+            "uuid": "^3.1.0"
+          }
+        },
+        "supports-color": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+          "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+          "dev": true,
+          "optional": true
+        },
+        "tough-cookie": {
+          "version": "2.3.4",
+          "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz",
+          "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "punycode": "^1.4.1"
+          }
+        }
+      }
+    },
+    "nopt": {
+      "version": "3.0.6",
+      "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
+      "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=",
+      "dev": true,
+      "requires": {
+        "abbrev": "1"
+      }
+    },
+    "normalize-package-data": {
+      "version": "2.5.0",
+      "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
+      "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+      "dev": true,
+      "requires": {
+        "hosted-git-info": "^2.1.4",
+        "resolve": "^1.10.0",
+        "semver": "2 || 3 || 4 || 5",
+        "validate-npm-package-license": "^3.0.1"
+      },
+      "dependencies": {
+        "resolve": {
+          "version": "1.11.1",
+          "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz",
+          "integrity": "sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==",
+          "dev": true,
+          "requires": {
+            "path-parse": "^1.0.6"
+          }
+        }
+      }
+    },
+    "normalize-path": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
+      "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
+      "dev": true,
+      "requires": {
+        "remove-trailing-separator": "^1.0.1"
+      }
+    },
+    "normalize-range": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz",
+      "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=",
+      "dev": true
+    },
+    "npm-package-arg": {
+      "version": "6.1.0",
+      "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.0.tgz",
+      "integrity": "sha512-zYbhP2k9DbJhA0Z3HKUePUgdB1x7MfIfKssC+WLPFMKTBZKpZh5m13PgexJjCq6KW7j17r0jHWcCpxEqnnncSA==",
+      "dev": true,
+      "requires": {
+        "hosted-git-info": "^2.6.0",
+        "osenv": "^0.1.5",
+        "semver": "^5.5.0",
+        "validate-npm-package-name": "^3.0.0"
+      }
+    },
+    "npm-registry-client": {
+      "version": "8.6.0",
+      "resolved": "https://registry.npmjs.org/npm-registry-client/-/npm-registry-client-8.6.0.tgz",
+      "integrity": "sha512-Qs6P6nnopig+Y8gbzpeN/dkt+n7IyVd8f45NTMotGk6Qo7GfBmzwYx6jRLoOOgKiMnaQfYxsuyQlD8Mc3guBhg==",
+      "dev": true,
+      "requires": {
+        "concat-stream": "^1.5.2",
+        "graceful-fs": "^4.1.6",
+        "normalize-package-data": "~1.0.1 || ^2.0.0",
+        "npm-package-arg": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0",
+        "npmlog": "2 || ^3.1.0 || ^4.0.0",
+        "once": "^1.3.3",
+        "request": "^2.74.0",
+        "retry": "^0.10.0",
+        "safe-buffer": "^5.1.1",
+        "semver": "2 >=2.2.1 || 3.x || 4 || 5",
+        "slide": "^1.1.3",
+        "ssri": "^5.2.4"
+      }
+    },
+    "npm-run-path": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
+      "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
+      "dev": true,
+      "requires": {
+        "path-key": "^2.0.0"
+      }
+    },
+    "npmlog": {
+      "version": "4.1.2",
+      "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
+      "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
+      "dev": true,
+      "requires": {
+        "are-we-there-yet": "~1.1.2",
+        "console-control-strings": "~1.1.0",
+        "gauge": "~2.7.3",
+        "set-blocking": "~2.0.0"
+      }
+    },
+    "null-check": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/null-check/-/null-check-1.0.0.tgz",
+      "integrity": "sha1-l33/1xdgErnsMNKjnbXPcqBDnt0=",
+      "dev": true
+    },
+    "num2fraction": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz",
+      "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=",
+      "dev": true
+    },
+    "number-is-nan": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
+      "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
+      "dev": true
+    },
+    "oauth-sign": {
+      "version": "0.9.0",
+      "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
+      "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
+      "dev": true
+    },
+    "object-assign": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+      "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
+      "dev": true
+    },
+    "object-component": {
+      "version": "0.0.3",
+      "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz",
+      "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=",
+      "dev": true
+    },
+    "object-copy": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
+      "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=",
+      "dev": true,
+      "requires": {
+        "copy-descriptor": "^0.1.0",
+        "define-property": "^0.2.5",
+        "kind-of": "^3.0.3"
+      },
+      "dependencies": {
+        "define-property": {
+          "version": "0.2.5",
+          "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+          "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+          "dev": true,
+          "requires": {
+            "is-descriptor": "^0.1.0"
+          }
+        },
+        "kind-of": {
+          "version": "3.2.2",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+          "dev": true,
+          "requires": {
+            "is-buffer": "^1.1.5"
+          }
+        }
+      }
+    },
+    "object-visit": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
+      "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=",
+      "dev": true,
+      "requires": {
+        "isobject": "^3.0.0"
+      }
+    },
+    "object.omit": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz",
+      "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=",
+      "dev": true,
+      "requires": {
+        "for-own": "^0.1.4",
+        "is-extendable": "^0.1.1"
+      },
+      "dependencies": {
+        "for-own": {
+          "version": "0.1.5",
+          "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz",
+          "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=",
+          "dev": true,
+          "requires": {
+            "for-in": "^1.0.1"
+          }
+        }
+      }
+    },
+    "object.pick": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
+      "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=",
+      "dev": true,
+      "requires": {
+        "isobject": "^3.0.1"
+      }
+    },
+    "obuf": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz",
+      "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==",
+      "dev": true
+    },
+    "on-finished": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+      "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
+      "dev": true,
+      "requires": {
+        "ee-first": "1.1.1"
+      }
+    },
+    "on-headers": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
+      "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==",
+      "dev": true
+    },
+    "once": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+      "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+      "dev": true,
+      "requires": {
+        "wrappy": "1"
+      }
+    },
+    "onetime": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
+      "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=",
+      "dev": true,
+      "requires": {
+        "mimic-fn": "^1.0.0"
+      },
+      "dependencies": {
+        "mimic-fn": {
+          "version": "1.2.0",
+          "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
+          "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
+          "dev": true
+        }
+      }
+    },
+    "opn": {
+      "version": "5.3.0",
+      "resolved": "https://registry.npmjs.org/opn/-/opn-5.3.0.tgz",
+      "integrity": "sha512-bYJHo/LOmoTd+pfiYhfZDnf9zekVJrY+cnS2a5F2x+w5ppvTqObojTP7WiFG+kVZs9Inw+qQ/lw7TroWwhdd2g==",
+      "dev": true,
+      "requires": {
+        "is-wsl": "^1.1.0"
+      }
+    },
+    "optimist": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
+      "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=",
+      "dev": true,
+      "requires": {
+        "minimist": "~0.0.1",
+        "wordwrap": "~0.0.2"
+      },
+      "dependencies": {
+        "wordwrap": {
+          "version": "0.0.3",
+          "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
+          "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=",
+          "dev": true
+        }
+      }
+    },
+    "optionator": {
+      "version": "0.8.2",
+      "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz",
+      "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=",
+      "dev": true,
+      "requires": {
+        "deep-is": "~0.1.3",
+        "fast-levenshtein": "~2.0.4",
+        "levn": "~0.3.0",
+        "prelude-ls": "~1.1.2",
+        "type-check": "~0.3.2",
+        "wordwrap": "~1.0.0"
+      }
+    },
+    "original": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz",
+      "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==",
+      "dev": true,
+      "requires": {
+        "url-parse": "^1.4.3"
+      }
+    },
+    "os-browserify": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz",
+      "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=",
+      "dev": true
+    },
+    "os-homedir": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
+      "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
+      "dev": true
+    },
+    "os-locale": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
+      "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "lcid": "^1.0.0"
+      }
+    },
+    "os-tmpdir": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+      "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
+      "dev": true
+    },
+    "osenv": {
+      "version": "0.1.5",
+      "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
+      "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
+      "dev": true,
+      "requires": {
+        "os-homedir": "^1.0.0",
+        "os-tmpdir": "^1.0.0"
+      }
+    },
+    "p-defer": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz",
+      "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=",
+      "dev": true
+    },
+    "p-finally": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
+      "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=",
+      "dev": true
+    },
+    "p-is-promise": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz",
+      "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==",
+      "dev": true
+    },
+    "p-limit": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
+      "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
+      "dev": true,
+      "requires": {
+        "p-try": "^1.0.0"
+      }
+    },
+    "p-locate": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
+      "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
+      "dev": true,
+      "requires": {
+        "p-limit": "^1.1.0"
+      }
+    },
+    "p-map": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz",
+      "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==",
+      "dev": true
+    },
+    "p-try": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
+      "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
+      "dev": true
+    },
+    "pako": {
+      "version": "1.0.10",
+      "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.10.tgz",
+      "integrity": "sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==",
+      "dev": true
+    },
+    "parallel-transform": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz",
+      "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=",
+      "dev": true,
+      "requires": {
+        "cyclist": "~0.2.2",
+        "inherits": "^2.0.3",
+        "readable-stream": "^2.1.5"
+      }
+    },
+    "parse-asn1": {
+      "version": "5.1.4",
+      "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.4.tgz",
+      "integrity": "sha512-Qs5duJcuvNExRfFZ99HDD3z4mAi3r9Wl/FOjEOijlxwCZs7E7mW2vjTpgQ4J8LpTF8x5v+1Vn5UQFejmWT11aw==",
+      "dev": true,
+      "requires": {
+        "asn1.js": "^4.0.0",
+        "browserify-aes": "^1.0.0",
+        "create-hash": "^1.1.0",
+        "evp_bytestokey": "^1.0.0",
+        "pbkdf2": "^3.0.3",
+        "safe-buffer": "^5.1.1"
+      }
+    },
+    "parse-glob": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz",
+      "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=",
+      "dev": true,
+      "requires": {
+        "glob-base": "^0.3.0",
+        "is-dotfile": "^1.0.0",
+        "is-extglob": "^1.0.0",
+        "is-glob": "^2.0.0"
+      },
+      "dependencies": {
+        "is-extglob": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
+          "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
+          "dev": true
+        },
+        "is-glob": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
+          "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
+          "dev": true,
+          "requires": {
+            "is-extglob": "^1.0.0"
+          }
+        }
+      }
+    },
+    "parse-json": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
+      "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
+      "dev": true,
+      "requires": {
+        "error-ex": "^1.2.0"
+      }
+    },
+    "parse5": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz",
+      "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==",
+      "dev": true
+    },
+    "parseqs": {
+      "version": "0.0.5",
+      "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz",
+      "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=",
+      "dev": true,
+      "requires": {
+        "better-assert": "~1.0.0"
+      }
+    },
+    "parseuri": {
+      "version": "0.0.5",
+      "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz",
+      "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=",
+      "dev": true,
+      "requires": {
+        "better-assert": "~1.0.0"
+      }
+    },
+    "parseurl": {
+      "version": "1.3.3",
+      "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+      "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+      "dev": true
+    },
+    "pascalcase": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
+      "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=",
+      "dev": true
+    },
+    "path-browserify": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz",
+      "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==",
+      "dev": true
+    },
+    "path-dirname": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
+      "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=",
+      "dev": true
+    },
+    "path-exists": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+      "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
+      "dev": true
+    },
+    "path-is-absolute": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+      "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+      "dev": true
+    },
+    "path-is-inside": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz",
+      "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=",
+      "dev": true
+    },
+    "path-key": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+      "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
+      "dev": true
+    },
+    "path-parse": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
+      "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
+      "dev": true
+    },
+    "path-to-regexp": {
+      "version": "0.1.7",
+      "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
+      "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=",
+      "dev": true
+    },
+    "path-type": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
+      "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
+      "dev": true,
+      "requires": {
+        "pify": "^3.0.0"
+      }
+    },
+    "pbkdf2": {
+      "version": "3.0.17",
+      "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz",
+      "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==",
+      "dev": true,
+      "requires": {
+        "create-hash": "^1.1.2",
+        "create-hmac": "^1.1.4",
+        "ripemd160": "^2.0.1",
+        "safe-buffer": "^5.0.1",
+        "sha.js": "^2.4.8"
+      }
+    },
+    "performance-now": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
+      "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
+      "dev": true
+    },
+    "pify": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+      "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+      "dev": true
+    },
+    "pinkie": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
+      "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
+      "dev": true
+    },
+    "pinkie-promise": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
+      "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
+      "dev": true,
+      "requires": {
+        "pinkie": "^2.0.0"
+      }
+    },
+    "pkg-dir": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz",
+      "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=",
+      "dev": true,
+      "requires": {
+        "find-up": "^2.1.0"
+      }
+    },
+    "portfinder": {
+      "version": "1.0.17",
+      "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.17.tgz",
+      "integrity": "sha512-syFcRIRzVI1BoEFOCaAiizwDolh1S1YXSodsVhncbhjzjZQulhczNRbqnUl9N31Q4dKGOXsNDqxC2BWBgSMqeQ==",
+      "dev": true,
+      "requires": {
+        "async": "^1.5.2",
+        "debug": "^2.2.0",
+        "mkdirp": "0.5.x"
+      }
+    },
+    "posix-character-classes": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
+      "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=",
+      "dev": true
+    },
+    "postcss": {
+      "version": "7.0.5",
+      "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.5.tgz",
+      "integrity": "sha512-HBNpviAUFCKvEh7NZhw1e8MBPivRszIiUnhrJ+sBFVSYSqubrzwX3KG51mYgcRHX8j/cAgZJedONZcm5jTBdgQ==",
+      "dev": true,
+      "requires": {
+        "chalk": "^2.4.1",
+        "source-map": "^0.6.1",
+        "supports-color": "^5.5.0"
+      },
+      "dependencies": {
+        "source-map": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+          "dev": true
+        }
+      }
+    },
+    "postcss-import": {
+      "version": "12.0.0",
+      "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-12.0.0.tgz",
+      "integrity": "sha512-3KqKRZcaZAvxbY8DVLdd81tG5uKzbUQuiWIvy0o0fzEC42bKacqPYFWbfCQyw6L4LWUaqPz/idvIdbhpgQ32eQ==",
+      "dev": true,
+      "requires": {
+        "postcss": "^7.0.1",
+        "postcss-value-parser": "^3.2.3",
+        "read-cache": "^1.0.0",
+        "resolve": "^1.1.7"
+      }
+    },
+    "postcss-load-config": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.1.0.tgz",
+      "integrity": "sha512-4pV3JJVPLd5+RueiVVB+gFOAa7GWc25XQcMp86Zexzke69mKf6Nx9LRcQywdz7yZI9n1udOxmLuAwTBypypF8Q==",
+      "dev": true,
+      "requires": {
+        "cosmiconfig": "^5.0.0",
+        "import-cwd": "^2.0.0"
+      }
+    },
+    "postcss-loader": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-3.0.0.tgz",
+      "integrity": "sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA==",
+      "dev": true,
+      "requires": {
+        "loader-utils": "^1.1.0",
+        "postcss": "^7.0.0",
+        "postcss-load-config": "^2.0.0",
+        "schema-utils": "^1.0.0"
+      }
+    },
+    "postcss-value-parser": {
+      "version": "3.3.1",
+      "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
+      "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
+      "dev": true
+    },
+    "prelude-ls": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
+      "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
+      "dev": true
+    },
+    "preserve": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz",
+      "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=",
+      "dev": true
+    },
+    "process": {
+      "version": "0.11.10",
+      "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
+      "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=",
+      "dev": true
+    },
+    "process-nextick-args": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+      "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
+      "dev": true
+    },
+    "promise": {
+      "version": "7.3.1",
+      "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
+      "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "asap": "~2.0.3"
+      }
+    },
+    "promise-inflight": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
+      "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=",
+      "dev": true
+    },
+    "protractor": {
+      "version": "5.4.2",
+      "resolved": "https://registry.npmjs.org/protractor/-/protractor-5.4.2.tgz",
+      "integrity": "sha512-zlIj64Cr6IOWP7RwxVeD8O4UskLYPoyIcg0HboWJL9T79F1F0VWtKkGTr/9GN6BKL+/Q/GmM7C9kFVCfDbP5sA==",
+      "dev": true,
+      "requires": {
+        "@types/q": "^0.0.32",
+        "@types/selenium-webdriver": "^3.0.0",
+        "blocking-proxy": "^1.0.0",
+        "browserstack": "^1.5.1",
+        "chalk": "^1.1.3",
+        "glob": "^7.0.3",
+        "jasmine": "2.8.0",
+        "jasminewd2": "^2.1.0",
+        "optimist": "~0.6.0",
+        "q": "1.4.1",
+        "saucelabs": "^1.5.0",
+        "selenium-webdriver": "3.6.0",
+        "source-map-support": "~0.4.0",
+        "webdriver-js-extender": "2.1.0",
+        "webdriver-manager": "^12.0.6"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "2.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+          "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+          "dev": true
+        },
+        "chalk": {
+          "version": "1.1.3",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^2.2.1",
+            "escape-string-regexp": "^1.0.2",
+            "has-ansi": "^2.0.0",
+            "strip-ansi": "^3.0.0",
+            "supports-color": "^2.0.0"
+          }
+        },
+        "del": {
+          "version": "2.2.2",
+          "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz",
+          "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=",
+          "dev": true,
+          "requires": {
+            "globby": "^5.0.0",
+            "is-path-cwd": "^1.0.0",
+            "is-path-in-cwd": "^1.0.0",
+            "object-assign": "^4.0.1",
+            "pify": "^2.0.0",
+            "pinkie-promise": "^2.0.0",
+            "rimraf": "^2.2.8"
+          }
+        },
+        "globby": {
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz",
+          "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=",
+          "dev": true,
+          "requires": {
+            "array-union": "^1.0.1",
+            "arrify": "^1.0.0",
+            "glob": "^7.0.3",
+            "object-assign": "^4.0.1",
+            "pify": "^2.0.0",
+            "pinkie-promise": "^2.0.0"
+          }
+        },
+        "minimist": {
+          "version": "1.2.0",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+          "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+          "dev": true
+        },
+        "pify": {
+          "version": "2.3.0",
+          "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+          "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+          "dev": true
+        },
+        "source-map": {
+          "version": "0.5.7",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+          "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+          "dev": true
+        },
+        "source-map-support": {
+          "version": "0.4.18",
+          "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz",
+          "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==",
+          "dev": true,
+          "requires": {
+            "source-map": "^0.5.6"
+          }
+        },
+        "supports-color": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+          "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+          "dev": true
+        },
+        "webdriver-manager": {
+          "version": "12.1.5",
+          "resolved": "https://registry.npmjs.org/webdriver-manager/-/webdriver-manager-12.1.5.tgz",
+          "integrity": "sha512-f1apDjMpZ8SHlXtXGzqBxOjV+WQcDRz5PN7pWScgjXS7vhUIFcM3V89Shetf4A04n8DDR2MxiVQq6JproFcRZw==",
+          "dev": true,
+          "requires": {
+            "adm-zip": "^0.4.9",
+            "chalk": "^1.1.1",
+            "del": "^2.2.0",
+            "glob": "^7.0.3",
+            "ini": "^1.3.4",
+            "minimist": "^1.2.0",
+            "q": "^1.4.1",
+            "request": "^2.87.0",
+            "rimraf": "^2.5.2",
+            "semver": "^5.3.0",
+            "xml2js": "^0.4.17"
+          }
+        }
+      }
+    },
+    "proxy-addr": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz",
+      "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==",
+      "dev": true,
+      "requires": {
+        "forwarded": "~0.1.2",
+        "ipaddr.js": "1.9.0"
+      }
+    },
+    "prr": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
+      "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=",
+      "dev": true
+    },
+    "pseudomap": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
+      "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
+      "dev": true
+    },
+    "psl": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/psl/-/psl-1.2.0.tgz",
+      "integrity": "sha512-GEn74ZffufCmkDDLNcl3uuyF/aSD6exEyh1v/ZSdAomB82t6G9hzJVRx0jBmLDW+VfZqks3aScmMw9DszwUalA==",
+      "dev": true
+    },
+    "public-encrypt": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz",
+      "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==",
+      "dev": true,
+      "requires": {
+        "bn.js": "^4.1.0",
+        "browserify-rsa": "^4.0.0",
+        "create-hash": "^1.1.0",
+        "parse-asn1": "^5.0.0",
+        "randombytes": "^2.0.1",
+        "safe-buffer": "^5.1.2"
+      }
+    },
+    "pump": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz",
+      "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==",
+      "dev": true,
+      "requires": {
+        "end-of-stream": "^1.1.0",
+        "once": "^1.3.1"
+      }
+    },
+    "pumpify": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz",
+      "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==",
+      "dev": true,
+      "requires": {
+        "duplexify": "^3.6.0",
+        "inherits": "^2.0.3",
+        "pump": "^2.0.0"
+      }
+    },
+    "punycode": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+      "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+      "dev": true
+    },
+    "q": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz",
+      "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=",
+      "dev": true
+    },
+    "qjobs": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz",
+      "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==",
+      "dev": true
+    },
+    "qs": {
+      "version": "6.5.2",
+      "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
+      "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
+      "dev": true
+    },
+    "querystring": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
+      "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=",
+      "dev": true
+    },
+    "querystring-es3": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz",
+      "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=",
+      "dev": true
+    },
+    "querystringify": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.1.tgz",
+      "integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==",
+      "dev": true
+    },
+    "randomatic": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz",
+      "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==",
+      "dev": true,
+      "requires": {
+        "is-number": "^4.0.0",
+        "kind-of": "^6.0.0",
+        "math-random": "^1.0.1"
+      },
+      "dependencies": {
+        "is-number": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz",
+          "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==",
+          "dev": true
+        }
+      }
+    },
+    "randombytes": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
+      "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+      "dev": true,
+      "requires": {
+        "safe-buffer": "^5.1.0"
+      }
+    },
+    "randomfill": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz",
+      "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==",
+      "dev": true,
+      "requires": {
+        "randombytes": "^2.0.5",
+        "safe-buffer": "^5.1.0"
+      }
+    },
+    "range-parser": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
+      "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
+      "dev": true
+    },
+    "raw-body": {
+      "version": "2.4.0",
+      "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
+      "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
+      "dev": true,
+      "requires": {
+        "bytes": "3.1.0",
+        "http-errors": "1.7.2",
+        "iconv-lite": "0.4.24",
+        "unpipe": "1.0.0"
+      },
+      "dependencies": {
+        "bytes": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
+          "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==",
+          "dev": true
+        }
+      }
+    },
+    "raw-loader": {
+      "version": "0.5.1",
+      "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-0.5.1.tgz",
+      "integrity": "sha1-DD0L6u2KAclm2Xh793goElKpeao=",
+      "dev": true
+    },
+    "read-cache": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
+      "integrity": "sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=",
+      "dev": true,
+      "requires": {
+        "pify": "^2.3.0"
+      },
+      "dependencies": {
+        "pify": {
+          "version": "2.3.0",
+          "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+          "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+          "dev": true
+        }
+      }
+    },
+    "read-pkg": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
+      "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
+      "dev": true,
+      "requires": {
+        "load-json-file": "^1.0.0",
+        "normalize-package-data": "^2.3.2",
+        "path-type": "^1.0.0"
+      },
+      "dependencies": {
+        "path-type": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
+          "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
+          "dev": true,
+          "requires": {
+            "graceful-fs": "^4.1.2",
+            "pify": "^2.0.0",
+            "pinkie-promise": "^2.0.0"
+          }
+        },
+        "pify": {
+          "version": "2.3.0",
+          "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+          "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+          "dev": true
+        }
+      }
+    },
+    "read-pkg-up": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
+      "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
+      "dev": true,
+      "requires": {
+        "find-up": "^1.0.0",
+        "read-pkg": "^1.0.0"
+      },
+      "dependencies": {
+        "find-up": {
+          "version": "1.1.2",
+          "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
+          "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
+          "dev": true,
+          "requires": {
+            "path-exists": "^2.0.0",
+            "pinkie-promise": "^2.0.0"
+          }
+        },
+        "path-exists": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
+          "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
+          "dev": true,
+          "requires": {
+            "pinkie-promise": "^2.0.0"
+          }
+        }
+      }
+    },
+    "readable-stream": {
+      "version": "2.3.6",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+      "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+      "dev": true,
+      "requires": {
+        "core-util-is": "~1.0.0",
+        "inherits": "~2.0.3",
+        "isarray": "~1.0.0",
+        "process-nextick-args": "~2.0.0",
+        "safe-buffer": "~5.1.1",
+        "string_decoder": "~1.1.1",
+        "util-deprecate": "~1.0.1"
+      }
+    },
+    "readdirp": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz",
+      "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "^4.1.11",
+        "micromatch": "^3.1.10",
+        "readable-stream": "^2.0.2"
+      }
+    },
+    "rechoir": {
+      "version": "0.6.2",
+      "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
+      "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=",
+      "dev": true,
+      "requires": {
+        "resolve": "^1.1.6"
+      }
+    },
+    "redent": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
+      "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "indent-string": "^2.1.0",
+        "strip-indent": "^1.0.1"
+      }
+    },
+    "reflect-metadata": {
+      "version": "0.1.13",
+      "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz",
+      "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==",
+      "dev": true
+    },
+    "regenerate": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz",
+      "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==",
+      "dev": true
+    },
+    "regenerator-runtime": {
+      "version": "0.11.1",
+      "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
+      "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==",
+      "dev": true
+    },
+    "regex-cache": {
+      "version": "0.4.4",
+      "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz",
+      "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==",
+      "dev": true,
+      "requires": {
+        "is-equal-shallow": "^0.1.3"
+      }
+    },
+    "regex-not": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
+      "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==",
+      "dev": true,
+      "requires": {
+        "extend-shallow": "^3.0.2",
+        "safe-regex": "^1.1.0"
+      }
+    },
+    "regexpu-core": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz",
+      "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=",
+      "dev": true,
+      "requires": {
+        "regenerate": "^1.2.1",
+        "regjsgen": "^0.2.0",
+        "regjsparser": "^0.1.4"
+      }
+    },
+    "regjsgen": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz",
+      "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=",
+      "dev": true
+    },
+    "regjsparser": {
+      "version": "0.1.5",
+      "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz",
+      "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=",
+      "dev": true,
+      "requires": {
+        "jsesc": "~0.5.0"
+      },
+      "dependencies": {
+        "jsesc": {
+          "version": "0.5.0",
+          "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
+          "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=",
+          "dev": true
+        }
+      }
+    },
+    "remove-trailing-separator": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
+      "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=",
+      "dev": true
+    },
+    "repeat-element": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz",
+      "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==",
+      "dev": true
+    },
+    "repeat-string": {
+      "version": "1.6.1",
+      "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
+      "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=",
+      "dev": true
+    },
+    "repeating": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
+      "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
+      "dev": true,
+      "requires": {
+        "is-finite": "^1.0.0"
+      }
+    },
+    "request": {
+      "version": "2.88.0",
+      "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
+      "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
+      "dev": true,
+      "requires": {
+        "aws-sign2": "~0.7.0",
+        "aws4": "^1.8.0",
+        "caseless": "~0.12.0",
+        "combined-stream": "~1.0.6",
+        "extend": "~3.0.2",
+        "forever-agent": "~0.6.1",
+        "form-data": "~2.3.2",
+        "har-validator": "~5.1.0",
+        "http-signature": "~1.2.0",
+        "is-typedarray": "~1.0.0",
+        "isstream": "~0.1.2",
+        "json-stringify-safe": "~5.0.1",
+        "mime-types": "~2.1.19",
+        "oauth-sign": "~0.9.0",
+        "performance-now": "^2.1.0",
+        "qs": "~6.5.2",
+        "safe-buffer": "^5.1.2",
+        "tough-cookie": "~2.4.3",
+        "tunnel-agent": "^0.6.0",
+        "uuid": "^3.3.2"
+      }
+    },
+    "require-directory": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+      "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
+      "dev": true
+    },
+    "require-main-filename": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
+      "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=",
+      "dev": true
+    },
+    "requires-port": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
+      "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
+      "dev": true
+    },
+    "resolve": {
+      "version": "1.1.7",
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
+      "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=",
+      "dev": true
+    },
+    "resolve-cwd": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz",
+      "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=",
+      "dev": true,
+      "requires": {
+        "resolve-from": "^3.0.0"
+      }
+    },
+    "resolve-from": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
+      "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=",
+      "dev": true
+    },
+    "resolve-url": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
+      "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=",
+      "dev": true
+    },
+    "restore-cursor": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
+      "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=",
+      "dev": true,
+      "requires": {
+        "onetime": "^2.0.0",
+        "signal-exit": "^3.0.2"
+      }
+    },
+    "ret": {
+      "version": "0.1.15",
+      "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
+      "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
+      "dev": true
+    },
+    "retry": {
+      "version": "0.10.1",
+      "resolved": "https://registry.npmjs.org/retry/-/retry-0.10.1.tgz",
+      "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=",
+      "dev": true
+    },
+    "rfdc": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.4.tgz",
+      "integrity": "sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug==",
+      "dev": true
+    },
+    "rimraf": {
+      "version": "2.6.3",
+      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
+      "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
+      "dev": true,
+      "requires": {
+        "glob": "^7.1.3"
+      }
+    },
+    "ripemd160": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz",
+      "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==",
+      "dev": true,
+      "requires": {
+        "hash-base": "^3.0.0",
+        "inherits": "^2.0.1"
+      }
+    },
+    "run-async": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz",
+      "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=",
+      "dev": true,
+      "requires": {
+        "is-promise": "^2.1.0"
+      }
+    },
+    "run-queue": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz",
+      "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=",
+      "dev": true,
+      "requires": {
+        "aproba": "^1.1.1"
+      }
+    },
+    "rxjs": {
+      "version": "6.3.3",
+      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz",
+      "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==",
+      "requires": {
+        "tslib": "^1.9.0"
+      }
+    },
+    "rxjs-compat": {
+      "version": "6.5.2",
+      "resolved": "https://registry.npmjs.org/rxjs-compat/-/rxjs-compat-6.5.2.tgz",
+      "integrity": "sha512-TRMkTp4FgSxE2HtGvxmgRukh3JqdFM7ejAj1Ti/VdodbPGfWvZR5+KdLKRV9jVDFyu2SknM8RD+PR54KGnoLjg=="
+    },
+    "safe-buffer": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+      "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+      "dev": true
+    },
+    "safe-regex": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
+      "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
+      "dev": true,
+      "requires": {
+        "ret": "~0.1.10"
+      }
+    },
+    "safer-buffer": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+      "dev": true
+    },
+    "sass-graph": {
+      "version": "2.2.4",
+      "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz",
+      "integrity": "sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k=",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "glob": "^7.0.0",
+        "lodash": "^4.0.0",
+        "scss-tokenizer": "^0.2.3",
+        "yargs": "^7.0.0"
+      }
+    },
+    "sass-loader": {
+      "version": "7.1.0",
+      "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-7.1.0.tgz",
+      "integrity": "sha512-+G+BKGglmZM2GUSfT9TLuEp6tzehHPjAMoRRItOojWIqIGPloVCMhNIQuG639eJ+y033PaGTSjLaTHts8Kw79w==",
+      "dev": true,
+      "requires": {
+        "clone-deep": "^2.0.1",
+        "loader-utils": "^1.0.1",
+        "lodash.tail": "^4.1.1",
+        "neo-async": "^2.5.0",
+        "pify": "^3.0.0",
+        "semver": "^5.5.0"
+      }
+    },
+    "saucelabs": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/saucelabs/-/saucelabs-1.5.0.tgz",
+      "integrity": "sha512-jlX3FGdWvYf4Q3LFfFWS1QvPg3IGCGWxIc8QBFdPTbpTJnt/v17FHXYVAn7C8sHf1yUXo2c7yIM0isDryfYtHQ==",
+      "dev": true,
+      "requires": {
+        "https-proxy-agent": "^2.2.1"
+      }
+    },
+    "sax": {
+      "version": "0.5.8",
+      "resolved": "https://registry.npmjs.org/sax/-/sax-0.5.8.tgz",
+      "integrity": "sha1-1HLbIo6zMcJQaw6MFVJK25OdEsE=",
+      "dev": true
+    },
+    "schema-utils": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
+      "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
+      "dev": true,
+      "requires": {
+        "ajv": "^6.1.0",
+        "ajv-errors": "^1.0.0",
+        "ajv-keywords": "^3.1.0"
+      }
+    },
+    "scss-tokenizer": {
+      "version": "0.2.3",
+      "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz",
+      "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "js-base64": "^2.1.8",
+        "source-map": "^0.4.2"
+      },
+      "dependencies": {
+        "source-map": {
+          "version": "0.4.4",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
+          "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "amdefine": ">=0.0.4"
+          }
+        }
+      }
+    },
+    "select-hose": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
+      "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=",
+      "dev": true
+    },
+    "selenium-webdriver": {
+      "version": "3.6.0",
+      "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-3.6.0.tgz",
+      "integrity": "sha512-WH7Aldse+2P5bbFBO4Gle/nuQOdVwpHMTL6raL3uuBj/vPG07k6uzt3aiahu352ONBr5xXh0hDlM3LhtXPOC4Q==",
+      "dev": true,
+      "requires": {
+        "jszip": "^3.1.3",
+        "rimraf": "^2.5.4",
+        "tmp": "0.0.30",
+        "xml2js": "^0.4.17"
+      },
+      "dependencies": {
+        "tmp": {
+          "version": "0.0.30",
+          "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.30.tgz",
+          "integrity": "sha1-ckGdSovn1s51FI/YsyTlk6cRwu0=",
+          "dev": true,
+          "requires": {
+            "os-tmpdir": "~1.0.1"
+          }
+        }
+      }
+    },
+    "selfsigned": {
+      "version": "1.10.4",
+      "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.4.tgz",
+      "integrity": "sha512-9AukTiDmHXGXWtWjembZ5NDmVvP2695EtpgbCsxCa68w3c88B+alqbmZ4O3hZ4VWGXeGWzEVdvqgAJD8DQPCDw==",
+      "dev": true,
+      "requires": {
+        "node-forge": "0.7.5"
+      }
+    },
+    "semver": {
+      "version": "5.5.1",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz",
+      "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==",
+      "dev": true
+    },
+    "semver-dsl": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/semver-dsl/-/semver-dsl-1.0.1.tgz",
+      "integrity": "sha1-02eN5VVeimH2Ke7QJTZq5fJzQKA=",
+      "dev": true,
+      "requires": {
+        "semver": "^5.3.0"
+      }
+    },
+    "semver-intersect": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/semver-intersect/-/semver-intersect-1.4.0.tgz",
+      "integrity": "sha512-d8fvGg5ycKAq0+I6nfWeCx6ffaWJCsBYU0H2Rq56+/zFePYfT8mXkB3tWBSjR5BerkHNZ5eTPIk1/LBYas35xQ==",
+      "dev": true,
+      "requires": {
+        "semver": "^5.0.0"
+      }
+    },
+    "send": {
+      "version": "0.17.1",
+      "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
+      "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
+      "dev": true,
+      "requires": {
+        "debug": "2.6.9",
+        "depd": "~1.1.2",
+        "destroy": "~1.0.4",
+        "encodeurl": "~1.0.2",
+        "escape-html": "~1.0.3",
+        "etag": "~1.8.1",
+        "fresh": "0.5.2",
+        "http-errors": "~1.7.2",
+        "mime": "1.6.0",
+        "ms": "2.1.1",
+        "on-finished": "~2.3.0",
+        "range-parser": "~1.2.1",
+        "statuses": "~1.5.0"
+      },
+      "dependencies": {
+        "ms": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+          "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
+          "dev": true
+        }
+      }
+    },
+    "serialize-javascript": {
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.7.0.tgz",
+      "integrity": "sha512-ke8UG8ulpFOxO8f8gRYabHQe/ZntKlcig2Mp+8+URDP1D8vJZ0KUt7LYo07q25Z/+JVSgpr/cui9PIp5H6/+nA==",
+      "dev": true
+    },
+    "serve-index": {
+      "version": "1.9.1",
+      "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz",
+      "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=",
+      "dev": true,
+      "requires": {
+        "accepts": "~1.3.4",
+        "batch": "0.6.1",
+        "debug": "2.6.9",
+        "escape-html": "~1.0.3",
+        "http-errors": "~1.6.2",
+        "mime-types": "~2.1.17",
+        "parseurl": "~1.3.2"
+      },
+      "dependencies": {
+        "http-errors": {
+          "version": "1.6.3",
+          "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
+          "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
+          "dev": true,
+          "requires": {
+            "depd": "~1.1.2",
+            "inherits": "2.0.3",
+            "setprototypeof": "1.1.0",
+            "statuses": ">= 1.4.0 < 2"
+          }
+        },
+        "inherits": {
+          "version": "2.0.3",
+          "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+          "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
+          "dev": true
+        },
+        "setprototypeof": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
+          "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==",
+          "dev": true
+        }
+      }
+    },
+    "serve-static": {
+      "version": "1.14.1",
+      "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz",
+      "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==",
+      "dev": true,
+      "requires": {
+        "encodeurl": "~1.0.2",
+        "escape-html": "~1.0.3",
+        "parseurl": "~1.3.3",
+        "send": "0.17.1"
+      }
+    },
+    "set-blocking": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+      "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
+      "dev": true
+    },
+    "set-immediate-shim": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz",
+      "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=",
+      "dev": true
+    },
+    "set-value": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
+      "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==",
+      "dev": true,
+      "requires": {
+        "extend-shallow": "^2.0.1",
+        "is-extendable": "^0.1.1",
+        "is-plain-object": "^2.0.3",
+        "split-string": "^3.0.1"
+      },
+      "dependencies": {
+        "extend-shallow": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+          "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+          "dev": true,
+          "requires": {
+            "is-extendable": "^0.1.0"
+          }
+        }
+      }
+    },
+    "setimmediate": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
+      "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=",
+      "dev": true
+    },
+    "setprototypeof": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
+      "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==",
+      "dev": true
+    },
+    "sha.js": {
+      "version": "2.4.11",
+      "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
+      "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
+      "dev": true,
+      "requires": {
+        "inherits": "^2.0.1",
+        "safe-buffer": "^5.0.1"
+      }
+    },
+    "shallow-clone": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-1.0.0.tgz",
+      "integrity": "sha512-oeXreoKR/SyNJtRJMAKPDSvd28OqEwG4eR/xc856cRGBII7gX9lvAqDxusPm0846z/w/hWYjI1NpKwJ00NHzRA==",
+      "dev": true,
+      "requires": {
+        "is-extendable": "^0.1.1",
+        "kind-of": "^5.0.0",
+        "mixin-object": "^2.0.1"
+      },
+      "dependencies": {
+        "kind-of": {
+          "version": "5.1.0",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+          "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+          "dev": true
+        }
+      }
+    },
+    "shebang-command": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+      "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+      "dev": true,
+      "requires": {
+        "shebang-regex": "^1.0.0"
+      }
+    },
+    "shebang-regex": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+      "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
+      "dev": true
+    },
+    "shelljs": {
+      "version": "0.8.3",
+      "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.3.tgz",
+      "integrity": "sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A==",
+      "dev": true,
+      "requires": {
+        "glob": "^7.0.0",
+        "interpret": "^1.0.0",
+        "rechoir": "^0.6.2"
+      }
+    },
+    "signal-exit": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
+      "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
+      "dev": true
+    },
+    "slash": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
+      "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=",
+      "dev": true
+    },
+    "slide": {
+      "version": "1.1.6",
+      "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz",
+      "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=",
+      "dev": true
+    },
+    "snapdragon": {
+      "version": "0.8.2",
+      "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
+      "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==",
+      "dev": true,
+      "requires": {
+        "base": "^0.11.1",
+        "debug": "^2.2.0",
+        "define-property": "^0.2.5",
+        "extend-shallow": "^2.0.1",
+        "map-cache": "^0.2.2",
+        "source-map": "^0.5.6",
+        "source-map-resolve": "^0.5.0",
+        "use": "^3.1.0"
+      },
+      "dependencies": {
+        "define-property": {
+          "version": "0.2.5",
+          "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+          "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+          "dev": true,
+          "requires": {
+            "is-descriptor": "^0.1.0"
+          }
+        },
+        "extend-shallow": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+          "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+          "dev": true,
+          "requires": {
+            "is-extendable": "^0.1.0"
+          }
+        },
+        "source-map": {
+          "version": "0.5.7",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+          "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+          "dev": true
+        }
+      }
+    },
+    "snapdragon-node": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz",
+      "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==",
+      "dev": true,
+      "requires": {
+        "define-property": "^1.0.0",
+        "isobject": "^3.0.0",
+        "snapdragon-util": "^3.0.1"
+      },
+      "dependencies": {
+        "define-property": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+          "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+          "dev": true,
+          "requires": {
+            "is-descriptor": "^1.0.0"
+          }
+        },
+        "is-accessor-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+          "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+          "dev": true,
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-data-descriptor": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+          "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+          "dev": true,
+          "requires": {
+            "kind-of": "^6.0.0"
+          }
+        },
+        "is-descriptor": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+          "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+          "dev": true,
+          "requires": {
+            "is-accessor-descriptor": "^1.0.0",
+            "is-data-descriptor": "^1.0.0",
+            "kind-of": "^6.0.2"
+          }
+        }
+      }
+    },
+    "snapdragon-util": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz",
+      "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==",
+      "dev": true,
+      "requires": {
+        "kind-of": "^3.2.0"
+      },
+      "dependencies": {
+        "kind-of": {
+          "version": "3.2.2",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+          "dev": true,
+          "requires": {
+            "is-buffer": "^1.1.5"
+          }
+        }
+      }
+    },
+    "socket.io": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz",
+      "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==",
+      "dev": true,
+      "requires": {
+        "debug": "~3.1.0",
+        "engine.io": "~3.2.0",
+        "has-binary2": "~1.0.2",
+        "socket.io-adapter": "~1.1.0",
+        "socket.io-client": "2.1.1",
+        "socket.io-parser": "~3.2.0"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        }
+      }
+    },
+    "socket.io-adapter": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz",
+      "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=",
+      "dev": true
+    },
+    "socket.io-client": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz",
+      "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==",
+      "dev": true,
+      "requires": {
+        "backo2": "1.0.2",
+        "base64-arraybuffer": "0.1.5",
+        "component-bind": "1.0.0",
+        "component-emitter": "1.2.1",
+        "debug": "~3.1.0",
+        "engine.io-client": "~3.2.0",
+        "has-binary2": "~1.0.2",
+        "has-cors": "1.1.0",
+        "indexof": "0.0.1",
+        "object-component": "0.0.3",
+        "parseqs": "0.0.5",
+        "parseuri": "0.0.5",
+        "socket.io-parser": "~3.2.0",
+        "to-array": "0.1.4"
+      },
+      "dependencies": {
+        "component-emitter": {
+          "version": "1.2.1",
+          "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
+          "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=",
+          "dev": true
+        },
+        "debug": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        }
+      }
+    },
+    "socket.io-parser": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz",
+      "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==",
+      "dev": true,
+      "requires": {
+        "component-emitter": "1.2.1",
+        "debug": "~3.1.0",
+        "isarray": "2.0.1"
+      },
+      "dependencies": {
+        "component-emitter": {
+          "version": "1.2.1",
+          "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
+          "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=",
+          "dev": true
+        },
+        "debug": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
+        "isarray": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
+          "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=",
+          "dev": true
+        }
+      }
+    },
+    "sockjs": {
+      "version": "0.3.19",
+      "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.19.tgz",
+      "integrity": "sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw==",
+      "dev": true,
+      "requires": {
+        "faye-websocket": "^0.10.0",
+        "uuid": "^3.0.1"
+      }
+    },
+    "sockjs-client": {
+      "version": "1.1.5",
+      "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.1.5.tgz",
+      "integrity": "sha1-G7fA9yIsQPQq3xT0RCy9Eml3GoM=",
+      "dev": true,
+      "requires": {
+        "debug": "^2.6.6",
+        "eventsource": "0.1.6",
+        "faye-websocket": "~0.11.0",
+        "inherits": "^2.0.1",
+        "json3": "^3.3.2",
+        "url-parse": "^1.1.8"
+      },
+      "dependencies": {
+        "faye-websocket": {
+          "version": "0.11.3",
+          "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz",
+          "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==",
+          "dev": true,
+          "requires": {
+            "websocket-driver": ">=0.5.1"
+          }
+        }
+      }
+    },
+    "source-list-map": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz",
+      "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==",
+      "dev": true
+    },
+    "source-map": {
+      "version": "0.7.3",
+      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
+      "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
+      "dev": true
+    },
+    "source-map-loader": {
+      "version": "0.2.4",
+      "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-0.2.4.tgz",
+      "integrity": "sha512-OU6UJUty+i2JDpTItnizPrlpOIBLmQbWMuBg9q5bVtnHACqw1tn9nNwqJLbv0/00JjnJb/Ee5g5WS5vrRv7zIQ==",
+      "dev": true,
+      "requires": {
+        "async": "^2.5.0",
+        "loader-utils": "^1.1.0"
+      },
+      "dependencies": {
+        "async": {
+          "version": "2.6.3",
+          "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
+          "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
+          "dev": true,
+          "requires": {
+            "lodash": "^4.17.14"
+          }
+        }
+      }
+    },
+    "source-map-resolve": {
+      "version": "0.5.2",
+      "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz",
+      "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==",
+      "dev": true,
+      "requires": {
+        "atob": "^2.1.1",
+        "decode-uri-component": "^0.2.0",
+        "resolve-url": "^0.2.1",
+        "source-map-url": "^0.4.0",
+        "urix": "^0.1.0"
+      }
+    },
+    "source-map-support": {
+      "version": "0.5.9",
+      "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz",
+      "integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==",
+      "dev": true,
+      "requires": {
+        "buffer-from": "^1.0.0",
+        "source-map": "^0.6.0"
+      },
+      "dependencies": {
+        "source-map": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+          "dev": true
+        }
+      }
+    },
+    "source-map-url": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz",
+      "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=",
+      "dev": true
+    },
+    "sourcemap-codec": {
+      "version": "1.4.6",
+      "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.6.tgz",
+      "integrity": "sha512-1ZooVLYFxC448piVLBbtOxFcXwnymH9oUF8nRd3CuYDVvkRBxRl6pB4Mtas5a4drtL+E8LDgFkQNcgIw6tc8Hg==",
+      "dev": true
+    },
+    "spdx-correct": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz",
+      "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==",
+      "dev": true,
+      "requires": {
+        "spdx-expression-parse": "^3.0.0",
+        "spdx-license-ids": "^3.0.0"
+      }
+    },
+    "spdx-exceptions": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz",
+      "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==",
+      "dev": true
+    },
+    "spdx-expression-parse": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz",
+      "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==",
+      "dev": true,
+      "requires": {
+        "spdx-exceptions": "^2.1.0",
+        "spdx-license-ids": "^3.0.0"
+      }
+    },
+    "spdx-license-ids": {
+      "version": "3.0.5",
+      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz",
+      "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==",
+      "dev": true
+    },
+    "spdy": {
+      "version": "3.4.7",
+      "resolved": "https://registry.npmjs.org/spdy/-/spdy-3.4.7.tgz",
+      "integrity": "sha1-Qv9B7OXMD5mjpsKKq7c/XDsDrLw=",
+      "dev": true,
+      "requires": {
+        "debug": "^2.6.8",
+        "handle-thing": "^1.2.5",
+        "http-deceiver": "^1.2.7",
+        "safe-buffer": "^5.0.1",
+        "select-hose": "^2.0.0",
+        "spdy-transport": "^2.0.18"
+      }
+    },
+    "spdy-transport": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-2.1.1.tgz",
+      "integrity": "sha512-q7D8c148escoB3Z7ySCASadkegMmUZW8Wb/Q1u0/XBgDKMO880rLQDj8Twiew/tYi7ghemKUi/whSYOwE17f5Q==",
+      "dev": true,
+      "requires": {
+        "debug": "^2.6.8",
+        "detect-node": "^2.0.3",
+        "hpack.js": "^2.1.6",
+        "obuf": "^1.1.1",
+        "readable-stream": "^2.2.9",
+        "safe-buffer": "^5.0.1",
+        "wbuf": "^1.7.2"
+      }
+    },
+    "speed-measure-webpack-plugin": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/speed-measure-webpack-plugin/-/speed-measure-webpack-plugin-1.3.1.tgz",
+      "integrity": "sha512-qVIkJvbtS9j/UeZumbdfz0vg+QfG/zxonAjzefZrqzkr7xOncLVXkeGbTpzd1gjCBM4PmVNkWlkeTVhgskAGSQ==",
+      "dev": true,
+      "requires": {
+        "chalk": "^2.0.1"
+      }
+    },
+    "split-string": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
+      "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==",
+      "dev": true,
+      "requires": {
+        "extend-shallow": "^3.0.0"
+      }
+    },
+    "sprintf-js": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+      "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
+      "dev": true
+    },
+    "sshpk": {
+      "version": "1.16.1",
+      "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
+      "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==",
+      "dev": true,
+      "requires": {
+        "asn1": "~0.2.3",
+        "assert-plus": "^1.0.0",
+        "bcrypt-pbkdf": "^1.0.0",
+        "dashdash": "^1.12.0",
+        "ecc-jsbn": "~0.1.1",
+        "getpass": "^0.1.1",
+        "jsbn": "~0.1.0",
+        "safer-buffer": "^2.0.2",
+        "tweetnacl": "~0.14.0"
+      }
+    },
+    "ssri": {
+      "version": "5.3.0",
+      "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.3.0.tgz",
+      "integrity": "sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==",
+      "dev": true,
+      "requires": {
+        "safe-buffer": "^5.1.1"
+      }
+    },
+    "static-extend": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
+      "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=",
+      "dev": true,
+      "requires": {
+        "define-property": "^0.2.5",
+        "object-copy": "^0.1.0"
+      },
+      "dependencies": {
+        "define-property": {
+          "version": "0.2.5",
+          "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+          "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+          "dev": true,
+          "requires": {
+            "is-descriptor": "^0.1.0"
+          }
+        }
+      }
+    },
+    "stats-webpack-plugin": {
+      "version": "0.7.0",
+      "resolved": "https://registry.npmjs.org/stats-webpack-plugin/-/stats-webpack-plugin-0.7.0.tgz",
+      "integrity": "sha512-NT0YGhwuQ0EOX+uPhhUcI6/+1Sq/pMzNuSCBVT4GbFl/ac6I/JZefBcjlECNfAb1t3GOx5dEj1Z7x0cAxeeVLQ==",
+      "dev": true,
+      "requires": {
+        "lodash": "^4.17.4"
+      }
+    },
+    "statuses": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
+      "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=",
+      "dev": true
+    },
+    "stdout-stream": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz",
+      "integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "readable-stream": "^2.0.1"
+      }
+    },
+    "stream-browserify": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz",
+      "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==",
+      "dev": true,
+      "requires": {
+        "inherits": "~2.0.1",
+        "readable-stream": "^2.0.2"
+      }
+    },
+    "stream-each": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz",
+      "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==",
+      "dev": true,
+      "requires": {
+        "end-of-stream": "^1.1.0",
+        "stream-shift": "^1.0.0"
+      }
+    },
+    "stream-http": {
+      "version": "2.8.3",
+      "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz",
+      "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==",
+      "dev": true,
+      "requires": {
+        "builtin-status-codes": "^3.0.0",
+        "inherits": "^2.0.1",
+        "readable-stream": "^2.3.6",
+        "to-arraybuffer": "^1.0.0",
+        "xtend": "^4.0.0"
+      }
+    },
+    "stream-shift": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz",
+      "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=",
+      "dev": true
+    },
+    "streamroller": {
+      "version": "0.7.0",
+      "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz",
+      "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==",
+      "dev": true,
+      "requires": {
+        "date-format": "^1.2.0",
+        "debug": "^3.1.0",
+        "mkdirp": "^0.5.1",
+        "readable-stream": "^2.3.0"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "3.2.6",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+          "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+          "dev": true,
+          "requires": {
+            "ms": "^2.1.1"
+          }
+        },
+        "ms": {
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+          "dev": true
+        }
+      }
+    },
+    "string-width": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+      "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+      "dev": true,
+      "requires": {
+        "code-point-at": "^1.0.0",
+        "is-fullwidth-code-point": "^1.0.0",
+        "strip-ansi": "^3.0.0"
+      }
+    },
+    "string_decoder": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+      "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+      "dev": true,
+      "requires": {
+        "safe-buffer": "~5.1.0"
+      }
+    },
+    "strip-ansi": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+      "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+      "dev": true,
+      "requires": {
+        "ansi-regex": "^2.0.0"
+      }
+    },
+    "strip-bom": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
+      "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
+      "dev": true,
+      "requires": {
+        "is-utf8": "^0.2.0"
+      }
+    },
+    "strip-eof": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
+      "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=",
+      "dev": true
+    },
+    "strip-indent": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz",
+      "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "get-stdin": "^4.0.1"
+      }
+    },
+    "style-loader": {
+      "version": "0.23.0",
+      "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.23.0.tgz",
+      "integrity": "sha512-uCcN7XWHkqwGVt7skpInW6IGO1tG6ReyFQ1Cseh0VcN6VdcFQi62aG/2F3Y9ueA8x4IVlfaSUxpmQXQD9QrEuQ==",
+      "dev": true,
+      "requires": {
+        "loader-utils": "^1.1.0",
+        "schema-utils": "^0.4.5"
+      },
+      "dependencies": {
+        "schema-utils": {
+          "version": "0.4.7",
+          "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz",
+          "integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==",
+          "dev": true,
+          "requires": {
+            "ajv": "^6.1.0",
+            "ajv-keywords": "^3.1.0"
+          }
+        }
+      }
+    },
+    "stylus": {
+      "version": "0.54.5",
+      "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.54.5.tgz",
+      "integrity": "sha1-QrlWCTHKcJDOhRWnmLqeaqPW3Hk=",
+      "dev": true,
+      "requires": {
+        "css-parse": "1.7.x",
+        "debug": "*",
+        "glob": "7.0.x",
+        "mkdirp": "0.5.x",
+        "sax": "0.5.x",
+        "source-map": "0.1.x"
+      },
+      "dependencies": {
+        "glob": {
+          "version": "7.0.6",
+          "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz",
+          "integrity": "sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo=",
+          "dev": true,
+          "requires": {
+            "fs.realpath": "^1.0.0",
+            "inflight": "^1.0.4",
+            "inherits": "2",
+            "minimatch": "^3.0.2",
+            "once": "^1.3.0",
+            "path-is-absolute": "^1.0.0"
+          }
+        },
+        "source-map": {
+          "version": "0.1.43",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz",
+          "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=",
+          "dev": true,
+          "requires": {
+            "amdefine": ">=0.0.4"
+          }
+        }
+      }
+    },
+    "stylus-loader": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/stylus-loader/-/stylus-loader-3.0.2.tgz",
+      "integrity": "sha512-+VomPdZ6a0razP+zinir61yZgpw2NfljeSsdUF5kJuEzlo3khXhY19Fn6l8QQz1GRJGtMCo8nG5C04ePyV7SUA==",
+      "dev": true,
+      "requires": {
+        "loader-utils": "^1.0.2",
+        "lodash.clonedeep": "^4.5.0",
+        "when": "~3.6.x"
+      }
+    },
+    "supports-color": {
+      "version": "5.5.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+      "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+      "dev": true,
+      "requires": {
+        "has-flag": "^3.0.0"
+      }
+    },
+    "symbol-observable": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz",
+      "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==",
+      "dev": true
+    },
+    "tapable": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz",
+      "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==",
+      "dev": true
+    },
+    "tar": {
+      "version": "2.2.2",
+      "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz",
+      "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "block-stream": "*",
+        "fstream": "^1.0.12",
+        "inherits": "2"
+      }
+    },
+    "terser": {
+      "version": "3.17.0",
+      "resolved": "https://registry.npmjs.org/terser/-/terser-3.17.0.tgz",
+      "integrity": "sha512-/FQzzPJmCpjAH9Xvk2paiWrFq+5M6aVOf+2KRbwhByISDX/EujxsK+BAvrhb6H+2rtrLCHK9N01wO014vrIwVQ==",
+      "dev": true,
+      "requires": {
+        "commander": "^2.19.0",
+        "source-map": "~0.6.1",
+        "source-map-support": "~0.5.10"
+      },
+      "dependencies": {
+        "source-map": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+          "dev": true
+        },
+        "source-map-support": {
+          "version": "0.5.12",
+          "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz",
+          "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==",
+          "dev": true,
+          "requires": {
+            "buffer-from": "^1.0.0",
+            "source-map": "^0.6.0"
+          }
+        }
+      }
+    },
+    "terser-webpack-plugin": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.1.0.tgz",
+      "integrity": "sha512-61lV0DSxMAZ8AyZG7/A4a3UPlrbOBo8NIQ4tJzLPAdGOQ+yoNC7l5ijEow27lBAL2humer01KLS6bGIMYQxKoA==",
+      "dev": true,
+      "requires": {
+        "cacache": "^11.0.2",
+        "find-cache-dir": "^2.0.0",
+        "schema-utils": "^1.0.0",
+        "serialize-javascript": "^1.4.0",
+        "source-map": "^0.6.1",
+        "terser": "^3.8.1",
+        "webpack-sources": "^1.1.0",
+        "worker-farm": "^1.5.2"
+      },
+      "dependencies": {
+        "cacache": {
+          "version": "11.3.3",
+          "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.3.tgz",
+          "integrity": "sha512-p8WcneCytvzPxhDvYp31PD039vi77I12W+/KfR9S8AZbaiARFBCpsPJS+9uhWfeBfeAtW7o/4vt3MUqLkbY6nA==",
+          "dev": true,
+          "requires": {
+            "bluebird": "^3.5.5",
+            "chownr": "^1.1.1",
+            "figgy-pudding": "^3.5.1",
+            "glob": "^7.1.4",
+            "graceful-fs": "^4.1.15",
+            "lru-cache": "^5.1.1",
+            "mississippi": "^3.0.0",
+            "mkdirp": "^0.5.1",
+            "move-concurrently": "^1.0.1",
+            "promise-inflight": "^1.0.1",
+            "rimraf": "^2.6.3",
+            "ssri": "^6.0.1",
+            "unique-filename": "^1.1.1",
+            "y18n": "^4.0.0"
+          }
+        },
+        "find-cache-dir": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz",
+          "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==",
+          "dev": true,
+          "requires": {
+            "commondir": "^1.0.1",
+            "make-dir": "^2.0.0",
+            "pkg-dir": "^3.0.0"
+          }
+        },
+        "find-up": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+          "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+          "dev": true,
+          "requires": {
+            "locate-path": "^3.0.0"
+          }
+        },
+        "glob": {
+          "version": "7.1.4",
+          "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz",
+          "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==",
+          "dev": true,
+          "requires": {
+            "fs.realpath": "^1.0.0",
+            "inflight": "^1.0.4",
+            "inherits": "2",
+            "minimatch": "^3.0.4",
+            "once": "^1.3.0",
+            "path-is-absolute": "^1.0.0"
+          }
+        },
+        "locate-path": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+          "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+          "dev": true,
+          "requires": {
+            "p-locate": "^3.0.0",
+            "path-exists": "^3.0.0"
+          }
+        },
+        "lru-cache": {
+          "version": "5.1.1",
+          "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+          "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+          "dev": true,
+          "requires": {
+            "yallist": "^3.0.2"
+          }
+        },
+        "make-dir": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
+          "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
+          "dev": true,
+          "requires": {
+            "pify": "^4.0.1",
+            "semver": "^5.6.0"
+          }
+        },
+        "mississippi": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz",
+          "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==",
+          "dev": true,
+          "requires": {
+            "concat-stream": "^1.5.0",
+            "duplexify": "^3.4.2",
+            "end-of-stream": "^1.1.0",
+            "flush-write-stream": "^1.0.0",
+            "from2": "^2.1.0",
+            "parallel-transform": "^1.1.0",
+            "pump": "^3.0.0",
+            "pumpify": "^1.3.3",
+            "stream-each": "^1.1.0",
+            "through2": "^2.0.0"
+          }
+        },
+        "p-limit": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz",
+          "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==",
+          "dev": true,
+          "requires": {
+            "p-try": "^2.0.0"
+          }
+        },
+        "p-locate": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+          "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+          "dev": true,
+          "requires": {
+            "p-limit": "^2.0.0"
+          }
+        },
+        "p-try": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+          "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+          "dev": true
+        },
+        "pify": {
+          "version": "4.0.1",
+          "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
+          "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+          "dev": true
+        },
+        "pkg-dir": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz",
+          "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==",
+          "dev": true,
+          "requires": {
+            "find-up": "^3.0.0"
+          }
+        },
+        "pump": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+          "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+          "dev": true,
+          "requires": {
+            "end-of-stream": "^1.1.0",
+            "once": "^1.3.1"
+          }
+        },
+        "semver": {
+          "version": "5.7.0",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
+          "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==",
+          "dev": true
+        },
+        "source-map": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+          "dev": true
+        },
+        "ssri": {
+          "version": "6.0.1",
+          "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz",
+          "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==",
+          "dev": true,
+          "requires": {
+            "figgy-pudding": "^3.5.1"
+          }
+        },
+        "yallist": {
+          "version": "3.0.3",
+          "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz",
+          "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==",
+          "dev": true
+        }
+      }
+    },
+    "through": {
+      "version": "2.3.8",
+      "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+      "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
+      "dev": true
+    },
+    "through2": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
+      "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
+      "dev": true,
+      "requires": {
+        "readable-stream": "~2.3.6",
+        "xtend": "~4.0.1"
+      }
+    },
+    "thunky": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.0.3.tgz",
+      "integrity": "sha512-YwT8pjmNcAXBZqrubu22P4FYsh2D4dxRmnWBOL8Jk8bUcRUtc5326kx32tuTmFDAZtLOGEVNl8POAR8j896Iow==",
+      "dev": true
+    },
+    "timers-browserify": {
+      "version": "2.0.10",
+      "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz",
+      "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==",
+      "dev": true,
+      "requires": {
+        "setimmediate": "^1.0.4"
+      }
+    },
+    "tmp": {
+      "version": "0.0.33",
+      "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
+      "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
+      "dev": true,
+      "requires": {
+        "os-tmpdir": "~1.0.2"
+      }
+    },
+    "to-array": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz",
+      "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=",
+      "dev": true
+    },
+    "to-arraybuffer": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz",
+      "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=",
+      "dev": true
+    },
+    "to-fast-properties": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz",
+      "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=",
+      "dev": true
+    },
+    "to-object-path": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz",
+      "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=",
+      "dev": true,
+      "requires": {
+        "kind-of": "^3.0.2"
+      },
+      "dependencies": {
+        "kind-of": {
+          "version": "3.2.2",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+          "dev": true,
+          "requires": {
+            "is-buffer": "^1.1.5"
+          }
+        }
+      }
+    },
+    "to-regex": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz",
+      "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==",
+      "dev": true,
+      "requires": {
+        "define-property": "^2.0.2",
+        "extend-shallow": "^3.0.2",
+        "regex-not": "^1.0.2",
+        "safe-regex": "^1.1.0"
+      }
+    },
+    "to-regex-range": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
+      "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
+      "dev": true,
+      "requires": {
+        "is-number": "^3.0.0",
+        "repeat-string": "^1.6.1"
+      }
+    },
+    "toidentifier": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
+      "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==",
+      "dev": true
+    },
+    "tough-cookie": {
+      "version": "2.4.3",
+      "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
+      "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
+      "dev": true,
+      "requires": {
+        "psl": "^1.1.24",
+        "punycode": "^1.4.1"
+      },
+      "dependencies": {
+        "punycode": {
+          "version": "1.4.1",
+          "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+          "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
+          "dev": true
+        }
+      }
+    },
+    "tree-kill": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.0.tgz",
+      "integrity": "sha512-DlX6dR0lOIRDFxI0mjL9IYg6OTncLm/Zt+JiBhE5OlFcAR8yc9S7FFXU9so0oda47frdM/JFsk7UjNt9vscKcg==",
+      "dev": true
+    },
+    "trim-newlines": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz",
+      "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=",
+      "dev": true,
+      "optional": true
+    },
+    "trim-right": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz",
+      "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=",
+      "dev": true
+    },
+    "true-case-path": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz",
+      "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "glob": "^7.1.2"
+      }
+    },
+    "ts-node": {
+      "version": "7.0.1",
+      "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz",
+      "integrity": "sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==",
+      "dev": true,
+      "requires": {
+        "arrify": "^1.0.0",
+        "buffer-from": "^1.1.0",
+        "diff": "^3.1.0",
+        "make-error": "^1.1.1",
+        "minimist": "^1.2.0",
+        "mkdirp": "^0.5.1",
+        "source-map-support": "^0.5.6",
+        "yn": "^2.0.0"
+      },
+      "dependencies": {
+        "minimist": {
+          "version": "1.2.0",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+          "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+          "dev": true
+        }
+      }
+    },
+    "tslib": {
+      "version": "1.10.0",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
+      "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
+    },
+    "tslint": {
+      "version": "5.11.0",
+      "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.11.0.tgz",
+      "integrity": "sha1-mPMMAurjzecAYgHkwzywi0hYHu0=",
+      "dev": true,
+      "requires": {
+        "babel-code-frame": "^6.22.0",
+        "builtin-modules": "^1.1.1",
+        "chalk": "^2.3.0",
+        "commander": "^2.12.1",
+        "diff": "^3.2.0",
+        "glob": "^7.1.1",
+        "js-yaml": "^3.7.0",
+        "minimatch": "^3.0.4",
+        "resolve": "^1.3.2",
+        "semver": "^5.3.0",
+        "tslib": "^1.8.0",
+        "tsutils": "^2.27.2"
+      },
+      "dependencies": {
+        "resolve": {
+          "version": "1.11.1",
+          "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz",
+          "integrity": "sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==",
+          "dev": true,
+          "requires": {
+            "path-parse": "^1.0.6"
+          }
+        }
+      }
+    },
+    "tsutils": {
+      "version": "2.29.0",
+      "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz",
+      "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==",
+      "dev": true,
+      "requires": {
+        "tslib": "^1.8.1"
+      }
+    },
+    "tty-browserify": {
+      "version": "0.0.0",
+      "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
+      "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=",
+      "dev": true
+    },
+    "tunnel-agent": {
+      "version": "0.6.0",
+      "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+      "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
+      "dev": true,
+      "requires": {
+        "safe-buffer": "^5.0.1"
+      }
+    },
+    "tweetnacl": {
+      "version": "0.14.5",
+      "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
+      "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
+      "dev": true
+    },
+    "type-check": {
+      "version": "0.3.2",
+      "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
+      "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
+      "dev": true,
+      "requires": {
+        "prelude-ls": "~1.1.2"
+      }
+    },
+    "type-is": {
+      "version": "1.6.18",
+      "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
+      "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
+      "dev": true,
+      "requires": {
+        "media-typer": "0.3.0",
+        "mime-types": "~2.1.24"
+      }
+    },
+    "typedarray": {
+      "version": "0.0.6",
+      "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
+      "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
+      "dev": true
+    },
+    "typescript": {
+      "version": "3.1.6",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.1.6.tgz",
+      "integrity": "sha512-tDMYfVtvpb96msS1lDX9MEdHrW4yOuZ4Kdc4Him9oU796XldPYF/t2+uKoX0BBa0hXXwDlqYQbXY5Rzjzc5hBA==",
+      "dev": true
+    },
+    "uglify-js": {
+      "version": "3.6.0",
+      "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.0.tgz",
+      "integrity": "sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "commander": "~2.20.0",
+        "source-map": "~0.6.1"
+      },
+      "dependencies": {
+        "source-map": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+          "dev": true,
+          "optional": true
+        }
+      }
+    },
+    "uglifyjs-webpack-plugin": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.3.0.tgz",
+      "integrity": "sha512-ovHIch0AMlxjD/97j9AYovZxG5wnHOPkL7T1GKochBADp/Zwc44pEWNqpKl1Loupp1WhFg7SlYmHZRUfdAacgw==",
+      "dev": true,
+      "requires": {
+        "cacache": "^10.0.4",
+        "find-cache-dir": "^1.0.0",
+        "schema-utils": "^0.4.5",
+        "serialize-javascript": "^1.4.0",
+        "source-map": "^0.6.1",
+        "uglify-es": "^3.3.4",
+        "webpack-sources": "^1.1.0",
+        "worker-farm": "^1.5.2"
+      },
+      "dependencies": {
+        "commander": {
+          "version": "2.13.0",
+          "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz",
+          "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==",
+          "dev": true
+        },
+        "schema-utils": {
+          "version": "0.4.7",
+          "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz",
+          "integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==",
+          "dev": true,
+          "requires": {
+            "ajv": "^6.1.0",
+            "ajv-keywords": "^3.1.0"
+          }
+        },
+        "source-map": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+          "dev": true
+        },
+        "uglify-es": {
+          "version": "3.3.9",
+          "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz",
+          "integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==",
+          "dev": true,
+          "requires": {
+            "commander": "~2.13.0",
+            "source-map": "~0.6.1"
+          }
+        }
+      }
+    },
+    "ultron": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz",
+      "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==",
+      "dev": true
+    },
+    "underscore": {
+      "version": "1.9.1",
+      "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz",
+      "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg=="
+    },
+    "union-value": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
+      "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==",
+      "dev": true,
+      "requires": {
+        "arr-union": "^3.1.0",
+        "get-value": "^2.0.6",
+        "is-extendable": "^0.1.1",
+        "set-value": "^2.0.1"
+      }
+    },
+    "unique-filename": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz",
+      "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==",
+      "dev": true,
+      "requires": {
+        "unique-slug": "^2.0.0"
+      }
+    },
+    "unique-slug": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz",
+      "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==",
+      "dev": true,
+      "requires": {
+        "imurmurhash": "^0.1.4"
+      }
+    },
+    "unpipe": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+      "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=",
+      "dev": true
+    },
+    "unset-value": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
+      "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=",
+      "dev": true,
+      "requires": {
+        "has-value": "^0.3.1",
+        "isobject": "^3.0.0"
+      },
+      "dependencies": {
+        "has-value": {
+          "version": "0.3.1",
+          "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz",
+          "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=",
+          "dev": true,
+          "requires": {
+            "get-value": "^2.0.3",
+            "has-values": "^0.1.4",
+            "isobject": "^2.0.0"
+          },
+          "dependencies": {
+            "isobject": {
+              "version": "2.1.0",
+              "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
+              "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
+              "dev": true,
+              "requires": {
+                "isarray": "1.0.0"
+              }
+            }
+          }
+        },
+        "has-values": {
+          "version": "0.1.4",
+          "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz",
+          "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=",
+          "dev": true
+        }
+      }
+    },
+    "upath": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.2.tgz",
+      "integrity": "sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q==",
+      "dev": true
+    },
+    "uri-js": {
+      "version": "4.2.2",
+      "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
+      "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
+      "dev": true,
+      "requires": {
+        "punycode": "^2.1.0"
+      }
+    },
+    "urix": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz",
+      "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=",
+      "dev": true
+    },
+    "url": {
+      "version": "0.11.0",
+      "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
+      "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=",
+      "dev": true,
+      "requires": {
+        "punycode": "1.3.2",
+        "querystring": "0.2.0"
+      },
+      "dependencies": {
+        "punycode": {
+          "version": "1.3.2",
+          "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
+          "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=",
+          "dev": true
+        }
+      }
+    },
+    "url-join": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz",
+      "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==",
+      "dev": true
+    },
+    "url-parse": {
+      "version": "1.4.7",
+      "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz",
+      "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==",
+      "dev": true,
+      "requires": {
+        "querystringify": "^2.1.1",
+        "requires-port": "^1.0.0"
+      }
+    },
+    "use": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
+      "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==",
+      "dev": true
+    },
+    "useragent": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.2.1.tgz",
+      "integrity": "sha1-z1k+9PLRdYdei7ZY6pLhik/QbY4=",
+      "dev": true,
+      "requires": {
+        "lru-cache": "2.2.x",
+        "tmp": "0.0.x"
+      },
+      "dependencies": {
+        "lru-cache": {
+          "version": "2.2.4",
+          "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.2.4.tgz",
+          "integrity": "sha1-bGWGGb7PFAMdDQtZSxYELOTcBj0=",
+          "dev": true
+        }
+      }
+    },
+    "util": {
+      "version": "0.11.1",
+      "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz",
+      "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==",
+      "dev": true,
+      "requires": {
+        "inherits": "2.0.3"
+      },
+      "dependencies": {
+        "inherits": {
+          "version": "2.0.3",
+          "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+          "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
+          "dev": true
+        }
+      }
+    },
+    "util-deprecate": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+      "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
+      "dev": true
+    },
+    "utils-merge": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+      "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=",
+      "dev": true
+    },
+    "uuid": {
+      "version": "3.3.2",
+      "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
+      "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="
+    },
+    "validate-npm-package-license": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+      "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+      "dev": true,
+      "requires": {
+        "spdx-correct": "^3.0.0",
+        "spdx-expression-parse": "^3.0.0"
+      }
+    },
+    "validate-npm-package-name": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz",
+      "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=",
+      "dev": true,
+      "requires": {
+        "builtins": "^1.0.3"
+      }
+    },
+    "vary": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+      "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=",
+      "dev": true
+    },
+    "verror": {
+      "version": "1.10.0",
+      "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
+      "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
+      "dev": true,
+      "requires": {
+        "assert-plus": "^1.0.0",
+        "core-util-is": "1.0.2",
+        "extsprintf": "^1.2.0"
+      }
+    },
+    "vm-browserify": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.0.tgz",
+      "integrity": "sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw==",
+      "dev": true
+    },
+    "void-elements": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz",
+      "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=",
+      "dev": true
+    },
+    "watchpack": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz",
+      "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==",
+      "dev": true,
+      "requires": {
+        "chokidar": "^2.0.2",
+        "graceful-fs": "^4.1.2",
+        "neo-async": "^2.5.0"
+      }
+    },
+    "wbuf": {
+      "version": "1.7.3",
+      "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz",
+      "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==",
+      "dev": true,
+      "requires": {
+        "minimalistic-assert": "^1.0.0"
+      }
+    },
+    "web-animations-js": {
+      "version": "2.3.2",
+      "resolved": "https://registry.npmjs.org/web-animations-js/-/web-animations-js-2.3.2.tgz",
+      "integrity": "sha512-TOMFWtQdxzjWp8qx4DAraTWTsdhxVSiWa6NkPFSaPtZ1diKUxTn4yTix73A1euG1WbSOMMPcY51cnjTIHrGtDA=="
+    },
+    "webdriver-js-extender": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/webdriver-js-extender/-/webdriver-js-extender-2.1.0.tgz",
+      "integrity": "sha512-lcUKrjbBfCK6MNsh7xaY2UAUmZwe+/ib03AjVOpFobX4O7+83BUveSrLfU0Qsyb1DaKJdQRbuU+kM9aZ6QUhiQ==",
+      "dev": true,
+      "requires": {
+        "@types/selenium-webdriver": "^3.0.0",
+        "selenium-webdriver": "^3.0.1"
+      }
+    },
+    "webpack": {
+      "version": "4.19.1",
+      "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.19.1.tgz",
+      "integrity": "sha512-j7Q/5QqZRqIFXJvC0E59ipLV5Hf6lAnS3ezC3I4HMUybwEDikQBVad5d+IpPtmaQPQArvgUZLXIN6lWijHBn4g==",
+      "dev": true,
+      "requires": {
+        "@webassemblyjs/ast": "1.7.6",
+        "@webassemblyjs/helper-module-context": "1.7.6",
+        "@webassemblyjs/wasm-edit": "1.7.6",
+        "@webassemblyjs/wasm-parser": "1.7.6",
+        "acorn": "^5.6.2",
+        "acorn-dynamic-import": "^3.0.0",
+        "ajv": "^6.1.0",
+        "ajv-keywords": "^3.1.0",
+        "chrome-trace-event": "^1.0.0",
+        "enhanced-resolve": "^4.1.0",
+        "eslint-scope": "^4.0.0",
+        "json-parse-better-errors": "^1.0.2",
+        "loader-runner": "^2.3.0",
+        "loader-utils": "^1.1.0",
+        "memory-fs": "~0.4.1",
+        "micromatch": "^3.1.8",
+        "mkdirp": "~0.5.0",
+        "neo-async": "^2.5.0",
+        "node-libs-browser": "^2.0.0",
+        "schema-utils": "^0.4.4",
+        "tapable": "^1.1.0",
+        "uglifyjs-webpack-plugin": "^1.2.4",
+        "watchpack": "^1.5.0",
+        "webpack-sources": "^1.2.0"
+      },
+      "dependencies": {
+        "schema-utils": {
+          "version": "0.4.7",
+          "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz",
+          "integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==",
+          "dev": true,
+          "requires": {
+            "ajv": "^6.1.0",
+            "ajv-keywords": "^3.1.0"
+          }
+        }
+      }
+    },
+    "webpack-core": {
+      "version": "0.6.9",
+      "resolved": "https://registry.npmjs.org/webpack-core/-/webpack-core-0.6.9.tgz",
+      "integrity": "sha1-/FcViMhVjad76e+23r3Fo7FyvcI=",
+      "dev": true,
+      "requires": {
+        "source-list-map": "~0.1.7",
+        "source-map": "~0.4.1"
+      },
+      "dependencies": {
+        "source-list-map": {
+          "version": "0.1.8",
+          "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-0.1.8.tgz",
+          "integrity": "sha1-xVCyq1Qn9rPyH1r+rYjE9Vh7IQY=",
+          "dev": true
+        },
+        "source-map": {
+          "version": "0.4.4",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
+          "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
+          "dev": true,
+          "requires": {
+            "amdefine": ">=0.0.4"
+          }
+        }
+      }
+    },
+    "webpack-dev-middleware": {
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.3.0.tgz",
+      "integrity": "sha512-5C5gXtOo1I6+0AEg4UPglYEtu3Rai6l5IiO6aUu65scHXz29dc3oIWMiRwvcNLXgL0HwRkRxa9N02ZjFt4hY8w==",
+      "dev": true,
+      "requires": {
+        "loud-rejection": "^1.6.0",
+        "memory-fs": "~0.4.1",
+        "mime": "^2.3.1",
+        "range-parser": "^1.0.3",
+        "url-join": "^4.0.0",
+        "webpack-log": "^2.0.0"
+      },
+      "dependencies": {
+        "mime": {
+          "version": "2.4.4",
+          "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",
+          "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==",
+          "dev": true
+        }
+      }
+    },
+    "webpack-dev-server": {
+      "version": "3.1.8",
+      "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.1.8.tgz",
+      "integrity": "sha512-c+tcJtDqnPdxCAzEEZKdIPmg3i5i7cAHe+B+0xFNK0BlCc2HF/unYccbU7xTgfGc5xxhCztCQzFmsqim+KhI+A==",
+      "dev": true,
+      "requires": {
+        "ansi-html": "0.0.7",
+        "bonjour": "^3.5.0",
+        "chokidar": "^2.0.0",
+        "compression": "^1.5.2",
+        "connect-history-api-fallback": "^1.3.0",
+        "debug": "^3.1.0",
+        "del": "^3.0.0",
+        "express": "^4.16.2",
+        "html-entities": "^1.2.0",
+        "http-proxy-middleware": "~0.18.0",
+        "import-local": "^2.0.0",
+        "internal-ip": "^3.0.1",
+        "ip": "^1.1.5",
+        "killable": "^1.0.0",
+        "loglevel": "^1.4.1",
+        "opn": "^5.1.0",
+        "portfinder": "^1.0.9",
+        "schema-utils": "^1.0.0",
+        "selfsigned": "^1.9.1",
+        "serve-index": "^1.7.2",
+        "sockjs": "0.3.19",
+        "sockjs-client": "1.1.5",
+        "spdy": "^3.4.1",
+        "strip-ansi": "^3.0.0",
+        "supports-color": "^5.1.0",
+        "webpack-dev-middleware": "3.2.0",
+        "webpack-log": "^2.0.0",
+        "yargs": "12.0.2"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+          "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+          "dev": true
+        },
+        "camelcase": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
+          "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=",
+          "dev": true
+        },
+        "cliui": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz",
+          "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==",
+          "dev": true,
+          "requires": {
+            "string-width": "^2.1.1",
+            "strip-ansi": "^4.0.0",
+            "wrap-ansi": "^2.0.0"
+          },
+          "dependencies": {
+            "strip-ansi": {
+              "version": "4.0.0",
+              "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+              "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+              "dev": true,
+              "requires": {
+                "ansi-regex": "^3.0.0"
+              }
+            }
+          }
+        },
+        "cross-spawn": {
+          "version": "6.0.5",
+          "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+          "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+          "dev": true,
+          "requires": {
+            "nice-try": "^1.0.4",
+            "path-key": "^2.0.1",
+            "semver": "^5.5.0",
+            "shebang-command": "^1.2.0",
+            "which": "^1.2.9"
+          }
+        },
+        "debug": {
+          "version": "3.2.6",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+          "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+          "dev": true,
+          "requires": {
+            "ms": "^2.1.1"
+          }
+        },
+        "decamelize": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-2.0.0.tgz",
+          "integrity": "sha512-Ikpp5scV3MSYxY39ymh45ZLEecsTdv/Xj2CaQfI8RLMuwi7XvjX9H/fhraiSuU+C5w5NTDu4ZU72xNiZnurBPg==",
+          "dev": true,
+          "requires": {
+            "xregexp": "4.0.0"
+          }
+        },
+        "execa": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz",
+          "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==",
+          "dev": true,
+          "requires": {
+            "cross-spawn": "^6.0.0",
+            "get-stream": "^4.0.0",
+            "is-stream": "^1.1.0",
+            "npm-run-path": "^2.0.0",
+            "p-finally": "^1.0.0",
+            "signal-exit": "^3.0.0",
+            "strip-eof": "^1.0.0"
+          }
+        },
+        "find-up": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+          "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+          "dev": true,
+          "requires": {
+            "locate-path": "^3.0.0"
+          }
+        },
+        "get-stream": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
+          "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
+          "dev": true,
+          "requires": {
+            "pump": "^3.0.0"
+          }
+        },
+        "invert-kv": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz",
+          "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==",
+          "dev": true
+        },
+        "is-fullwidth-code-point": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+          "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+          "dev": true
+        },
+        "lcid": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz",
+          "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==",
+          "dev": true,
+          "requires": {
+            "invert-kv": "^2.0.0"
+          }
+        },
+        "locate-path": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+          "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+          "dev": true,
+          "requires": {
+            "p-locate": "^3.0.0",
+            "path-exists": "^3.0.0"
+          }
+        },
+        "mime": {
+          "version": "2.4.4",
+          "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",
+          "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==",
+          "dev": true
+        },
+        "ms": {
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+          "dev": true
+        },
+        "os-locale": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz",
+          "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==",
+          "dev": true,
+          "requires": {
+            "execa": "^1.0.0",
+            "lcid": "^2.0.0",
+            "mem": "^4.0.0"
+          }
+        },
+        "p-limit": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz",
+          "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==",
+          "dev": true,
+          "requires": {
+            "p-try": "^2.0.0"
+          }
+        },
+        "p-locate": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+          "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+          "dev": true,
+          "requires": {
+            "p-limit": "^2.0.0"
+          }
+        },
+        "p-try": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+          "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+          "dev": true
+        },
+        "pump": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+          "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+          "dev": true,
+          "requires": {
+            "end-of-stream": "^1.1.0",
+            "once": "^1.3.1"
+          }
+        },
+        "string-width": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+          "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+          "dev": true,
+          "requires": {
+            "is-fullwidth-code-point": "^2.0.0",
+            "strip-ansi": "^4.0.0"
+          },
+          "dependencies": {
+            "strip-ansi": {
+              "version": "4.0.0",
+              "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+              "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+              "dev": true,
+              "requires": {
+                "ansi-regex": "^3.0.0"
+              }
+            }
+          }
+        },
+        "webpack-dev-middleware": {
+          "version": "3.2.0",
+          "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.2.0.tgz",
+          "integrity": "sha512-YJLMF/96TpKXaEQwaLEo+Z4NDK8aV133ROF6xp9pe3gQoS7sxfpXh4Rv9eC+8vCvWfmDjRQaMSlRPbO+9G6jgA==",
+          "dev": true,
+          "requires": {
+            "loud-rejection": "^1.6.0",
+            "memory-fs": "~0.4.1",
+            "mime": "^2.3.1",
+            "path-is-absolute": "^1.0.0",
+            "range-parser": "^1.0.3",
+            "url-join": "^4.0.0",
+            "webpack-log": "^2.0.0"
+          }
+        },
+        "which-module": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
+          "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
+          "dev": true
+        },
+        "yargs": {
+          "version": "12.0.2",
+          "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.2.tgz",
+          "integrity": "sha512-e7SkEx6N6SIZ5c5H22RTZae61qtn3PYUE8JYbBFlK9sYmh3DMQ6E5ygtaG/2BW0JZi4WGgTR2IV5ChqlqrDGVQ==",
+          "dev": true,
+          "requires": {
+            "cliui": "^4.0.0",
+            "decamelize": "^2.0.0",
+            "find-up": "^3.0.0",
+            "get-caller-file": "^1.0.1",
+            "os-locale": "^3.0.0",
+            "require-directory": "^2.1.1",
+            "require-main-filename": "^1.0.1",
+            "set-blocking": "^2.0.0",
+            "string-width": "^2.0.0",
+            "which-module": "^2.0.0",
+            "y18n": "^3.2.1 || ^4.0.0",
+            "yargs-parser": "^10.1.0"
+          }
+        },
+        "yargs-parser": {
+          "version": "10.1.0",
+          "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz",
+          "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==",
+          "dev": true,
+          "requires": {
+            "camelcase": "^4.1.0"
+          }
+        }
+      }
+    },
+    "webpack-log": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz",
+      "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==",
+      "dev": true,
+      "requires": {
+        "ansi-colors": "^3.0.0",
+        "uuid": "^3.3.2"
+      }
+    },
+    "webpack-merge": {
+      "version": "4.1.4",
+      "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.1.4.tgz",
+      "integrity": "sha512-TmSe1HZKeOPey3oy1Ov2iS3guIZjWvMT2BBJDzzT5jScHTjVC3mpjJofgueEzaEd6ibhxRDD6MIblDr8tzh8iQ==",
+      "dev": true,
+      "requires": {
+        "lodash": "^4.17.5"
+      }
+    },
+    "webpack-sources": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.2.0.tgz",
+      "integrity": "sha512-9BZwxR85dNsjWz3blyxdOhTgtnQvv3OEs5xofI0wPYTwu5kaWxS08UuD1oI7WLBLpRO+ylf0ofnXLXWmGb2WMw==",
+      "dev": true,
+      "requires": {
+        "source-list-map": "^2.0.0",
+        "source-map": "~0.6.1"
+      },
+      "dependencies": {
+        "source-map": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+          "dev": true
+        }
+      }
+    },
+    "webpack-subresource-integrity": {
+      "version": "1.1.0-rc.6",
+      "resolved": "https://registry.npmjs.org/webpack-subresource-integrity/-/webpack-subresource-integrity-1.1.0-rc.6.tgz",
+      "integrity": "sha512-Az7y8xTniNhaA0620AV1KPwWOqawurVVDzQSpPAeR5RwNbL91GoBSJAAo9cfd+GiFHwsS5bbHepBw1e6Hzxy4w==",
+      "dev": true,
+      "requires": {
+        "webpack-core": "^0.6.8"
+      }
+    },
+    "websocket-driver": {
+      "version": "0.7.3",
+      "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.3.tgz",
+      "integrity": "sha512-bpxWlvbbB459Mlipc5GBzzZwhoZgGEZLuqPaR0INBGnPAY1vdBX6hPnoFXiw+3yWxDuHyQjO2oXTMyS8A5haFg==",
+      "dev": true,
+      "requires": {
+        "http-parser-js": ">=0.4.0 <0.4.11",
+        "safe-buffer": ">=5.1.0",
+        "websocket-extensions": ">=0.1.1"
+      }
+    },
+    "websocket-extensions": {
+      "version": "0.1.3",
+      "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz",
+      "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==",
+      "dev": true
+    },
+    "when": {
+      "version": "3.6.4",
+      "resolved": "https://registry.npmjs.org/when/-/when-3.6.4.tgz",
+      "integrity": "sha1-RztRfsFZ4rhQBUl6E5g/CVQS404=",
+      "dev": true
+    },
+    "which": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+      "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+      "dev": true,
+      "requires": {
+        "isexe": "^2.0.0"
+      }
+    },
+    "which-module": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz",
+      "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=",
+      "dev": true,
+      "optional": true
+    },
+    "wide-align": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
+      "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
+      "dev": true,
+      "requires": {
+        "string-width": "^1.0.2 || 2"
+      }
+    },
+    "wordwrap": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
+      "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=",
+      "dev": true
+    },
+    "worker-farm": {
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz",
+      "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==",
+      "dev": true,
+      "requires": {
+        "errno": "~0.1.7"
+      }
+    },
+    "wrap-ansi": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
+      "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
+      "dev": true,
+      "requires": {
+        "string-width": "^1.0.1",
+        "strip-ansi": "^3.0.1"
+      }
+    },
+    "wrappy": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+      "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+      "dev": true
+    },
+    "ws": {
+      "version": "3.3.3",
+      "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz",
+      "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==",
+      "dev": true,
+      "requires": {
+        "async-limiter": "~1.0.0",
+        "safe-buffer": "~5.1.0",
+        "ultron": "~1.1.0"
+      }
+    },
+    "xml2js": {
+      "version": "0.4.19",
+      "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz",
+      "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==",
+      "dev": true,
+      "requires": {
+        "sax": ">=0.6.0",
+        "xmlbuilder": "~9.0.1"
+      },
+      "dependencies": {
+        "sax": {
+          "version": "1.2.4",
+          "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
+          "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
+          "dev": true
+        }
+      }
+    },
+    "xmlbuilder": {
+      "version": "9.0.7",
+      "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz",
+      "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=",
+      "dev": true
+    },
+    "xmlhttprequest-ssl": {
+      "version": "1.5.5",
+      "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz",
+      "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=",
+      "dev": true
+    },
+    "xregexp": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.0.0.tgz",
+      "integrity": "sha512-PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg==",
+      "dev": true
+    },
+    "xtend": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+      "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
+      "dev": true
+    },
+    "y18n": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
+      "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
+      "dev": true
+    },
+    "yallist": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+      "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
+      "dev": true
+    },
+    "yargs": {
+      "version": "7.1.0",
+      "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz",
+      "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "camelcase": "^3.0.0",
+        "cliui": "^3.2.0",
+        "decamelize": "^1.1.1",
+        "get-caller-file": "^1.0.1",
+        "os-locale": "^1.4.0",
+        "read-pkg-up": "^1.0.1",
+        "require-directory": "^2.1.1",
+        "require-main-filename": "^1.0.1",
+        "set-blocking": "^2.0.0",
+        "string-width": "^1.0.2",
+        "which-module": "^1.0.0",
+        "y18n": "^3.2.1",
+        "yargs-parser": "^5.0.0"
+      },
+      "dependencies": {
+        "camelcase": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
+          "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=",
+          "dev": true,
+          "optional": true
+        },
+        "y18n": {
+          "version": "3.2.1",
+          "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
+          "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=",
+          "dev": true,
+          "optional": true
+        }
+      }
+    },
+    "yargs-parser": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz",
+      "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "camelcase": "^3.0.0"
+      },
+      "dependencies": {
+        "camelcase": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
+          "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=",
+          "dev": true,
+          "optional": true
+        }
+      }
+    },
+    "yeast": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz",
+      "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=",
+      "dev": true
+    },
+    "yn": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz",
+      "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=",
+      "dev": true
+    },
+    "zone.js": {
+      "version": "0.8.29",
+      "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.8.29.tgz",
+      "integrity": "sha512-mla2acNCMkWXBD+c+yeUrBUrzOxYMNFdQ6FGfigGGtEVBPJx07BQeJekjt9DmH1FtZek4E9rE1eRR9qQpxACOQ=="
+    }
+  }
+}
diff --git a/portal-FE-os/package.json b/portal-FE-os/package.json
new file mode 100644 (file)
index 0000000..e432be7
--- /dev/null
@@ -0,0 +1,73 @@
+{
+  "name": "portal-fe-os",
+  "version": "7.0.0",
+  "scripts": {
+    "ng": "ng",
+    "start": "ng serve --host www.portal.openecomp.org --port 8989 --open",
+    "build": "ng build --prod --aot=false --build-optimizer=false",
+    "test": "ng test",
+    "lint": "ng lint",
+    "e2e": "ng e2e"
+  },
+  "private": true,
+  "dependencies": {
+    "@angular/animations": "~7.0.0",
+    "@angular/cdk": "~7.0.0",
+    "@angular/common": "~7.0.0",
+    "@angular/compiler": "~7.0.0",
+    "@angular/core": "~7.0.0",
+    "@angular/forms": "~7.0.0",
+    "@angular/http": "~7.0.0",
+    "@angular/material": "~7.0.0",
+    "@angular/platform-browser": "~7.0.0",
+    "@angular/platform-browser-dynamic": "~7.0.0",
+    "@angular/router": "~7.0.0",
+    "@ng-bootstrap/ng-bootstrap": "4.2.1",
+    "@types/jquery": "^3.3.31",
+    "@types/underscore": "^1.9.3",
+    "@types/uuid": "^3.4.5",
+    "abs-components-bc": "file:abs-components-bc-1.0.7.tgz",
+    "angular-gridster2": "^8.0.0",
+    "angular2-uuid": "^1.1.1",
+    "classlist.js": "^1.1.20150312",
+    "core-js": "^2.5.4",
+    "cs-jqtree-contextmenu": "^0.1.0",
+    "font-awesome": "^4.7.0",
+    "hammerjs": "^2.0.8",
+    "ionicons": "^4.6.2",
+    "jqtree": "^1.4.11",
+    "jquery": "^3.4.1",
+    "material-design-icons-iconfont": "^5.0.1",
+    "ng-click-outside": "^5.0.0",
+    "ngx-cookie-service": "^2.2.0",
+    "rxjs": "~6.3.3",
+    "rxjs-compat": "^6.5.2",
+    "systemjs": "^6.1.1",
+    "tslib": "^1.9.0",
+    "underscore": "^1.9.1",
+    "uuid": "^3.3.2",
+    "web-animations-js": "^2.3.2",
+    "zone.js": "~0.8.26"
+  },
+  "devDependencies": {
+    "@angular-devkit/build-angular": "^0.10.0",
+    "@angular/cli": "~7.0.6",
+    "@angular/compiler-cli": "~7.0.0",
+    "@angular/language-service": "~7.0.0",
+    "@types/jasmine": "~2.8.8",
+    "@types/jasminewd2": "~2.0.3",
+    "@types/node": "~8.9.4",
+    "codelyzer": "~4.5.0",
+    "jasmine-core": "~2.99.1",
+    "jasmine-spec-reporter": "~4.2.1",
+    "karma": "~3.0.0",
+    "karma-chrome-launcher": "~2.2.0",
+    "karma-coverage-istanbul-reporter": "~2.0.1",
+    "karma-jasmine": "~1.1.2",
+    "karma-jasmine-html-reporter": "^0.2.2",
+    "protractor": "~5.4.0",
+    "ts-node": "~7.0.0",
+    "tslint": "~5.11.0",
+    "typescript": "~3.1.6"
+  }
+}
diff --git a/portal-FE-os/pom.xml b/portal-FE-os/pom.xml
new file mode 100644 (file)
index 0000000..626addb
--- /dev/null
@@ -0,0 +1,118 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+       <modelVersion>4.0.0</modelVersion>
+
+       <groupId>org.onap.portal</groupId>
+       <artifactId>portal-FE-os</artifactId>
+       <version>3.1.0</version>
+
+       <properties>
+               <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+               <skipnode>false</skipnode>
+               <skipcopy>false</skipcopy>
+       </properties>
+
+       <build>
+               <plugins>
+
+                       <plugin>
+                               <artifactId>maven-clean-plugin</artifactId>
+                               <version>3.0.0</version>
+                               <configuration>
+                                       <filesets>
+                                               <fileset>
+                                                       <directory>${basedir}/dist</directory>
+                                               </fileset>
+                                               <!--
+                                               <fileset>
+                                                       <directory>${basedir}/node</directory>
+                                               </fileset>
+                                               <fileset>
+                                                       <directory>${basedir}/node_modules</directory>
+                                               </fileset>
+                                               -->
+                                       </filesets>
+                               </configuration>
+                       </plugin>
+
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-resources-plugin</artifactId>
+                               <version>3.0.2</version>
+                               <executions>
+
+                                       <execution>
+                                               <id>copy-common</id>
+                                               <phase>generate-resources</phase>
+                                               <goals>
+                                                       <goal>copy-resources</goal>
+                                               </goals>
+                                               <configuration>
+                                                       <outputDirectory>${basedir}/src</outputDirectory>
+                                                       <overwrite>false</overwrite>
+                                                       <skip>${skipcopy}</skip>
+                                                       <resources>
+                                                               <resource>
+                                                                       <directory>../portal-FE-common/src</directory>
+                                                               </resource>
+                                                       </resources>
+                                               </configuration>
+                                       </execution>
+
+                               </executions>
+                       </plugin>
+
+                       <plugin>
+                               <groupId>com.github.eirslett</groupId>
+                               <artifactId>frontend-maven-plugin</artifactId>
+                               <!-- Use the latest released version: https://repo1.maven.org/maven2/com/github/eirslett/frontend-maven-plugin/ -->
+                               <version>1.3</version>
+                               <configuration>
+                                       <skip>${skipnode}</skip>
+                                       <nodeVersion>v10.13.0</nodeVersion>
+                                       <nodeDownloadRoot>https://nodejs.org/dist/</nodeDownloadRoot>
+                                       <npmDownloadRoot>https://nodejs.org/dist/npm/</npmDownloadRoot>
+                                       <installDirectory>./</installDirectory>
+                               </configuration>
+                               <executions>
+                                       <execution>
+                                               <!-- optional: you don't really need execution ids, but it looks nice 
+                                                       in your build log. -->
+                                               <id>install node and npm</id>
+                                               <goals>
+                                                       <goal>install-node-and-npm</goal>
+                                               </goals>
+                                               <phase>generate-resources</phase>
+                                       </execution>
+
+                                       <execution>
+                                               <id>npm install</id>
+                                               <goals>
+                                                       <goal>npm</goal>
+                                               </goals>
+
+                                               <phase>generate-resources</phase>
+
+                                               <configuration>
+                                                       <arguments>install</arguments>
+                                               </configuration>
+                                       </execution>
+
+                                       <execution>
+                                               <id>npm build</id>
+                                               <goals>
+                                                       <goal>npm</goal>
+                                               </goals>
+
+                                               <phase>generate-resources</phase>
+
+                                               <configuration>
+                                                       <arguments>run-script build</arguments>
+                                               </configuration>
+                                       </execution>
+
+                               </executions>
+                       </plugin>
+               </plugins>
+       </build>
+</project>
diff --git a/portal-FE-os/src/.gitignore b/portal-FE-os/src/.gitignore
new file mode 100644 (file)
index 0000000..61810b1
--- /dev/null
@@ -0,0 +1 @@
+/styles/
\ No newline at end of file
diff --git a/portal-FE-os/src/app/.gitignore b/portal-FE-os/src/app/.gitignore
new file mode 100644 (file)
index 0000000..961a384
--- /dev/null
@@ -0,0 +1,8 @@
+/ng-material-module.ts
+!layout/
+/modals/
+/shared/
+!shared/interceptors/
+/pages/
+!pages/application-onboarding
+!pages/users
\ No newline at end of file
diff --git a/portal-FE-os/src/app/app-routing.module.ts b/portal-FE-os/src/app/app-routing.module.ts
new file mode 100644 (file)
index 0000000..0142e63
--- /dev/null
@@ -0,0 +1,49 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+import { NgModule } from '@angular/core';
+import { Routes, RouterModule } from '@angular/router';
+
+const routes: Routes = [
+    { path: '', loadChildren: () => import('./layout/layout.module').then(m => m.LayoutModule) }
+];
+
+@NgModule({
+    imports: [RouterModule.forRoot(routes)],
+    exports: [RouterModule]
+})
+export class AppRoutingModule {}
diff --git a/portal-FE-os/src/app/app.component.html b/portal-FE-os/src/app/app.component.html
new file mode 100644 (file)
index 0000000..dea5177
--- /dev/null
@@ -0,0 +1,39 @@
+<!--
+  ============LICENSE_START==========================================
+  ONAP Portal
+  ===================================================================
+  Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+  ===================================================================
+  Unless otherwise specified, all software contained herein is licensed
+  under the Apache License, Version 2.0 (the "License");
+  you may not use this software except in compliance with the License.
+  You may obtain a copy of the License at
+              http://www.apache.org/licenses/LICENSE-2.0
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  Unless otherwise specified, all documentation contained herein is licensed
+  under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+  you may not use this documentation except in compliance with the License.
+  You may obtain a copy of the License at
+              https://creativecommons.org/licenses/by/4.0/
+  Unless required by applicable law or agreed to in writing, documentation
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT 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============================================
+  
+  -->
+
+<router-outlet></router-outlet>
diff --git a/portal-FE-os/src/app/app.component.scss b/portal-FE-os/src/app/app.component.scss
new file mode 100644 (file)
index 0000000..7a77339
--- /dev/null
@@ -0,0 +1,37 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
\ No newline at end of file
diff --git a/portal-FE-os/src/app/app.component.spec.ts b/portal-FE-os/src/app/app.component.spec.ts
new file mode 100644 (file)
index 0000000..afc476f
--- /dev/null
@@ -0,0 +1,72 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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============================================
+ *
+ * 
+ */s
+import { TestBed, async } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+import { AppComponent } from './app.component';
+
+describe('AppComponent', () => {
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      imports: [
+        RouterTestingModule
+      ],
+      declarations: [
+        AppComponent
+      ],
+    }).compileComponents();
+  }));
+
+  it('should create the app', () => {
+    const fixture = TestBed.createComponent(AppComponent);
+    const app = fixture.debugElement.componentInstance;
+    expect(app).toBeTruthy();
+  });
+
+  it(`should have as title 'portal-FE-os'`, () => {
+    const fixture = TestBed.createComponent(AppComponent);
+    const app = fixture.debugElement.componentInstance;
+    expect(app.title).toEqual('portal-FE-os');
+  });
+
+  it('should render title in a h1 tag', () => {
+    const fixture = TestBed.createComponent(AppComponent);
+    fixture.detectChanges();
+    const compiled = fixture.debugElement.nativeElement;
+    expect(compiled.querySelector('h1').textContent).toContain('Welcome to portal-FE-os!');
+  });
+});
diff --git a/portal-FE-os/src/app/app.component.ts b/portal-FE-os/src/app/app.component.ts
new file mode 100644 (file)
index 0000000..dbfb568
--- /dev/null
@@ -0,0 +1,47 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+import { Component } from '@angular/core';
+
+@Component({
+  selector: 'app-root',
+  templateUrl: './app.component.html',
+  styleUrls: ['./app.component.scss']
+})
+export class AppComponent {
+  
+}
diff --git a/portal-FE-os/src/app/app.module.ts b/portal-FE-os/src/app/app.module.ts
new file mode 100644 (file)
index 0000000..a7b267f
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright Ã¯Â¿Â½ 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+import { CommonModule } from '@angular/common';
+import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
+
+import { AppRoutingModule } from './app-routing.module';
+import { AppComponent } from './app.component';
+import { HeaderInterceptor } from './shared/interceptors/header-interceptor';
+import { CookieService } from 'ngx-cookie-service';
+import { FooterComponent } from './footer/footer.component';
+
+
+@NgModule({
+    imports: [
+        CommonModule,
+        BrowserModule,
+        BrowserAnimationsModule,
+        HttpClientModule,
+        AppRoutingModule
+    ],
+    declarations: [AppComponent, FooterComponent],
+    providers: [CookieService,{
+        provide: HTTP_INTERCEPTORS,
+        useClass: HeaderInterceptor,
+        multi: true,
+    }],
+    bootstrap: [AppComponent]
+})
+export class AppModule { }
diff --git a/portal-FE-os/src/app/layout/components/footer/footer.component.html b/portal-FE-os/src/app/layout/components/footer/footer.component.html
new file mode 100644 (file)
index 0000000..3a4d72a
--- /dev/null
@@ -0,0 +1,45 @@
+<!--
+  ============LICENSE_START==========================================
+  ONAP Portal
+  ===================================================================
+  Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+  ===================================================================
+  Unless otherwise specified, all software contained herein is licensed
+  under the Apache License, Version 2.0 (the "License");
+  you may not use this software except in compliance with the License.
+  You may obtain a copy of the License at
+              http://www.apache.org/licenses/LICENSE-2.0
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  Unless otherwise specified, all documentation contained herein is licensed
+  under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+  you may not use this documentation except in compliance with the License.
+  You may obtain a copy of the License at
+              https://creativecommons.org/licenses/by/4.0/
+  Unless required by applicable law or agreed to in writing, documentation
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT 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============================================
+  
+  -->
+<footer>
+  <!-- <a class="navbar-brand" href="#">Ecomp Portal</a> -->
+  <div id="footer-text" class="footerText">
+    <p class="copyright-text" style="color:white">
+        {{ecompTitle}} Version {{buildVersion}}
+    </p>
+  </div>
+</footer>
\ No newline at end of file
diff --git a/portal-FE-os/src/app/layout/components/footer/footer.component.scss b/portal-FE-os/src/app/layout/components/footer/footer.component.scss
new file mode 100644 (file)
index 0000000..deb2b80
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * ============LICENSE_START==========================================
+ * ONAP Portal SDK
+ * ===================================================================
+ * Copyright ï¿½ 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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============================================
+ *
+ * 
+ */
+$topnav-background-color: #222;
+.footerText {
+  background-color: $topnav-background-color;
+}
+
+.copyright-text {
+  background-color: $topnav-background-color;
+  color: #fff;
+  font-size: 11px;
+  margin-bottom: 0;
+  line-height: 3rem;
+  margin-top: 20px;
+  margin-left: 100px;
+}
diff --git a/portal-FE-os/src/app/layout/components/footer/footer.component.spec.ts b/portal-FE-os/src/app/layout/components/footer/footer.component.spec.ts
new file mode 100644 (file)
index 0000000..ea3a67c
--- /dev/null
@@ -0,0 +1,63 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ *
+ */
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { FooterComponent } from './footer.component';
+
+describe('FooterComponent', () => {
+  let component: FooterComponent;
+  let fixture: ComponentFixture<FooterComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ FooterComponent ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(FooterComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/portal-FE-os/src/app/layout/components/footer/footer.component.ts b/portal-FE-os/src/app/layout/components/footer/footer.component.ts
new file mode 100644 (file)
index 0000000..bfbc292
--- /dev/null
@@ -0,0 +1,58 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ *
+ */
+import { Component, OnInit } from '@angular/core';
+import { ManifestService } from '../shared/services';
+
+@Component({
+  selector: 'app-footer',
+  templateUrl: './footer.component.html',
+  styleUrls: ['./footer.component.scss']
+})
+export class FooterComponent implements OnInit {
+
+  buildVersion;
+  constructor(private manifest: ManifestService) { }
+
+  ngOnInit() {
+    this.manifest.getManifest().subscribe((_res: any) => {
+      this.buildVersion = _res;
+    })
+  }
+
+}
diff --git a/portal-FE-os/src/app/layout/components/global-search/global-search.component.html b/portal-FE-os/src/app/layout/components/global-search/global-search.component.html
new file mode 100644 (file)
index 0000000..ff5473b
--- /dev/null
@@ -0,0 +1,109 @@
+<!--
+  ============LICENSE_START==========================================
+  ONAP Portal
+  ===================================================================
+  Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+  ===================================================================
+  Unless otherwise specified, all software contained herein is licensed
+  under the Apache License, Version 2.0 (the "License");
+  you may not use this software except in compliance with the License.
+  You may obtain a copy of the License at
+              http://www.apache.org/licenses/LICENSE-2.0
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  Unless otherwise specified, all documentation contained herein is licensed
+  under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+  you may not use this documentation except in compliance with the License.
+  You may obtain a copy of the License at
+              https://creativecommons.org/licenses/by/4.0/
+  Unless required by applicable law or agreed to in writing, documentation
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  ============LICENSE_END============================================
+  
+  -->
+<div class="search-div" (clickOutside)="clickOutSide($event)">
+  <div class="notification-div">
+    <div class="form-field form-field__small">
+      <div class="search-input">
+        <input id="mainSearchText" style="border-radius:0.25rem;" type="text" (keypress)="searchDialogToggle($event)"
+          placeholder="What are you looking for?" class="form-field form-field__small" />
+      </div>
+      <span class="icon-search-span"> <i class="icon-search">&nbsp;</i>
+      </span>
+
+    </div>
+  </div>  
+</div>
+<div *ngIf="searchResDialog" class="search-res-dialog">
+  <div id="reg-header-snippet">
+
+    <div tabindex="0"  id="reg-searchPop-id">
+      <div id="contentVertical" att-scrollbar="y">
+        <ul class="searchUl">
+          <li><a class="icon-tiles"></a> <a id="search-app-title" (click)="goToUrl(item)"
+              class="searchLiHeader">Applications:</a>
+          </li>
+          <li *ngFor="let item of items?.application"><a
+              id="search-app-item-{{item.name.split(' ').join('-')}}-{{$index}}" (click)="goToUrl(item)"
+              class="searchLiItems">{{item.name}}</a>
+          </li>
+        </ul>
+
+        <ul class="searchUl">
+          <li><a class="icon-tiles-small"></a> <a id="seach-functional-menu-title" (click)="goToUrl(item)"
+              class="searchLiHeader">Functional Menus:</a></li>
+          <li *ngFor="let item of items?.menu"><a
+              id="search-functional-menu-item-{{item.name.split(' ').join('-')}}-{{$index}}" (click)="goToUrl(item)"
+              class="searchLiItems">{{item.name}}</a>
+          </li>
+        </ul>
+
+
+        <ul class="searchUl">
+          <li><a class="full-linear-icon-person search-li"></a> <a id="search-user-title" (click)="goToUrl(item)"
+              class="searchLiHeader">Users:</a></li>
+          <li *ngFor="let item of items?.user"><a id="search-user-item-{{item.name.split(' ').join('-')}}-{{$index}}"
+              href="qto://talk/{{item.target}}" class="searchLiItems">{{item.name}}</a>
+
+          </li>
+        </ul>
+
+        <ul class="searchUl">
+          <li><a class="full-linear-icon-person search-li"></a> <a id="search-widgets-title" (click)="goToUrl(item)"
+              class="searchLiHeader">Widgets:</a></li>
+          <li *ngFor="let item of items?.widget"><a
+              id="search-widgets-item-{{item.name.split(' ').join('-')}}-{{$index}}" href="widgetCatalog"
+              class="searchLiHeader">{{item.name}}</a></li>
+        </ul>
+
+        <ul class="searchUl">
+          <li><a class="full-linear-icon-internet search-li"></a> <a id="search-intranet"
+              (click)="goToUrl(item, 'intra')" class="searchLiHeader" style="cursor: pointer;">Click to search
+              Intranet <span class="icon-arrow-right"></span>
+            </a></li>
+        </ul>
+
+        <ul class="searchUl">
+          <li><a class="full-linear-icon-internet search-li"></a> <a id="search-extranet"
+              (click)="goToUrl(item, 'extra')" class="searchLiHeader" style="cursor: pointer;">Click to search
+              Extranet <span class="icon-arrow-right"></span></a></li>
+        </ul>
+
+      </div>
+    </div>
+  </div>
+</div>
\ No newline at end of file
diff --git a/portal-FE-os/src/app/layout/components/global-search/global-search.component.scss b/portal-FE-os/src/app/layout/components/global-search/global-search.component.scss
new file mode 100644 (file)
index 0000000..70f1b34
--- /dev/null
@@ -0,0 +1,74 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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============================================
+ *
+ * 
+ */
+
+ .search-div {
+    margin-bottom: -14px;
+  }
+
+  .search-res-dialog{
+    position: fixed;
+      background: white;
+      box-shadow: rgba(0, 0, 0, 0.247059) 0px 5px 6px 0px;
+      top: 2.5em;
+      border-radius: 0.25rem;
+      padding: 20px;
+      opacity: 1;
+      z-index: 1;
+  }
+  .searchUl {
+    list-style: none; 
+    border-bottom: 1px solid #bbb; 
+    padding-bottom: 20px;
+    padding-left: 4px;
+    }
+    .searchLiHeader {
+      font-weight: bold; 
+      color: #0574ac; 
+      font-size: 16px;
+      padding-bottom: 10px;
+      line-height: 1.5;
+      font-family: Omnes-ECOMP-W02,Arial;
+      
+      }
+      .searchLiItems{
+        cursor: pointer;
+        font-weight: normal; 
+        font-size: 12px;
+        color: #444444;
+        font-family: Omnes-ECOMP-W02,Arial;
+        }
\ No newline at end of file
diff --git a/portal-FE-os/src/app/layout/components/global-search/global-search.component.spec.ts b/portal-FE-os/src/app/layout/components/global-search/global-search.component.spec.ts
new file mode 100644 (file)
index 0000000..c377137
--- /dev/null
@@ -0,0 +1,62 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { GlobalSearchComponent } from './global-search.component';
+
+describe('GlobalSearchComponent', () => {
+  let component: GlobalSearchComponent;
+  let fixture: ComponentFixture<GlobalSearchComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ GlobalSearchComponent ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(GlobalSearchComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/portal-FE-os/src/app/layout/components/global-search/global-search.component.ts b/portal-FE-os/src/app/layout/components/global-search/global-search.component.ts
new file mode 100644 (file)
index 0000000..4a6fb20
--- /dev/null
@@ -0,0 +1,114 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+import { Component, OnInit, Output, EventEmitter } from '@angular/core';
+import { GlobalSearchService } from 'src/app/shared/services/global-search/global-search.service';
+import { GlobalSearchItem } from 'src/app/shared/model/global-search-item.model';
+import * as $ from 'jquery';
+import { AddTabFunctionService } from 'src/app/shared/services/tab/add-tab-function.service';
+
+@Component({
+  selector: 'app-global-search',
+  templateUrl: './global-search.component.html',
+  styleUrls: ['./global-search.component.scss']
+})
+export class GlobalSearchComponent implements OnInit {
+  searchResDialog: boolean = false;
+  items: any;
+  constructor(private globalSearchService: GlobalSearchService,private addTabFuntionService: AddTabFunctionService) { }
+
+  ngOnInit() {
+  }
+
+  showHideSearchSnippet() {
+    setTimeout(() => {
+      $('#mainSearchSnippet').click();
+    }, 1000);
+    setTimeout(() => {
+      $('mainSearchText').focus();
+    }, 1000);
+  }
+
+  mainSearchEvent = $('#mainSearchDiv').keyup((event) => {
+    if (event.keyCode == 13) {
+
+      this.getSearchResult(<string><any>$('#mainSearchText').val());
+
+      // opens the popup
+      var popupDomObj = $("[content='searchSnippet.html']");
+      if (popupDomObj.length == 0) {
+        this.showHideSearchSnippet();
+      } else {
+        $('#mainSearchSnippet').click();
+        this.showHideSearchSnippet();
+      }
+
+
+
+    }
+  });
+
+  clickOutSide(event: any) {
+
+    this.searchResDialog = false;
+
+  }
+  searchDialogToggle(event: any) {
+    if (event.keyCode == 13) {
+      this.searchResDialog = true;
+      this.getSearchResult(<string><any>$('#mainSearchText').val());
+    }
+  }
+
+  getSearchResult(searchString: string) {
+    //console.log("getSearch Result");
+    this.globalSearchService.getSearchResults(searchString).subscribe(data => {
+      //console.log("Response data" + data);
+      this.items = data.response;
+      //console.log("search result data" + JSON.stringify(data));
+
+    }, error => {
+      console.log('getSearchResult Error Object' + error);
+    });
+  };
+  goToUrl(item: any){
+    //console.log('check goto');
+    var a = {'test1':'value1','test2':'value3','test3':'value2'};
+    this.addTabFuntionService.filter(a);
+  }
+
+}
diff --git a/portal-FE-os/src/app/layout/components/header-menu/header-menu.component.html b/portal-FE-os/src/app/layout/components/header-menu/header-menu.component.html
new file mode 100644 (file)
index 0000000..b1d4d83
--- /dev/null
@@ -0,0 +1,128 @@
+<!--
+  ============LICENSE_START==========================================
+  ONAP Portal
+  ===================================================================
+  Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+  ===================================================================
+  Unless otherwise specified, all software contained herein is licensed
+  under the Apache License, Version 2.0 (the "License");
+  you may not use this software except in compliance with the License.
+  You may obtain a copy of the License at
+              http://www.apache.org/licenses/LICENSE-2.0
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  Unless otherwise specified, all documentation contained herein is licensed
+  under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+  you may not use this documentation except in compliance with the License.
+  You may obtain a copy of the License at
+              https://creativecommons.org/licenses/by/4.0/
+  Unless required by applicable law or agreed to in writing, documentation
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  ============LICENSE_END============================================
+  
+  -->
+<div id="container" style="width: 100%;" (clickOutside)="clickOutSide($event)">
+  <!-- First Level menu -->
+  <div id="megaMenu-{{item.text.split(' ').join('-')}}"
+    *ngFor="let item of megaMenuDataObject;let megaMenuIndex = index" (mousedown)="loadFirstLevel(megaMenuIndex)"
+    role="presentation" class="header-menu-item-div"><a href="javascript:void(0);" id="parentmenu-tabs" role="menuitem"
+      class="header-menu-item-link">{{item.text}}<b class="caret"></b><span class="sr-only"></span></a>
+
+    <div class="header-secondlevel-menu" *ngIf="item.active_yn=='Y' && hideMenus[megaMenuIndex]">
+      <ul class="header-secondary" role="menu">
+        <!-- Second Level menu -->
+        <li class="header-menu-item-li" id="subItem-{{i.text.split(' ').join('-')}}"
+          *ngFor="let i of item.children;let secondLevelIndex = index"
+          (mousemove)="hideThirdLevelMenu(megaMenuIndex,secondLevelIndex)" role="presentation">
+          <!-- Favorites -->
+
+          <div *ngIf="i.text=='Favorites'">
+            <a href="javascript:void(0);" class="menu__item" role="menuitem">{{i.text}}</a>
+            <i id="favorite-star" data-size="large" class="icon-star favorites-icon-active"></i>
+            <div class="header-columns-div" *ngIf="hideSecondLevelMenus[megaMenuIndex][secondLevelIndex]">
+              <div class="header-tertiary-wrapper" id="header-favorites">
+                <ul class="header-tertiary" role="menu">
+                  <li role="presentation">
+                    <div *ngFor="let subItem of (favoritesMenuItems ? favoritesMenuItems : [])"
+                      id="favoritesMenuItems-{{subItem.text.split(' ').join('-')}}">
+                      <div class="fav-links">
+                        <i id="favorite-selector-favorites-list" class="icon-star favorites-icon-active"
+                          (click)="removeAsFavoriteItem($event, subItem.menuId)"
+                          (mousedown)="removeAsFavoriteItem($event, subItem.menuId)">
+                        </i> <a id="favorites-list" (click)="goToUrl(subItem)">{{subItem.text}}</a>
+                      </div>
+                    </div>
+
+                    <div id="favorites-empty" class="favorites-window-empty" *ngIf="emptyFavorites">
+                      <p id="p-no-favs-icon" class="no-fav-icon">
+                        <span class="icon-star"></span>
+                      </p>
+                      <p id="p-no-favs" class="largeText">{{'No
+                              Favorites'}}</p>
+                      <p id="p-no-favs-desc" class="normal">{{'Add your
+                              favorite items for quick access'}}.</p>
+                    </div>
+                  </li>
+                </ul>
+              </div>
+            </div>
+          </div> <!-- Support or Help -->
+          <div *ngIf="item.text=='Support' || item.text=='Help'" id="second-level-menus-help">
+            <a id="second-level-menus-{{i.text.split(' ').join('-')}}-help" href="javascript:void(0);"
+              (click)="goToUrl(i);auditLog(i,'Support')" class="menu__item" role="menuitem">{{i.text}}</a>
+          </div> <!-- Others -->
+          <div *ngIf="i.text!='Favorites' && (item.text!='Support' && item.text!='Help')">
+            <a href="javascript:void(0);" class="menu__item" role="menuitem">{{i.text}}</a>
+            <div class="header-thirdlevel-menu" *ngIf="hideSecondLevelMenus[megaMenuIndex][secondLevelIndex]">
+              <ul class="third-level-menu" role="menu" id="third-level-menus">
+                <!-- Third Level menu -->
+
+                <li *ngFor="let link of i.children" role="presentation"><i id="level3-star-inactive-{{link.menuId}}"
+                    class="icon-star favorites-icon-inactive" data-size="large"
+                    (mousedown)="setAsFavoriteItem($event, link.menuId)"
+                    *ngIf="link.url.length > 1 && isUrlFavorite(link.menuId)==false">
+                  </i> <i id="level3-star-active-{{link.menuId}}"
+                    *ngIf="link.url.length > 1 && isUrlFavorite(link.menuId)" class="icon-star favorites-icon-active"
+                    data-size="large" (mousedown)="removeAsFavoriteItem($event, link.menuId)">
+                  </i> <a class="third-level-title"
+                    (mousedown)="goToUrl(link);auditLog(link,'application')">{{link.text}}</a>
+                  <!-- Fourth Level menu -->
+                  <div *ngFor="let title of link.children">
+                    <i id="level4-star-inactive-{{title.menuId}}" class="icon-star favorites-icon-inactive"
+                      (mousedown)="setAsFavoriteItem($event, title.menuId)"
+                      *ngIf="title.url.length > 1 && isUrlFavorite(title.menuId)==false">
+                    </i> <i id="level4-star-active-{{title.menuId}}" class="icon-star favorites-icon-active"
+                      (mousedown)="removeAsFavoriteItem($event, title.menuId)"
+                      *ngIf="title.url.length > 1 && isUrlFavorite(title.menuId)">
+                    </i> <a href="javascript:void(0);" class="header-tertiaryitem"
+                      [ngClass]="{'disabled': title.disabled}" role="menuitem"
+                      (mousedown)="goToUrl(title);auditLog(title,'functional')">{{title.text}}</a>
+                  </div>
+                </li>
+
+
+
+
+              </ul>
+            </div>
+          </div>
+
+        </li>
+      </ul>
+    </div>
+  </div>
+</div>
\ No newline at end of file
diff --git a/portal-FE-os/src/app/layout/components/header-menu/header-menu.component.scss b/portal-FE-os/src/app/layout/components/header-menu/header-menu.component.scss
new file mode 100644 (file)
index 0000000..d69b858
--- /dev/null
@@ -0,0 +1,150 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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============================================
+ *
+ * 
+ */
+ .header-menu-item-div
+ {
+     float: left; 
+     margin-right: 5%;
+ }
+ .header-menu-item-li
+ {
+     float: left; 
+     margin-right: 2%;
+     
+ }
+ .header-menu-item-link
+ {
+     font-family:"Open Sans", Arial;
+     font-size:16px;
+     color:#999;
+     text-decoration:none;
+     
+ }
+ #parentmenu-tabs:hover {
+     color: #fff;
+ }
+ .third-level-menu{
+ column-count: 4;
+     line-height: 12px;
+     overflow-x: hidden;
+     overflow-y: hidden;
+     column-gap: 13px;
+     column-rule: 1px outset #d2d2d2;
+     margin-left:20px;
+ }
+ .third-level-menu a{
+  color:black;
+ }
+ .third-level-menu li a {
+     color: #333;
+     display: inline-flex;
+     padding: 7px 15px;
+     font-family:"Omnes-ECOMP-W02", Arial;
+     margin-top:5px;
+   margin-bottom:5px;
+ }
+ .third-level-menu li{
+     width:100%;
+     border-bottom: 1px solid #d2d2d2;
+ }
+ .b2b-header-tabs .header-secondary .header-subitem a.menu__item{
+   font-size:16px;
+ }
+ .third-level-title{
+   font-size:15px;
+   font-weight: 700;
+ }
+ .header-secondlevel-menu 
+   {
+     background-color: #fff;
+     position: fixed;
+     right:1%;
+     width: -webkit-fill-available;
+     
+   }
+   .header-thirdlevel-menu 
+   {
+     background-color: #fff;
+     position: fixed;
+     left:0;
+     height: 70%;    
+     width: 100%;
+   }
+   
+   a.menu__item{
+    font-size:16px;
+    font-family:"Open Sans", Arial;
+    color:#333;
+  }
\ No newline at end of file
diff --git a/portal-FE-os/src/app/layout/components/header-menu/header-menu.component.spec.ts b/portal-FE-os/src/app/layout/components/header-menu/header-menu.component.spec.ts
new file mode 100644 (file)
index 0000000..889f499
--- /dev/null
@@ -0,0 +1,62 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { HeaderMenuComponent } from './header-menu.component';
+
+describe('HeaderMenuComponent', () => {
+  let component: HeaderMenuComponent;
+  let fixture: ComponentFixture<HeaderMenuComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ HeaderMenuComponent ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(HeaderMenuComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/portal-FE-os/src/app/layout/components/header-menu/header-menu.component.ts b/portal-FE-os/src/app/layout/components/header-menu/header-menu.component.ts
new file mode 100644 (file)
index 0000000..eb8f747
--- /dev/null
@@ -0,0 +1,231 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+import * as _ from 'underscore';
+import { Component, OnInit } from '@angular/core';
+import { MenusService } from 'src/app/shared/services/menus/menus.service';
+import { AddTabFunctionService } from 'src/app/shared/services/tab/add-tab-function.service';
+import { Router } from '@angular/router';
+
+@Component({
+  selector: 'app-header-menu',
+  templateUrl: './header-menu.component.html',
+  styleUrls: ['./header-menu.component.scss']
+})
+export class HeaderMenuComponent implements OnInit {
+  hideMenus: boolean[] = [];
+  hideSecondLevelMenus: boolean[][] = [];
+  hideThirdLevelMenus: boolean[] = [];
+  megaMenuDataObject: any[];
+  favoritesMenuItems: any[];
+  favoritesWindow: boolean;
+  showFavorites: boolean;
+  emptyFavorites: boolean;
+  favoriteItemsCount: number;
+
+  constructor(public router: Router, private menusService: MenusService, private addTabFuntionService: AddTabFunctionService) { }
+
+  ngOnInit() {
+    //this.hideMenus[0] = false;
+    this.getFunctionalMenuForUser();
+
+  }
+
+  unflatten(array: any, parent?: any, tree?: any) {
+    tree = typeof tree !== 'undefined' ? tree : [];
+    parent = typeof parent !== 'undefined' ? parent : { menuId: null };
+    var children = _.filter(array, function (child: any) {
+      return child.parentMenuId == parent.menuId;
+    });
+    if (!_.isEmpty(children)) {
+      if (parent.menuId === null) {
+        tree = children;
+      } else {
+        parent['children'] = children
+      }
+      _.each(children, function (child: any) {
+        this.unflatten(array, child)
+      }, this);
+    }
+
+    return tree;
+  }
+  getFunctionalMenuForUser() {
+    this.menusService.getFunctionalMenuForUser().subscribe((jsonHeaderMenu: any) => {
+      this.megaMenuDataObject = this.unflatten(jsonHeaderMenu);
+      // for (let entry of this.megaMenuDataObject) {
+      //   console.log('First level '+entry.text);
+      //   for (let secondLevel of entry.children)
+      //   {
+      //     if(secondLevel)
+      //   {
+      //     console.log('Second level '+secondLevel.text);
+      //     for (let thirdLevel of secondLevel.children)
+      //   {
+      //     console.log('Third level '+thirdLevel.text);
+      //   }
+      //   }
+
+      //   }
+
+      // }
+
+
+    }, (err) => {
+      console.log('HeaderCtrl::GetFunctionalMenuForUser: HeaderCtrl json returned: ' + err);
+    });
+
+  }
+  getFavoriteItems() {
+    this.menusService.getFavoriteItems().toPromise().then((jsonFavourites: any) => {
+      this.favoritesMenuItems = jsonFavourites;
+      if (this.favoritesMenuItems) {
+        this.favoriteItemsCount = this.favoritesMenuItems.length;
+      }
+    }, (err) => {
+      console.log('HeaderCtrl::getFavoriteItems: HeaderCtrl json returned: ' + err);
+    });
+  }
+  loadFirstLevel(index: any) {
+    this.hideMenus = [];
+    this.hideSecondLevelMenus = [];
+    for (let firstLevelIndex = 0; firstLevelIndex < this.megaMenuDataObject.length; firstLevelIndex++) {
+      this.hideMenus.push(false);
+      this.hideSecondLevelMenus.push(new Array(this.megaMenuDataObject[firstLevelIndex].length).fill(false));
+    }
+    this.hideMenus[index] = true;
+    if (!this.favoritesMenuItems) {
+      this.getFavoriteItems();
+    }
+
+  }
+  isUrlFavorite(menuId: any) {
+    if (this.favoritesMenuItems) {
+      var jsonMenu = JSON.stringify(this.favoritesMenuItems);
+      var isMenuFavorite = jsonMenu.indexOf('menuId\":' + menuId);
+      if (isMenuFavorite == -1) {
+        return false;
+      } else {
+        return true;
+      }
+    }
+    else {
+      return false;
+    }
+  }
+  submenuLevelAction(index: any, column: any) {
+    //console.log('index and column' + index + column);
+    if (index == 'Favorites' && this.favoriteItemsCount != 0) {
+      this.favoritesWindow = true;
+      this.showFavorites = true;
+      this.emptyFavorites = false;
+    }
+    if (index == 'Favorites' && this.favoriteItemsCount == 0) {
+      this.favoritesWindow = true;
+      this.showFavorites = false;
+      this.emptyFavorites = true;
+    }
+    if (index != 'Favorites') {
+      this.favoritesWindow = false;
+      this.showFavorites = false;
+      this.emptyFavorites = false;
+    }
+  }
+  hideFavoritesWindow() {
+    this.showFavorites = false;
+    this.emptyFavorites = false;
+  }
+  removeAsFavoriteItem(event: any, menuId: any) {
+    this.menusService.removeFavoriteItem(menuId).subscribe(() => {
+      //angular.element('#' + event.target.id).css('color', '#666666');
+      this.getFavoriteItems();
+    }, (err) => {
+      console.error('HeaderCtrl::removeAsFavoriteItem: API removeFavoriteItem error: ' + err);
+    });
+  }
+  hideThirdLevelMenu(firstLevelIndex: any, secondLevelIndex: any) {
+    this.hideSecondLevelMenus = [];
+    for (let firstLevelIndex = 0; firstLevelIndex < this.megaMenuDataObject.length; firstLevelIndex++) {
+      this.hideSecondLevelMenus.push(new Array(this.megaMenuDataObject[firstLevelIndex].length).fill(false));
+    }
+    this.hideSecondLevelMenus[firstLevelIndex][secondLevelIndex] = true;
+  }
+
+  clickOutSide(event: any) {
+    this.hideMenus = [];
+    this.hideSecondLevelMenus = [];
+    for (let firstLevelIndex = 0; firstLevelIndex < this.megaMenuDataObject.length; firstLevelIndex++) {
+      this.hideMenus.push(false);
+      this.hideSecondLevelMenus.push(new Array(this.megaMenuDataObject[firstLevelIndex].length).fill(false));
+    }
+
+  }
+  setAsFavoriteItem(event: any, menuId: any) {
+
+  }
+  goToUrl(item: any) {
+    //console.log('Get into URL function' + item.url);
+    let url = item.url;
+    let restrictedApp = item.restrictedApp;
+    if (!url) {
+      console.log('HeaderCtrl::goToUrl: No url found for this application, doing nothing..');
+      return;
+    }
+    if (restrictedApp) {
+      window.open(url, '_blank');
+    } else {
+      if (item.url == "getAccess" || item.url == "contactUs") {
+
+        this.router.navigate(['/' + item.url]);
+
+      } else {
+        var tabContent = {
+          id: new Date(),
+          title: item.text,
+          url: item.url,
+          appId: item.appid
+        };
+        this.addTabFuntionService.filter(tabContent);
+      }
+    }
+
+  }
+  auditLog(link: any, action: any) {
+
+  }
+
+}
diff --git a/portal-FE-os/src/app/layout/components/header/header.component.html b/portal-FE-os/src/app/layout/components/header/header.component.html
new file mode 100644 (file)
index 0000000..d8c938d
--- /dev/null
@@ -0,0 +1,129 @@
+<!--
+  ============LICENSE_START==========================================
+  ONAP Portal
+  ===================================================================
+  Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+  ===================================================================
+  Unless otherwise specified, all software contained herein is licensed
+  under the Apache License, Version 2.0 (the "License");
+  you may not use this software except in compliance with the License.
+  You may obtain a copy of the License at
+              http://www.apache.org/licenses/LICENSE-2.0
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  Unless otherwise specified, all documentation contained herein is licensed
+  under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+  you may not use this documentation except in compliance with the License.
+  You may obtain a copy of the License at
+              https://creativecommons.org/licenses/by/4.0/
+  Unless required by applicable law or agreed to in writing, documentation
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  ============LICENSE_END============================================
+  
+  -->
+
+<div style="bottom: tabBottom; display: flex; height: 100%; overflow: hidden">
+    <nav class="navbar navbar-expand-lg fixed-top">
+        <div class="header-menu-display">
+            <app-header-menu></app-header-menu>
+        </div>
+        <button class="navbar-toggler" type="button" (click)="toggleSidebar()">
+            <i class="icon ion-md-menu" style="color:white;"></i>
+        </button>
+        <div class="collapse navbar-collapse">
+            <ul class="navbar-nav ml-auto">
+                <app-global-search></app-global-search>
+                <li class="nav-item dropdown" ngbDropdown>
+                    <a href="javascript:void(0)" class="nav-link" ngbDropdownToggle>
+                        <i class="icon ion-md-bulb"></i> <b class="caret"></b><span class="sr-only"></span>
+                    </a>
+                    <div class="custom-dropdown-item" ngbDropdownMenu>
+
+                <li class="dropdown-divider"></li>
+        </div>
+        </li>
+        <li class="nav-item dropdown" ngbDropdown>
+            <a href="javascript:void(0)" class="nav-link" ngbDropdownToggle>
+                <i class="icon ion-md-flag"></i> <b class="caret"></b><span class="sr-only"></span>
+            </a>
+            <div class="dropdown-menu-right" ngbDropdownMenu>
+                <a style="margin-left: 8%;" id="application-role" [routerLink]="['/recentNotifications']"
+                    href="javascript:void(0);">
+                    {{ 'View All Recent Notifications' }} </a>
+        <li class="dropdown-divider"></li>
+</div>
+</li>
+<li class="nav-item dropdown" ngbDropdown>
+    <a href="javascript:void(0)" class="nav-link" ngbDropdownToggle>
+        <i class="icon ion-md-person"></i> {{firstName}} <b class="caret"></b>
+    </a>
+    <div class="dropdown-menu-right" ngbDropdownMenu>
+<li class="dropdown-item" style="font-weight: lighter">
+    {{firstName}}, {{lastName}}
+</li>
+<li class="dropdown-item">
+    <span class="dropdown-item-name"> {{ 'Email'}}: </span>
+    <div>
+        <span class="dropdown-item-value">
+            {{loginSnippetEmail}}
+        </span>
+    </div>
+</li>
+<li class="dropdown-item">
+    <span class="dropdown-item-name"> {{ 'User Id' }}: </span>
+    <div>
+        <span class="dropdown-item-value">
+            {{loginSnippetUserid}}
+        </span>
+    </div>
+</li>
+<li class="dropdown-item">
+    <span class="dropdown-item-name"> {{ 'Last login' }}: </span>
+    <div>
+        <span class="dropdown-item-value">
+            {{lastLogin | date:'medium'}}
+        </span>
+    </div>
+</li>
+<li class="custom-display-item">
+    <a (click)="getUserApplicationRoles()" href="javascript:void(0);"><span><i class="icon ion-md-add-circle-outline"
+                [ngClass]="{true: 'icon ion-md-add-circle-outline', false: 'icon ion-md-remove-circle-outline'}[ !displayUserAppRoles]"></i>
+            {{ 'Applications and Roles' }} </span></a>
+    <span class="ecomp-spinner" *ngIf="isLoading"></span>
+</li> <br>
+<div class="custom-display-item approles" [hidden]="!displayUserAppRoles">
+    <div *ngFor="let ua of userapproles ; index as i">
+        <div class="reg-userApp-value">
+            <span class="dropdown-item-name">{{ua.App}}:</span>
+        </div>
+        <div *ngFor="let role of ua.Roles ; index as i" class="reg-userAppRoles-value">
+            <span *ngIf="role.indexOf('global_')!=-1" id="required" style="color: Red;" visible="false">
+                *</span> <span class="dropdown-item-value">{{role}}</span>
+        </div>
+        <br>
+    </div>
+</div>
+<hr>
+<div id="reg-logout-div" >
+<button type="button" class="btn btn-primary"  (click)="allAppsLogout()">
+    <i class="icon ion-md-log-out"></i> {{ 'Log Out' }} </button></div>
+</div>
+</li>
+</ul>
+</div>
+</nav>
+</div>
\ No newline at end of file
diff --git a/portal-FE-os/src/app/layout/components/header/header.component.scss b/portal-FE-os/src/app/layout/components/header/header.component.scss
new file mode 100644 (file)
index 0000000..c1ef2a3
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright ï¿½ 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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============================================
+ *
+ * 
+ */
+$topnav-background-color: #222;
+:host {
+  .navbar {
+    background-color: $topnav-background-color;
+    .navbar-brand {
+      color: #fff;
+    }
+    .nav-item > a {
+      color: #999;
+      &:hover {
+        color: #fff;
+      }
+    }
+  }
+
+  .dropdown-menu-right.dropdown-menu.show{
+    width: 250px;
+  }
+  .dropdown-item-name {
+    font-weight: bold;
+  }
+
+  .dropdown-item-value {
+    font-weight: lighter;
+  }
+
+  .custom-display-item {
+    display: block;
+    width: 100%;
+    padding: 0.25rem 1.5rem;
+    clear: both;
+    font-weight: 400;
+    color: #212529;
+    text-align: inherit;
+    white-space: nowrap;
+    background-color: transparent;
+    border: 0;
+  }
+
+  .custom-display-item.approles {
+    overflow-y: scroll;
+    height: 250px;
+  }
+  .header-menu-display {
+    width: 250px;
+  }
+}
diff --git a/portal-FE-os/src/app/layout/components/header/header.component.spec.ts b/portal-FE-os/src/app/layout/components/header/header.component.spec.ts
new file mode 100644 (file)
index 0000000..1bcd2ff
--- /dev/null
@@ -0,0 +1,63 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { HeaderComponent } from './header.component';
+
+describe('HeaderComponent', () => {
+  let component: HeaderComponent;
+  let fixture: ComponentFixture<HeaderComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ HeaderComponent ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(HeaderComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/portal-FE-os/src/app/layout/components/header/header.component.ts b/portal-FE-os/src/app/layout/components/header/header.component.ts
new file mode 100644 (file)
index 0000000..5248200
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright ï¿½ 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+import { Component, OnInit } from '@angular/core';
+import { Router, NavigationEnd } from '@angular/router';
+import { UserProfileService, MenusService } from 'src/app/shared/services';
+import { CookieService } from 'ngx-cookie-service';
+
+@Component({
+    selector: 'app-header',
+    templateUrl: './header.component.html',
+    styleUrls: ['./header.component.scss']
+})
+export class HeaderComponent implements OnInit {
+    public pushRightClass: string;
+    firstName: string;
+    lastName: string;
+    loginSnippetUserid: any;
+    lastLogin: number;
+    loginSnippetEmail: any;
+    userapproles: any[];
+    displayUserAppRoles: any;
+    isLoading: boolean;
+
+    constructor(public router: Router, private userProfileService: UserProfileService, private menusService: MenusService, private cookieService: CookieService) {
+
+        this.router.events.subscribe(val => {
+            if (
+                val instanceof NavigationEnd &&
+                window.innerWidth <= 992 &&
+                this.isToggled()
+            ) {
+                this.toggleSidebar();
+            }
+        });
+    }
+
+    ngOnInit() {
+        this.pushRightClass = 'push-right';
+        this.getUserInformation();
+    }
+
+    getUserInformation() {
+        this.userProfileService.getFunctionalMenuStaticInfo().toPromise().then((res: any) => {
+            if (res == null || res.firstName == null || res.firstName == '' || res.lastName == null || res.lastName == '') {
+                // $log.info('HeaderCtrl: failed to get all required data, trying user profile');
+                this.userProfileService.getUserProfile().toPromise().then((profile: any) => {
+                    this.firstName = profile.firstName;
+                    this.lastName = profile.lastName;
+                }, (err) => {
+                    // $log.error('Header Controller:: getUserProfile() failed: ' + err);
+                });
+            } else {
+                this.firstName = res.firstName;
+                this.lastName = res.lastName;
+                this.loginSnippetEmail = res.email;
+                this.loginSnippetUserid = res.userId;
+                this.lastLogin = Date.parse(res.last_login);
+            }
+            sessionStorage.userId = res.userId;
+            this.menusService.getFunctionalMenuForUser().toPromise().then((jsonHeaderMenu: any) => {
+                // $scope.menuItems = unflatten(jsonHeaderMenu);
+                // $scope.megaMenuDataObject = $scope.menuItems;
+            }, (err) => {
+                // $log.error('HeaderCtrl::GetFunctionalMenuForUser: HeaderCtrl json returned: ' + err);
+            });
+
+        }, (err) => {
+            // $log.error('HeaderCtrl::getFunctionalMenuStaticInfo failed: ' + err);
+        })
+    }
+
+    //     unflatten = function( array, parent, tree ){
+
+    //     tree = typeof tree !== 'undefined' ? tree : [];
+    //     parent = typeof parent !== 'undefined' ? parent : { menuId: null };
+    //     var children = _.filter( array, function(child){ return child.parentMenuId == parent.menuId; });
+
+    //     if( !_.isEmpty( children )  ){
+    //       if( parent.menuId === null ){
+    //         tree = children;
+    //       }else{
+    //         parent['children'] = children
+    //       }
+    //       _.each( children, function( child ){ unflatten( array, child ) } );
+    //     }
+
+    //     return tree;
+    // }
+
+    getUserApplicationRoles() {
+        this.userapproles = [];
+        if (this.displayUserAppRoles) {
+            this.displayUserAppRoles = false;
+        } else {
+            this.displayUserAppRoles = true;
+            this.isLoading = true;
+            this.userProfileService.getUserAppRoles(this.loginSnippetUserid)
+            .subscribe((res: any) => {
+                this.isLoading = false;
+                for (var i = 0; i < res.length; i++) {
+                    var userapprole = {
+                        App: res[i].appName,
+                        Roles: res[i].roleNames,
+                    };
+                    this.userapproles.push(userapprole);
+                }
+            }, (err) => {
+                this.isLoading = false;
+            });
+        }
+    }
+
+    allAppsLogout() {
+        this.firstName="";
+        this.lastName="";
+        this.displayUserAppRoles=false;        
+        var cookieTabs = this.cookieService.get("visInVisCookieTabs").toString;
+         if(cookieTabs!=null){
+             for(var t in cookieTabs){
+             
+                 var url = cookieTabs[t].content;
+                 if(url != "") {
+                     this.menusService.logout(url);
+                   }
+             }
+         }
+         // wait for individual applications to log out before the portal logout
+         setTimeout(function() {
+             window.location.href = "logout.htm";
+         }, 2000);
+    }
+
+    isToggled(): boolean {
+        const dom: Element = document.querySelector('body');
+        return dom.classList.contains(this.pushRightClass);
+    }
+
+    toggleSidebar() {
+        const dom: any = document.querySelector('body');
+        dom.classList.toggle(this.pushRightClass);
+    }
+
+    onLoggedout() {
+        localStorage.removeItem('isLoggedin');
+    }
+}
diff --git a/portal-FE-os/src/app/layout/components/search-users/search-users.component.html b/portal-FE-os/src/app/layout/components/search-users/search-users.component.html
new file mode 100644 (file)
index 0000000..4c318f9
--- /dev/null
@@ -0,0 +1,73 @@
+<!--
+  ============LICENSE_START==========================================
+  ONAP Portal
+  ===================================================================
+  Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+  ===================================================================
+  Unless otherwise specified, all software contained herein is licensed
+  under the Apache License, Version 2.0 (the "License");
+  you may not use this software except in compliance with the License.
+  You may obtain a copy of the License at
+              http://www.apache.org/licenses/LICENSE-2.0
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  Unless otherwise specified, all documentation contained herein is licensed
+  under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+  you may not use this documentation except in compliance with the License.
+  You may obtain a copy of the License at
+              https://creativecommons.org/licenses/by/4.0/
+  Unless required by applicable law or agreed to in writing, documentation
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT 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============================================
+  
+  -->
+
+<form>
+    {{searchTitle}}
+    <div class="form-row">
+        <div class="col-md-6 my-1">
+            <label for="inputSearch" class="sr-only"></label>
+            <input id="inputSearch" pattern="[a-zA-Z0-9-'\s]{3,}" [(ngModel)]="searchString" (keyup)="passSystemUserInfo($event.srcElement.value)" maxlength="80"
+                required="true" name="searchString" #searchInput auto-focus tabindex="0" autocomplete="off" type="text"
+                class="form-control" value="searchString" placeholder="{{placeHolder}}">
+        </div>
+
+        <div class="col-auto my-1">
+            <button id="button-search-users" *ngIf="!isSystemUser" [disabled]="!searchInput.validity.valid || isLoading " type="submit"
+                class="btn btn-primary mb-2" (click)="searchUsers()"> Search
+            </button>
+        </div>
+    </div>
+</form>
+<span class="ecomp-spinner" *ngIf="isLoading"></span>
+<div class="search-user-container" *ngIf="showUserTable && !isSystemUser">
+    <table mat-table [dataSource]="dataSourceMap">
+        <!-- Search Result Column-->
+        <ng-container matColumnDef="firstName">
+            <th id="rowheader-result" mat-header-cell *matHeaderCellDef> Showing {{searchUsersResults.length}} {{txtResults}} </th>
+            <td id="table-data-{{i}}" mat-cell *matCellDef="let element; let i = index;">
+                {{element.firstName}} {{element.lastName}} <br> {{element.jobTitle}}
+            </td>
+        </ng-container>
+        <tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>
+        <tr mat-row (click)="setSelectedUser(row)" id="table-row-{{i}}" [ngClass]="{ 'selected': row === selectedUser }"
+            *matRowDef="let row; columns: displayedColumns; let i = index;"></tr>
+    </table>
+</div>
+<div class="search-user-container" *ngIf="noUserFlag">
+    <p>{{message}} Or <a href="javascript:void(0);" (click)="addNewUser()"><b>Click Here</b></a> to add <b>New User!</b></p>
+</div>
\ No newline at end of file
diff --git a/portal-FE-os/src/app/layout/components/search-users/search-users.component.scss b/portal-FE-os/src/app/layout/components/search-users/search-users.component.scss
new file mode 100644 (file)
index 0000000..95a2a5e
--- /dev/null
@@ -0,0 +1,56 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+@import "../../../pages/pages.component";
+
+.mat-row {
+  cursor: pointer;
+  background-color: #f2f2f2;
+}
+.selected {
+  background-color: #ffffff !important;
+}
+
+.search-user-container {
+  overflow-y: auto;
+  height: 250px;
+}
+
+.ecomp-spinner{
+  opacity: 10;
+}
diff --git a/portal-FE-os/src/app/layout/components/search-users/search-users.component.spec.ts b/portal-FE-os/src/app/layout/components/search-users/search-users.component.spec.ts
new file mode 100644 (file)
index 0000000..66a966c
--- /dev/null
@@ -0,0 +1,63 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { SearchUsersComponent } from './search-users.component';
+
+describe('SearchUsersComponent', () => {
+  let component: SearchUsersComponent;
+  let fixture: ComponentFixture<SearchUsersComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ SearchUsersComponent ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(SearchUsersComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/portal-FE-os/src/app/layout/components/search-users/search-users.component.ts b/portal-FE-os/src/app/layout/components/search-users/search-users.component.ts
new file mode 100644 (file)
index 0000000..10e4e04
--- /dev/null
@@ -0,0 +1,115 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+import { Component, OnInit, Input, ViewChild, Output, EventEmitter } from '@angular/core';
+import { UsersService } from 'src/app/shared/services';
+import { MatTableDataSource, MatPaginator, MatSort } from '@angular/material';
+import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
+import { ConfirmationModalComponent } from 'src/app/modals/confirmation-modal/confirmation-modal.component';
+import { PortalAdmin } from 'src/app/shared/model/PortalAdmin';
+
+@Component({
+  selector: 'app-search-users',
+  templateUrl: './search-users.component.html',
+  styleUrls: ['./search-users.component.scss']
+})
+export class SearchUsersComponent implements OnInit {
+
+  constructor(private userService: UsersService, private ngModal: NgbModal) { }
+  @Input() searchTitle: string;
+  @Input() placeHolder: string;
+  @Input() isSystemUser: boolean;
+  @ViewChild(MatSort) sort: MatSort;
+  @ViewChild(MatPaginator) paginator: MatPaginator;
+  @Output() passBackSelectedUser: EventEmitter<any> = new EventEmitter();
+  @Output() userNotFoundFlag = new EventEmitter<boolean>();
+  searchString: string;
+  txtResults = 'result';
+  searchUsersResults: any;
+  selected: any;
+  isLoading: boolean;
+  showUserTable: boolean;
+  selectedUser: any;
+  displayedColumns: string[] = ['firstName'];
+  dataSourceMap = new MatTableDataSource(this.searchUsersResults);
+  submitted = false;
+  message = " No users found with your query. Please change your search and try again.";
+
+  ngOnInit() {
+    this.searchString = '';
+    this.showUserTable = false;
+    this.isSystemUser = false;
+  }
+
+  passSystemUserInfo(systemUser: string) {
+    if (this.isSystemUser)
+      this.passBackSelectedUser.emit(systemUser);
+  }
+
+  noUserFlag: boolean = false;
+  searchUsers() {
+    if (!this.isSystemUser) {
+      this.isLoading = true;
+      this.showUserTable = false;
+      this.passBackSelectedUser.emit(this.selectedUser = '');
+      this.userService.searchUsers(this.searchString).subscribe((_data: PortalAdmin) => {
+        this.searchUsersResults = _data;
+        if (this.searchUsersResults == null || this.searchUsersResults.length == 0) {
+          this.noUserFlag = true;
+          this.isLoading = false;
+        } else {
+          this.noUserFlag = false;
+          this.showUserTable = true;
+          this.isLoading = false;
+          this.dataSourceMap = new MatTableDataSource(this.searchUsersResults);
+          this.txtResults = (this.searchUsersResults && this.searchUsersResults.length > 1) ? 'results' : 'result';
+        }
+      });
+    }
+  }
+
+  setSelectedUser(user: PortalAdmin) {
+    this.selectedUser = user;
+    this.passBackSelectedUser.emit(this.selectedUser);
+  }
+
+  addNewUser() {
+    console.log("Emit the value to parent");
+    this.userNotFoundFlag.emit(true);
+  }
+
+}
diff --git a/portal-FE-os/src/app/layout/components/sidebar/sidebar.component.html b/portal-FE-os/src/app/layout/components/sidebar/sidebar.component.html
new file mode 100644 (file)
index 0000000..e2f4f3a
--- /dev/null
@@ -0,0 +1,72 @@
+<!--
+  ============LICENSE_START==========================================
+  ONAP Portal
+  ===================================================================
+  Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+  ===================================================================
+  Unless otherwise specified, all software contained herein is licensed
+  under the Apache License, Version 2.0 (the "License");
+  you may not use this software except in compliance with the License.
+  You may obtain a copy of the License at
+              http://www.apache.org/licenses/LICENSE-2.0
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  Unless otherwise specified, all documentation contained herein is licensed
+  under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+  you may not use this documentation except in compliance with the License.
+  You may obtain a copy of the License at
+              https://creativecommons.org/licenses/by/4.0/
+  Unless required by applicable law or agreed to in writing, documentation
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT 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============================================
+  
+  -->
+  
+<nav class="sidebar" [ngClass]="{sidebarPushRight: isActive, collapsed: collapsed}">
+    <div class="toggle-button" [ngClass]="{collapsed: collapsed}" (click)="toggleCollapsed()">
+        <i class="icon ion-md-arrow-{{collapsed?'dropright':'dropleft'}}" style="float:right"></i> <i
+            class="icon ion-md-arrow-{{collapsed?'dropright':'dropleft'}}" style="float:right"></i>&nbsp;
+    </div>
+    <div class="list-group" *ngFor="let menu of menuData ; index as item">
+        <a href="{{menu.href}}" *ngIf="!showOnlyParentMenu" [routerLinkActive]="['router-link-active']"
+            class="list-group-item">
+            <i class="icon ion-md-{{menu.imageSrc}}"></i>&nbsp;
+            <span>{{menu.name}}</span>
+        </a>
+        <a [routerLink]="menu.state" *ngIf="showOnlyParentMenu" [routerLinkActive]="['router-link-active']"
+            class="list-group-item">
+            <i class="icon ion-md-{{menu.imageSrc}}"></i>&nbsp;
+            <span>{{menu.name}}</span>
+        </a>
+        <div class="nested-menu" *ngIf="menu.menuItems.length > 0">
+            <a href="javascript:void(0)" class="list-group-item" (click)="addExpandClass(menu.name)">
+                <i class="fa fa-plus"></i>&nbsp;
+                <span>{{menu.name}}</span>
+            </a>
+            <li class="nested" [class.expand]="showMenu === menu.name">
+                <ul class="submenu">
+                    <li *ngFor="let menuItems of menu.menuItems">
+                        <a href="{{menuItems.href}}">
+                            <i class="fa fa-monument"></i>&nbsp;
+                            <span>{{ menuItems.name }}</span>
+                        </a>
+                    </li>
+                </ul>
+            </li>
+        </div>
+    </div>
+</nav>
\ No newline at end of file
diff --git a/portal-FE-os/src/app/layout/components/sidebar/sidebar.component.scss b/portal-FE-os/src/app/layout/components/sidebar/sidebar.component.scss
new file mode 100644 (file)
index 0000000..fd114bd
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright ï¿½ 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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============================================
+ *
+ *
+ */
+$topnav-background-color: #fff;
+.sidebar {
+    border-radius: 0;
+    position: relative;
+    z-index: 1000;
+    //top: 56px;
+    left: 270px;
+    width: 270px;
+    margin-left: -270px;
+    margin-bottom: 48px;
+    border: none;
+    border-radius: 0;
+    overflow-y: auto;
+    background-color: $topnav-background-color;
+    bottom: 0;
+    overflow-x: hidden;
+    padding-bottom: 40px;
+    white-space: nowrap;
+    -webkit-transition: all 0.2s ease-in-out;
+    -moz-transition: all 0.2s ease-in-out;
+    -ms-transition: all 0.2s ease-in-out;
+    -o-transition: all 0.2s ease-in-out;
+    transition: all 0.2s ease-in-out;
+    .list-group {
+        a.list-group-item {
+            background: $topnav-background-color;
+            border: 0;
+            border-top: 1px solid #999;
+            border-radius: 0;
+            color: #0568ae;
+            text-decoration: none;
+            .icon {
+                margin-right: 10px;
+                color: #000;
+            }
+        }
+        a:hover {
+            background: darken($topnav-background-color, 2%);
+            color: #000;
+        }
+        a.router-link-active {
+            background: darken($topnav-background-color, 5%);
+            color: #000;
+        }
+        .header-fields {
+            padding-top: 10px;
+
+            > .list-group-item:first-child {
+                border-top: 1px solid rgba(255, 255, 255, 0.2);
+            }
+        }
+    }
+    .sidebar-dropdown {
+        *:focus {
+            border-radius: none;
+            border: none;
+        }
+        .panel-title {
+            font-size: 1rem;
+            height: 50px;
+            margin-bottom: 0;
+            a {
+                color: #999;
+                text-decoration: none;
+                font-weight: 400;
+                background: $topnav-background-color;
+                span {
+                    position: relative;
+                    display: block;
+                    padding: 0.75rem 1.5rem;
+                    padding-top: 1rem;
+                }
+            }
+            a:hover,
+            a:focus {
+                color: #fff;
+                outline: none;
+                outline-offset: -2px;
+            }
+        }
+        .panel-title:hover {
+            background: darken($topnav-background-color, 5%);
+        }
+        .panel-collapse {
+            border-radious: 0;
+            border: none;
+            .panel-body {
+                .list-group-item {
+                    border-radius: 0;
+                    background-color: $topnav-background-color;
+                    border: 0 solid transparent;
+                    a {
+                        color: #999;
+                    }
+                    a:hover {
+                        color: #fff;
+                    }
+                }
+                .list-group-item:hover {
+                    background: darken($topnav-background-color, 5%);
+                }
+            }
+        }
+    }
+}
+
+.nested-menu {
+    .list-group-item {
+        cursor: pointer;
+    }
+    .nested {
+        list-style-type: none;
+    }
+    ul.submenu {
+        display: none;
+        height: 0;
+    }
+    & .expand {
+        ul.submenu {
+            display: block;
+            list-style-type: none;
+            height: auto;
+            li {
+                a {
+                    color: #0568ae;
+                    padding: 10px;
+                    display: block;
+                }
+            }
+        }
+    }
+}
+@media screen and (max-width: 992px) {
+    .sidebar {
+        top: 54px;
+        left: 0px;
+    }
+}
+@media print {
+    .sidebar {
+        display: none !important;
+    }
+}
+@media (min-width: 992px) {
+    .header-fields {
+        display: none;
+    }
+}
+
+::-webkit-scrollbar {
+    width: 8px;
+}
+
+::-webkit-scrollbar-track {
+    -webkit-box-shadow: inset 0 0 0px rgba(255, 255, 255, 1);
+    border-radius: 3px;
+}
+
+::-webkit-scrollbar-thumb {
+    border-radius: 3px;
+    -webkit-box-shadow: inset 0 0 3px rgba(255, 255, 255, 1);
+}
+
+.toggle-button {
+    width: 270px;
+    cursor: pointer;
+    padding: 12px;
+    bottom: 0;
+    color: #0568ae;
+    background: #fff;
+    i {
+        font-size: 23px;
+    }
+    &:hover {
+        background: darken($topnav-background-color, 2%);
+        color: #000;
+    }
+    border-top: 1px solid #999;
+    -webkit-transition: all 0.2s ease-in-out;
+    -moz-transition: all 0.2s ease-in-out;
+    -ms-transition: all 0.2s ease-in-out;
+    -o-transition: all 0.2s ease-in-out;
+    transition: all 0.2s ease-in-out;
+}
+
+.collapsed {
+    width: 60px;
+    span {
+        display: none;
+    }
+}
diff --git a/portal-FE-os/src/app/layout/components/sidebar/sidebar.component.spec.ts b/portal-FE-os/src/app/layout/components/sidebar/sidebar.component.spec.ts
new file mode 100644 (file)
index 0000000..92caeb4
--- /dev/null
@@ -0,0 +1,62 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { SidebarComponent } from './sidebar.component';
+
+describe('SidebarComponent', () => {
+  let component: SidebarComponent;
+  let fixture: ComponentFixture<SidebarComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ SidebarComponent ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(SidebarComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/portal-FE-os/src/app/layout/components/sidebar/sidebar.component.ts b/portal-FE-os/src/app/layout/components/sidebar/sidebar.component.ts
new file mode 100644 (file)
index 0000000..d56f443
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright Â© 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+import { Component, Output, EventEmitter, OnInit, Input } from '@angular/core';
+import { Router, NavigationEnd } from '@angular/router';
+import { SidebarService } from '../../../shared/services/index'
+
+@Component({
+    selector: 'app-sidebar',
+    templateUrl: './sidebar.component.html',
+    styleUrls: ['./sidebar.component.scss']
+})
+export class SidebarComponent implements OnInit {
+    @Input() labelName: string;
+    isActive: boolean;
+    collapsed: boolean;
+    showMenu: string;
+    pushRightClass: string;
+    result: any;
+    showOnlyParentMenu: boolean;
+    leftParentData: any;
+    leftChildData: any;
+    menuData: Array<object> = [];
+    page: any;
+
+    @Output() collapsedEvent = new EventEmitter<boolean>();
+
+    constructor(public router: Router, public sidebarService: SidebarService) {
+        this.router.events.subscribe(val => {
+            if (
+                val instanceof NavigationEnd &&
+                window.innerWidth <= 992 &&
+                this.isToggled()
+            ) {
+                this.toggleSidebar();
+            }
+        });
+    }
+
+    ngOnInit() {
+        this.isActive = false;
+        this.collapsed = false;
+        this.showMenu = '';
+        this.pushRightClass = 'push-right';
+        this.sidebarService.getLeftMenu()
+            .subscribe(data => {
+                this.result = data;
+                if (this.result.data && this.result.data2) {
+                    this.leftParentData = JSON.parse(this.result.data);
+                    this.leftChildData = JSON.parse(this.result.data2);
+                } else {
+                    this.labelName = this.result.label;
+                    this.leftParentData = this.result.navItems;
+                    this.showOnlyParentMenu = true;
+                }
+
+                for (var i = 0; i < this.leftParentData.length; i++) {
+                    var parentItem = {
+                        name: null,
+                        imageSrc: null,
+                        href: null,
+                        menuItems: [],
+                        state: null
+                    }
+                    if (this.showOnlyParentMenu) {
+                        parentItem.name = this.leftParentData[i].name;
+                        parentItem.imageSrc = this.leftParentData[i].imageSrc;
+                        parentItem.state = '/'+this.leftParentData[i].state;
+                    } else {
+                        parentItem.name = this.leftParentData[i].label;
+                        parentItem.imageSrc = this.leftParentData[i].imageSrc;
+                    }
+                    // Add link to items with no subitems
+                    if (!this.showOnlyParentMenu) {
+                        if (this.leftChildData[i].length == 0)
+                            parentItem.href = this.leftParentData[i].action;
+
+                        for (var j = 0; j < this.leftChildData[i].length; j++) {
+
+                            var childItem = {
+                                name: null,
+                                href: null
+                            };
+                            if (this.leftChildData[i][j].label != null && this.leftChildData[i][j].label.length > 0) {
+
+                                childItem.name = this.leftChildData[i][j].label;
+                                childItem.href = this.leftChildData[i][j].action;
+                                parentItem.menuItems.push(childItem);
+                            }
+                        }
+                    }
+                    this.menuData.push(parentItem);
+                }
+
+            });
+
+    }
+    eventCalled() {
+        this.isActive = !this.isActive;
+    }
+
+    addExpandClass(element: any) {
+        if (element === this.showMenu) {
+            this.showMenu = '0';
+        } else {
+            this.showMenu = element;
+        }
+    }
+
+    toggleCollapsed() {
+        this.collapsed = !this.collapsed;
+        this.collapsedEvent.emit(this.collapsed);
+    }
+
+    isToggled(): boolean {
+        const dom: Element = document.querySelector('body');
+        return dom.classList.contains(this.pushRightClass);
+    }
+
+    toggleSidebar() {
+        const dom: any = document.querySelector('body');
+        dom.classList.toggle(this.pushRightClass);
+    }
+}
diff --git a/portal-FE-os/src/app/layout/components/tabbar/tab.ts b/portal-FE-os/src/app/layout/components/tabbar/tab.ts
new file mode 100644 (file)
index 0000000..0b941c6
--- /dev/null
@@ -0,0 +1,12 @@
+import { SafeUrl } from '@angular/platform-browser';
+
+export class Tab {
+  label: string;
+  url: SafeUrl;
+  active: boolean;
+
+  constructor(label: string) {
+      this.label = label;
+  }
+
+}
diff --git a/portal-FE-os/src/app/layout/components/tabbar/tabbar.component.html b/portal-FE-os/src/app/layout/components/tabbar/tabbar.component.html
new file mode 100644 (file)
index 0000000..4a704da
--- /dev/null
@@ -0,0 +1,77 @@
+<!--
+  ============LICENSE_START==========================================
+  ONAP Portal
+  ===================================================================
+  Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+  ===================================================================
+
+  Unless otherwise specified, all software contained herein is licensed
+  under the Apache License, Version 2.0 (the "License");
+  you may not use this software except in compliance with the License.
+  You may obtain a copy of the License at
+
+              http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+  Unless otherwise specified, all documentation contained herein is licensed
+  under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+  you may not use this documentation except in compliance with the License.
+  You may obtain a copy of the License at
+
+              https://creativecommons.org/licenses/by/4.0/
+
+  Unless required by applicable law or agreed to in writing, documentation
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+  ============LICENSE_END============================================
+
+  -->
+
+  <div style="display: flex; flex-direction:column">
+    <div>
+      <mat-tab-group [selectedIndex]="selected.value" (selectedIndexChange)="selected.setValue($event)"
+        (selectedTabChange)="tabChanged($event)">
+        <mat-tab [label]="mainTab">
+          <mat-grid-list cols="5">
+            <mat-grid-tile [colspan]="1" [rowspan]="3">
+              <app-sidebar (collapsedEvent)="receiveCollapsed($event)"></app-sidebar>
+              <app-userbar></app-userbar>
+            </mat-grid-tile>
+            <mat-grid-tile [colspan]="4" style="height: calc(100vh - 24px);overflow-y: scroll">
+              <div class="container">
+                <router-outlet></router-outlet>
+              </div>
+            </mat-grid-tile>
+          </mat-grid-list>
+  
+        </mat-tab>
+  
+        <mat-tab *ngFor="let tab of tabs; let index = index">
+          <ng-template mat-tab-label>
+            {{tab.label | elipsis: 13}} &nbsp;
+            <i class="icon ion-md-close-circle" (click)="removeTab(index)"></i>
+          </ng-template>
+  
+  
+        </mat-tab>
+  
+      </mat-tab-group>
+      <mat-grid-list cols="5">
+        <mat-grid-tile [colspan]="5" [rowspan]="tab.active? 3 : 0" *ngFor="let tab of tabs; let index = index"
+          [style.display]='tab.active? "inline" : "none"' [style.position]='tab.active? "static" : "absolute"'>
+  
+          <iframe id="tabframe-{{tab.label.split(' ').join('-')}}" scrolling='yes' frameBorder='0' width='100%'
+            scrolling='yes' frameBorder='0' width='100%' height='90%' [src]='tab.url'></iframe>
+  
+        </mat-grid-tile>
+  
+      </mat-grid-list>
+    </div>
\ No newline at end of file
diff --git a/portal-FE-os/src/app/layout/components/tabbar/tabbar.component.scss b/portal-FE-os/src/app/layout/components/tabbar/tabbar.component.scss
new file mode 100644 (file)
index 0000000..807e2d5
--- /dev/null
@@ -0,0 +1,80 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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============================================
+ *
+ *
+ */
+
+ .input-label,
+ .add-tab-button,
+ .delete-tab-button {
+   margin: 8px;
+ }
+ .search-bar {
+   position: absolute;
+   right: 10%;
+ }
+ #mat-tab-label-0-1 {
+   position: fixed;
+   right: 1em;
+ }
+ .mat-tab-group{
+   margin-top: 55px;
+ }
+
+ ::ng-deep .mat-tab-label {
+   font-size: 13px !important;
+   line-height: 30px !important;
+   margin: 5px 0px 0 !important;
+   border-top-left-radius: 88px 205px !important;
+   border-top-right-radius: 88px 205px !important;
+   padding: 0 30px 0 25px !important;
+   height: 35px !important;
+   background: #d2d2d2 !important;
+   position: relative !important;
+   box-shadow: 0 4px 6px rgba(0, 0, 0, 0.5) !important;
+   width: 180px !important;
+   max-width: 200px !important;
+   min-width: 20px !important;
+   border: 1px solid #aaa !important;
+   text-transform: capitalize !important;
+   text-align: left !important;
+ }
+ ::ng-deep .mat-tab-label.mat-ripple.ng-star-inserted.mat-tab-label-active {
+   opacity: 1;
+ }
\ No newline at end of file
diff --git a/portal-FE-os/src/app/layout/components/tabbar/tabbar.component.spec.ts b/portal-FE-os/src/app/layout/components/tabbar/tabbar.component.spec.ts
new file mode 100644 (file)
index 0000000..94866e4
--- /dev/null
@@ -0,0 +1,63 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ *
+ */
+
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { TabbarComponent } from './tabbar.component';
+
+describe('TabbarComponent', () => {
+  let component: TabbarComponent;
+  let fixture: ComponentFixture<TabbarComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ TabbarComponent ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(TabbarComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/portal-FE-os/src/app/layout/components/tabbar/tabbar.component.ts b/portal-FE-os/src/app/layout/components/tabbar/tabbar.component.ts
new file mode 100644 (file)
index 0000000..7a10e39
--- /dev/null
@@ -0,0 +1,95 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ *
+ */
+import { Component, OnInit } from '@angular/core';
+import { FormControl } from '@angular/forms';
+import { DomSanitizer } from '@angular/platform-browser';
+import { Tab } from './tab';
+import { AddTabFunctionService } from 'src/app/shared/services/tab/add-tab-function.service';
+
+@Component({
+  selector: 'app-tabbar',
+  templateUrl: './tabbar.component.html',
+  styleUrls: ['./tabbar.component.scss']
+})
+export class TabbarComponent implements OnInit {
+
+  tabs = [];
+  mainTab = 'Home';
+  selected = new FormControl(0);
+  collapedSideBar: boolean;
+
+  constructor(private sanitizer: DomSanitizer, private addTabFuntionService: AddTabFunctionService) {
+
+  }
+
+  ngOnInit(): void {
+
+    this.addTabFuntionService.listen().subscribe((m: any) => {
+      console.log(m);
+      this.addTab(true, m.title, m.url);
+    })
+  }
+
+  addTab(selectAfterAdding: boolean, label: string, url: string) {
+    const tab = new Tab(label);
+    tab.url = this.sanitizer.bypassSecurityTrustResourceUrl(url);
+    tab.active = true;
+    this.tabs.push(tab);
+
+    if (selectAfterAdding) {
+      this.selected.setValue(this.tabs.length);
+    }
+  }
+
+  removeTab(index: number) {
+    this.tabs.splice(index, 1);
+  }
+
+  receiveCollapsed($event) {
+    this.collapedSideBar = $event;
+  }
+
+  tabChanged($event) {
+
+    for (const ttab of this.tabs) {
+      ttab.active = false;
+    }
+    if(this.tabs.length != 0 && $event.index != 0)
+      this.tabs[$event.index - 1].active = true;
+  }
+}
diff --git a/portal-FE-os/src/app/layout/components/userbar/userbar.component.html b/portal-FE-os/src/app/layout/components/userbar/userbar.component.html
new file mode 100644 (file)
index 0000000..e9a8b82
--- /dev/null
@@ -0,0 +1,13 @@
+<button type="button" class="btn btn-primary" href="javascript:void(0)"
+[ngStyle]="{'right': isOpen ? '65px' : '-18px' }" (click)="toggleSidebar()">
+  <span id="user-chevron-down" class="icon-controls-down" [hidden]="!isOpen">Close</span>
+  <span id="user-chevron-up" class="icon-controls-upPRIMARY" [hidden]="isOpen"><span class="right-menu-button"><i
+        class="icon ion-md-arrow-dropup"></i> Users</span></span>
+</button>
+<nav [ngStyle]="{'right': isOpen ? '18px' : '-75px' }" class="usb-item usb-item-vertical usb-item-right" id="usb-item-s2">
+  <h3>Online Users</h3>
+  <div *ngFor="let user of userList" style="font-size: 10px;">
+    <a [href]="user.linkQ"><img class="activeUserIcon" [src]="user.linkPic" alt="User Link"></a>
+    <div class="userId-txt">{{user.userId}}</div>
+  </div>
+</nav>
\ No newline at end of file
diff --git a/portal-FE-os/src/app/layout/components/userbar/userbar.component.scss b/portal-FE-os/src/app/layout/components/userbar/userbar.component.scss
new file mode 100644 (file)
index 0000000..ee9f827
--- /dev/null
@@ -0,0 +1,114 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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============================================
+ *
+ *
+ */
+.usb-item {
+  background: #fff;
+  position: fixed;
+}
+
+.usb-item h3 {
+  color: #ef6f00;
+  font-size: 14px;
+  padding: 20px;
+  margin: 0;
+  text-align: center;
+  font-weight: 300;
+  background: #f8f9fa;
+}
+
+.usb-item a {
+  display: block;
+  color: #fff;
+  font-size: 1.1em;
+  font-weight: 300;
+  transition: all 0.2s ease-in-out;
+  -ms-transition: all 0.2s ease-in-out; /* IE 9 */
+  -webkit-transition: all 0.2s ease-in-out; /* Safari 3-8 */
+}
+
+.usb-item a:active {
+  background: #afdefa;
+  color: #47a3da;
+}
+
+.usb-item-right {
+  transition: all 0.5s ease-in-out;
+  -ms-transition: all 0.5s ease-in-out; /* IE 9 */
+  -webkit-transition: all 0.5s ease-in-out; /* Safari 3-8 */
+}
+
+.usb-item a:hover {
+  -ms-transform: scale(1.5); /* IE 9 */
+  -webkit-transform: scale(1.5); /* Safari 3-8 */
+  transform: scale(1.5);
+}
+
+.usb-item-vertical {
+  margin-top: 105px;
+  text-align: center;
+  width: 75px;
+  height: 79%;
+  top: 0;
+  z-index: 1000;
+  box-shadow: 0 4px 5px rgba(0, 0, 0, 0.2);
+}
+
+.usb-item-vertical a {
+  padding: 0.5em;
+}
+
+button {
+  transition: all 0.5s ease-in-out;
+  -ms-transition: all 0.5s ease-in-out; /* IE 9 */
+  -webkit-transition: all 0.5s ease-in-out; /* Safari 3-8 */
+  z-index: 9999;
+  top: 450px;
+  -ms-transform: rotate(-90deg); /* IE 9 */
+  -webkit-transform: rotate(-90deg); /* Safari 3-8 */
+  transform: rotate(-90deg);
+  position: fixed;
+}
+
+.activeUserIcon {
+  display: block;
+  margin-left: auto;
+  margin-right: auto;
+  height: 55px;
+  width: 55px;
+  border-radius: 50%;
+}
diff --git a/portal-FE-os/src/app/layout/components/userbar/userbar.component.spec.ts b/portal-FE-os/src/app/layout/components/userbar/userbar.component.spec.ts
new file mode 100644 (file)
index 0000000..4115433
--- /dev/null
@@ -0,0 +1,63 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ *
+ */
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { UserbarComponent } from './userbar.component';
+
+describe('UserbarComponent', () => {
+  let component: UserbarComponent;
+  let fixture: ComponentFixture<UserbarComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ UserbarComponent ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(UserbarComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/portal-FE-os/src/app/layout/components/userbar/userbar.component.ts b/portal-FE-os/src/app/layout/components/userbar/userbar.component.ts
new file mode 100644 (file)
index 0000000..343305f
--- /dev/null
@@ -0,0 +1,134 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ *
+ */
+import { Component, OnInit } from '@angular/core';
+import { UserbarService, UserProfileService } from 'src/app/shared/services';
+import { DomSanitizer } from '@angular/platform-browser';
+
+@Component({
+  selector: 'app-userbar',
+  templateUrl: './userbar.component.html',
+  styleUrls: ['./userbar.component.scss']
+})
+export class UserbarComponent implements OnInit {
+
+  userList;
+  isOpen: boolean;
+  intervalPromise = null;
+  updateRate: number;
+  myservice: UserbarService;
+  constructor(private sanitizer: DomSanitizer, private userbarService: UserbarService, private userProfileService: UserProfileService) { }
+
+  ngOnInit() {
+    this.userList = [];
+    this.myservice = this.userbarService;
+    this.isOpen = true;
+    // this.userbarService.getOnlineUserUpdateRate().subscribe((_res: any) => {
+    //   if (_res != null) {
+    //     var rate = parseInt(_res.onlineUserUpdateRate);
+    //     var duration = parseInt(_res.onlineUserUpdateDuration);
+    //     this.userbarService.setMaxRefreshCount((duration / rate) + 1);
+    //     this.userbarService.setRefreshCount(this.userbarService.maxCount);
+    //     if (rate != NaN && duration != NaN) {
+    //       // $log.debug('UserbarCtlr: scheduling function at interval ' + millis);
+    //       this.updateRate = rate;
+    //       this.start(this.updateRate);
+    //     }
+    //   }
+    // })
+    this.updateActiveUsers();
+  }
+
+  updateActiveUsers() {
+    // this.userbarService.decrementRefreshCount();
+    this.userProfileService.getActiveUser().subscribe((_res: any) => {
+      if (_res == null) {
+        // $log.error('UserbarCtrl::updateActiveUsers: failed to get active user');
+        this.stop();
+      } else {
+        var maxItems = 25;
+        if (_res.length < maxItems)
+          maxItems = _res.length;
+        for (var i = 0; i < maxItems; i++) {
+          var data = {
+            userId: _res[i],
+            linkQ: this.sanitizer.bypassSecurityTrustResourceUrl('qto://talk/' + _res[i]),
+            linkPic: 'https://tspace.web.att.com/profiles/photo.do?uid=' + _res[i]
+          }
+          this.userList.push(data);
+        }
+      }
+
+    }, (err) => {
+      this.userList = [];
+      this.stop();
+    })
+
+    // .add(() => {
+    //   var footerOff = $('#online-userbar').offset().top;
+    //   var headOff = $('#footer').offset().top;
+    //   var defaultOffSet = 45;
+    //   $(".online-user-container").css({
+    //     "height": headOff - footerOff - defaultOffSet
+    //   });
+    // })
+
+  }
+
+  toggleSidebar() {
+    this.isOpen = !this.isOpen;
+  }
+
+  start(rate) {
+    // stops any running interval to avoid two intervals running at the same time
+    this.stop();
+    // store the interval promise
+    this.intervalPromise = setInterval(this.updateActiveUsers, rate);
+  };
+
+
+  stop() {
+    if (this.intervalPromise != null) {
+      clearInterval(this.intervalPromise);
+      this.intervalPromise = null;
+    }
+  };
+
+
+
+}
diff --git a/portal-FE-os/src/app/layout/layout-routing.module.ts b/portal-FE-os/src/app/layout/layout-routing.module.ts
new file mode 100644 (file)
index 0000000..5fa77e3
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * ============LICENSE_START==========================================
+ * ONAP Portal SDK
+ * ===================================================================
+ * Copyright ï¿½ 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+import { NgModule } from '@angular/core';
+import { Routes, RouterModule } from '@angular/router';
+import { LayoutComponent } from './layout.component';
+
+const routes: Routes = [
+    {
+        path: '',
+        component: LayoutComponent,
+        children: [
+            //redirecting to pages module
+            { path: '', redirectTo: 'app', },
+            { path: 'app', loadChildren: () => import('../pages/pages.module').then(m => m.PagesModule) },        ]
+    }
+];
+
+@NgModule({
+    imports: [RouterModule.forChild(routes)],
+    exports: [RouterModule]
+})
+export class LayoutRoutingModule {}
diff --git a/portal-FE-os/src/app/layout/layout.component.html b/portal-FE-os/src/app/layout/layout.component.html
new file mode 100644 (file)
index 0000000..757c986
--- /dev/null
@@ -0,0 +1,45 @@
+<!--
+  ============LICENSE_START==========================================
+  ONAP Portal
+  ===================================================================
+  Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+  ===================================================================
+  Unless otherwise specified, all software contained herein is licensed
+  under the Apache License, Version 2.0 (the "License");
+  you may not use this software except in compliance with the License.
+  You may obtain a copy of the License at
+              http://www.apache.org/licenses/LICENSE-2.0
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  Unless otherwise specified, all documentation contained herein is licensed
+  under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+  you may not use this documentation except in compliance with the License.
+  You may obtain a copy of the License at
+              https://creativecommons.org/licenses/by/4.0/
+  Unless required by applicable law or agreed to in writing, documentation
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  ============LICENSE_END============================================
+  
+  -->
+
+  <app-header></app-header>
+  <app-tabbar></app-tabbar>
+  <app-footer></app-footer>
+  
+  
+  
+  
\ No newline at end of file
diff --git a/portal-FE-os/src/app/layout/layout.component.scss b/portal-FE-os/src/app/layout/layout.component.scss
new file mode 100644 (file)
index 0000000..a8adf26
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * ============LICENSE_START==========================================
+ * ONAP Portal SDK
+ * ===================================================================
+ * Copyright ï¿½ 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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============================================
+ *
+ * 
+ */
+* {
+    -webkit-transition: margin-left 0.2s ease-in-out;
+    -moz-transition: margin-left 0.2s ease-in-out;
+    -ms-transition: margin-left 0.2s ease-in-out;
+    -o-transition: margin-left 0.2s ease-in-out;
+    transition: margin-left 0.2s ease-in-out;
+}
+.main-container {
+    margin-top: 56px;
+    margin-left: 270px;
+    padding: 15px;
+    -ms-overflow-x: hidden;
+    overflow-x: hidden;
+    overflow-y: scroll;
+    position: relative;
+    overflow: hidden;
+}
+.collapsed {
+    margin-left: 60px;
+}
+@media screen and (max-width: 992px) {
+    .main-container {
+        margin-left: 0px !important;
+    }
+}
+@media print {
+    .main-container {
+        margin-top: 0px !important;
+        margin-left: 0px !important;
+    }
+}
diff --git a/portal-FE-os/src/app/layout/layout.component.spec.ts b/portal-FE-os/src/app/layout/layout.component.spec.ts
new file mode 100644 (file)
index 0000000..5184fe4
--- /dev/null
@@ -0,0 +1,62 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { LayoutComponent } from './layout.component';
+
+describe('LayoutComponent', () => {
+  let component: LayoutComponent;
+  let fixture: ComponentFixture<LayoutComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ LayoutComponent ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(LayoutComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/portal-FE-os/src/app/layout/layout.component.ts b/portal-FE-os/src/app/layout/layout.component.ts
new file mode 100644 (file)
index 0000000..b512988
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * ============LICENSE_START==========================================
+ * ONAP Portal SDK
+ * ===================================================================
+ * Copyright Â© 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ * 
+ */
+import { Component, OnInit } from '@angular/core';
+
+@Component({
+    selector: 'app-layout',
+    templateUrl: './layout.component.html',
+    styleUrls: ['./layout.component.scss']
+})
+export class LayoutComponent implements OnInit {
+
+    collapedSideBar: boolean;
+
+    constructor() {}
+
+    ngOnInit() {}
+
+    receiveCollapsed($event) {
+        this.collapedSideBar = $event;
+    }
+}
diff --git a/portal-FE-os/src/app/layout/layout.module.ts b/portal-FE-os/src/app/layout/layout.module.ts
new file mode 100644 (file)
index 0000000..63a99d8
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * ============LICENSE_START==========================================
+ * ONAP Portal SDK
+ * ===================================================================
+ * Copyright ï¿½ 2019 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ *
+ */
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap';
+import { NgMaterialModule } from '../ng-material-module';
+import { LayoutRoutingModule } from './layout-routing.module';
+import { LayoutComponent } from './layout.component';
+import { SidebarComponent } from './components/sidebar/sidebar.component';
+import { HeaderComponent } from './components/header/header.component';
+import { GlobalSearchComponent } from './components/global-search/global-search.component';
+import { ClickOutsideModule } from 'ng-click-outside';
+import { TabbarComponent } from './components/tabbar/tabbar.component';
+import { HeaderMenuComponent } from './components/header-menu/header-menu.component';
+import { UserbarComponent } from './components/userbar/userbar.component';
+import { FooterComponent } from './components/footer/footer.component';
+import { ApplicationPipesModule } from '../shared/pipes/application-pipes.module';
+
+@NgModule({
+    imports: [
+        CommonModule,
+        NgMaterialModule,
+        LayoutRoutingModule,
+        ApplicationPipesModule,
+        NgbDropdownModule,
+        ClickOutsideModule
+    ],
+    declarations: [LayoutComponent, SidebarComponent, HeaderComponent,GlobalSearchComponent, TabbarComponent, HeaderMenuComponent, UserbarComponent, FooterComponent]
+})
+export class LayoutModule {}
diff --git a/portal-FE-os/src/assets/images/default_app_image.gif b/portal-FE-os/src/assets/images/default_app_image.gif
new file mode 100644 (file)
index 0000000..b3aa80d
Binary files /dev/null and b/portal-FE-os/src/assets/images/default_app_image.gif differ
diff --git a/portal-FE-os/src/assets/images/global.logo b/portal-FE-os/src/assets/images/global.logo
new file mode 100644 (file)
index 0000000..8d60100
Binary files /dev/null and b/portal-FE-os/src/assets/images/global.logo differ
diff --git a/portal-FE-os/src/assets/images/spinner.gif b/portal-FE-os/src/assets/images/spinner.gif
new file mode 100644 (file)
index 0000000..c97ec6e
Binary files /dev/null and b/portal-FE-os/src/assets/images/spinner.gif differ
diff --git a/portal-FE-os/src/browserslist b/portal-FE-os/src/browserslist
new file mode 100644 (file)
index 0000000..37371cb
--- /dev/null
@@ -0,0 +1,11 @@
+# This file is currently used by autoprefixer to adjust CSS to support the below specified browsers
+# For additional information regarding the format and rule options, please see:
+# https://github.com/browserslist/browserslist#queries
+#
+# For IE 9-11 support, please remove 'not' from the last line of the file and adjust as needed
+
+> 0.5%
+last 2 versions
+Firefox ESR
+not dead
+not IE 9-11
\ No newline at end of file
diff --git a/portal-FE-os/src/environments/environment.prod.ts b/portal-FE-os/src/environments/environment.prod.ts
new file mode 100644 (file)
index 0000000..2c02646
--- /dev/null
@@ -0,0 +1,120 @@
+export const environment = {
+  production: true,
+  "api": {
+    "singleAppInfo": "portalApi/singleAppInfo",
+    "singleAppInfoById": "portalApi/singleAppInfoById",
+    "syncRolesFromExternalAuthSystem": "portalApi/syncRoles",
+    "syncFunctionsFromExternalAuthSystem": "portalApi/syncFunctions",
+    "userApps": "portalApi/userApps/",
+    "persUserApps": "portalApi/persUserApps",
+    "appCatalog": "portalApi/appCatalog",
+    "accountAdmins": "portalApi/accountAdmins",
+    "availableApps": "portalApi/availableApps",
+    "allAvailableApps": "portalApi/allAvailableApps",
+    "externalRequestAccessSystem": "portalApi/externalRequestAccessSystem",
+    "userProfile": "portalApi/userProfile",
+    "queryUsers": "portalApi/queryUsers",
+    "adminAppsRoles": "portalApi/adminAppsRoles",
+    "adminApps": "portalApi/adminApps",
+    "appsForSuperAdminAndAccountAdmin": "portalApi/appsForSuperAdminAndAccountAdmin",
+    "accountUsers": "portalApi/app/:appId/users",
+    "saveNewUser": "portalApi/saveNewUser",
+    "userAppRoles": "portalApi/userAppRoles",
+    "onboardingApps": "portalApi/onboardingApps",
+    "widgets": "portalApi/widgets",
+    "widgetsValidation": "portalApi/widgets/validation",
+    "functionalMenuForAuthUser": "portalApi/functionalMenuForAuthUser",
+    "functionalMenuForEditing": "portalApi/functionalMenuForEditing",
+    "functionalMenuForNotificationTree": "portalApi/functionalMenuForNotificationTree",
+    "functionalMenu": "portalApi/functionalMenu",
+    "functionalMenuItemDetails": "portalApi/functionalMenuItemDetails/:menuId",
+    "appRoles": "portalApi/appRoles/:appId",
+    "appThumbnail": "portalApi/appThumbnail/:appId",
+    "functionalMenuItem": "portalApi/functionalMenuItem",
+    "regenerateFunctionalMenuAncestors": "portalApi/regenerateFunctionalMenuAncestors",
+    "listOfApp": "portalApi/getAppList",
+    "setFavoriteItem": "portalApi/setFavoriteItem",
+    "getFavoriteItems": "portalApi/getFavoriteItems",
+    "removeFavoriteItem": "portalApi/removeFavoriteItem/:menuId",
+    "ping": "portalApi/ping",
+    "functionalMenuStaticInfo": "portalApi/functionalMenuStaticInfo",
+    "portalAdmins": "portalApi/portalAdmins",
+    "portalAdmin": "portalApi/portalAdmin",
+    "getManifest": "portalApi/manifest",
+    "getActiveUser": "portalApi/dashboard/activeUsers",
+    "getSearchAllByStringResults": "portalApi/dashboard/search",
+    "commonWidget": "portalApi/dashboard/widgetData",
+    "deleteCommonWidget": "portalApi/dashboard/deleteData",
+    "getContactUS": "portalApi/contactus/list",
+    "getAppsAndContacts": "portalApi/contactus/allapps",
+    "saveContactUS": "portalApi/contactus/save",
+    "deleteContactUS": "portalApi/contactus/delete",
+    "getContactUSPortalDetails": "portalApi/contactus/feedback",
+    "getAppCategoryFunctions": "portalApi/contactus/functions",
+    "onlineUserUpdateRate": "portalApi/dashboard/onlineUserUpdateRate",
+    "storeAuditLog": "portalApi/auditLog/store",
+    "leftmenuItems": "portalApi/leftmenuItems",
+    "getFunctionalMenuRole": "portalApi/getFunctionalMenuRole",
+    "getNotifications": "portalApi/getNotifications",
+    "getAdminNotifications": "portalApi/getAdminNotifications",
+    "getAllAppRoleIds": "portalApi/getNotificationAppRoles",
+    "getNotificationHistory": "portalApi/getNotificationHistory",
+    "notificationUpdateRate": "portalApi/notificationUpdateRate",
+    "notificationRead": "portalApi/notificationRead",
+    "saveNotification": "portalApi/saveNotification",
+    "getMessageRecipients": "portalApi/getMessageRecipients",
+    "getNotificationRoles": "portalApi/notificationRole",
+    "getRole": "portalApi/get_role",
+    "getRoles": "portalApi/get_roles/:appId",
+    "toggleRole": "portalApi/role_list/toggleRole",
+    "removeRole": "portalApi/role_list/removeRole",
+    "saveRole": "portalApi/role/saveRole/:appId",
+    "toggleRoleRoleFunction": "portalApi/role/removeRoleFunction.htm",
+    "addRoleRoleFunction": "portalApi/role/addRoleFunction.htm",
+    "toggleRoleChildRole": "portalApi/role/removeChildRole.htm",
+    "addRoleChildRole": "portalApi/role/addChildRole.htm",
+    "getRoleFunctions": "portalApi/get_role_functions/:appId",
+    "saveRoleFunction": "portalApi/role_function_list/saveRoleFunction/:appId",
+    "removeRoleFunction": "portalApi/role_function_list/removeRoleFunction/:appId",
+    "userAppsOrderBySortPref": "portalApi/userAppsOrderBySortPref",
+    "userAppsOrderByName": "portalApi/userAppsOrderByName",
+    "saveUserAppsSortingPreference": "portalApi/saveUserAppsSortingPreference",
+    "userAppsSortTypePreference": "portalApi/userAppsSortTypePreference",
+    "userAppsOrderByLastUsed": "portalApi/userAppsOrderByLastUsed",
+    "userAppsOrderByMostUsed": "portalApi/userAppsOrderByMostUsed",
+    "userAppsOrderByManual": "portalApi/userAppsOrderByManual",
+    "saveUserAppsSortingManual": "portalApi/saveUserAppsSortingManual",
+    "saveUserWidgetsSortManual": "portalApi/saveUserWidgetsSortManual",
+    "updateWidgetsSortPref": "portalApi/updateWidgetsSortPref",
+    "UpdateUserAppsSortManual": "portalApi/UpdateUserAppsSortManual",
+    "widgetCatalogSelection": "portalApi/widgetCatalogSelection",
+    "widgetCommon": "portalApi/microservices",
+    "appCatalogRoles": "portalApi/appCatalogRoles",
+    "saveUserAppRoles": "portalApi/saveUserAppRoles",
+    "userApplicationRoles": "portalApi/userApplicationRoles",
+    "microserviceProxy": "portalApi/microservice/proxy",
+    "getUserAppsWebAnalytics": "portalApi/getUserAppsWebAnalytics",
+    "getWebAnalyticsOfApp": "portalApi/getWebAnalyticsOfApp",
+    "basicAuthAccount": "portalApi/basicAuthAccount",
+    "addWebAnalyticsReport": "portalApi/addWebAnalyticsReport",
+    "getUserJourneyAnalyticsReport": "portalApi/getUserJourneyAnalyticsReport",
+    "deleteWebAnalyticsReport": "portalApi/deleteWebAnalyticsReport",
+    "getAllWebAnalytics": "portalApi/getAllWebAnalytics",
+    "modifyWebAnalyticsReport": "portalApi/modifyWebAnalyticsReport",
+    "appsFullList": "portalApi/appsFullList",
+    "ecompTitle": "portalApi/ecompTitle",
+    "getRecommendations": "portalApi/getRecommendations",
+    "centralizedApps": "portalApi/centralizedApps",
+    "getSchedulerId": "portalApi/post_create_new_vnf_change",
+    "getTimeslotsForScheduler": "portalApi/get_time_slots",
+    "postSubmitForApprovedTimeslots": "portalApi/submit_vnf_change_timeslots",
+    "getPolicy": "portalApi/get_policy",
+    "getSchedulerConstants": "portalApi/get_scheduler_constant",
+    "uploadRoleFunction": "portalApi/uploadRoleFunction/:appId",
+    "checkIfUserIsSuperAdmin": "portalApi/checkIfUserIsSuperAdmin",
+    "getCurrentLang": "auxapi/languageSetting/user/:loginId",
+    "getLanguages": "auxapi/language",
+    "updateLang": "auxapi/languageSetting/user/:loginId"
+},
+"cookieDomain": "att.com"
+};
diff --git a/portal-FE-os/src/environments/environment.ts b/portal-FE-os/src/environments/environment.ts
new file mode 100644 (file)
index 0000000..8d15706
--- /dev/null
@@ -0,0 +1,134 @@
+// This file can be replaced during build by using the `fileReplacements` array.
+// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.
+// The list of file replacements can be found in `angular.json`.
+
+export const environment = {
+  production: false,
+  "api": {
+    "singleAppInfo": "http://www.portal.onap.org:9080/portal-be-os/portalApi/singleAppInfo",
+    "singleAppInfoById": "http://www.portal.onap.org:9080/portal-be-os/portalApi/singleAppInfoById",
+    "syncRolesFromExternalAuthSystem": "http://www.portal.onap.org:9080/portal-be-os/portalApi/syncRoles",
+    "syncFunctionsFromExternalAuthSystem": "http://www.portal.onap.org:9080/portal-be-os/portalApi/syncFunctions",
+    "userApps": "http://www.portal.onap.org:9080/portal-be-os/portalApi/userApps",
+    "persUserApps": "http://www.portal.onap.org:9080/portal-be-os/portalApi/persUserApps",
+    "appCatalog": "http://www.portal.onap.org:9080/portal-be-os/portalApi/appCatalog",
+    "accountAdmins": "http://www.portal.onap.org:9080/portal-be-os/portalApi/accountAdmins",
+    "availableApps": "http://www.portal.onap.org:9080/portal-be-os/portalApi/availableApps",
+    "allAvailableApps": "http://www.portal.onap.org:9080/portal-be-os/portalApi/allAvailableApps",
+    "externalRequestAccessSystem": "http://www.portal.onap.org:9080/portal-be-os/portalApi/externalRequestAccessSystem",
+    "userProfile": "http://www.portal.onap.org:9080/portal-be-os/portalApi/userProfile",
+    "queryUsers": "http://www.portal.onap.org:9080/portal-be-os/portalApi/queryUsers",
+    "adminAppsRoles": "http://www.portal.onap.org:9080/portal-be-os/portalApi/adminAppsRoles",
+    "adminApps": "http://www.portal.onap.org:9080/portal-be-os/portalApi/adminApps",
+    "appsForSuperAdminAndAccountAdmin": "http://www.portal.onap.org:9080/portal-be-os/portalApi/appsForSuperAdminAndAccountAdmin",
+    "accountUsers": "http://www.portal.onap.org:9080/portal-be-os/portalApi/app/:appId/users",
+    "saveNewUser": "http://www.portal.onap.org:9080/portal-be-os/portalApi/saveNewUser",
+    "userAppRoles": "http://www.portal.onap.org:9080/portal-be-os/portalApi/userAppRoles",
+    "onboardingApps": "http://www.portal.onap.org:9080/portal-be-os/portalApi/onboardingApps",
+    "widgets": "http://www.portal.onap.org:9080/portal-be-os/portalApi/widgets",
+    "widgetsValidation": "http://www.portal.onap.org:9080/portal-be-os/portalApi/widgets/validation",
+    "functionalMenuForAuthUser": "http://www.portal.onap.org:9080/portal-be-os/portalApi/functionalMenuForAuthUser",
+    "functionalMenuForEditing": "http://www.portal.onap.org:9080/portal-be-os/portalApi/functionalMenuForEditing",
+    "functionalMenuForNotificationTree": "http://www.portal.onap.org:9080/portal-be-os/portalApi/functionalMenuForNotificationTree",
+    "functionalMenu": "http://www.portal.onap.org:9080/portal-be-os/portalApi/functionalMenu",
+    "functionalMenuItemDetails": "http://www.portal.onap.org:9080/portal-be-os/portalApi/functionalMenuItemDetails/:menuId",
+    "appRoles": "http://www.portal.onap.org:9080/portal-be-os/portalApi/appRoles/:appId",
+    "appThumbnail": "http://www.portal.onap.org:9080/portal-be-os/portalApi/appThumbnail/:appId",
+    "functionalMenuItem": "http://www.portal.onap.org:9080/portal-be-os/portalApi/functionalMenuItem",
+    "regenerateFunctionalMenuAncestors": "http://www.portal.onap.org:9080/portal-be-os/portalApi/regenerateFunctionalMenuAncestors",
+    "listOfApp": "http://www.portal.onap.org:9080/portal-be-os/portalApi/getAppList",
+    "setFavoriteItem": "http://www.portal.onap.org:9080/portal-be-os/portalApi/setFavoriteItem",
+    "getFavoriteItems": "http://www.portal.onap.org:9080/portal-be-os/portalApi/getFavoriteItems",
+    "removeFavoriteItem": "http://www.portal.onap.org:9080/portal-be-os/portalApi/removeFavoriteItem/:menuId",
+    "ping": "http://www.portal.onap.org:9080/portal-be-os/portalApi/ping",
+    "functionalMenuStaticInfo": "http://www.portal.onap.org:9080/portal-be-os/portalApi/functionalMenuStaticInfo",
+    "portalAdmins": "http://www.portal.onap.org:9080/portal-be-os/portalApi/portalAdmins",
+    "portalAdmin": "http://www.portal.onap.org:9080/portal-be-os/portalApi/portalAdmin",
+    "getManifest": "http://www.portal.onap.org:9080/portal-be-os/portalApi/manifest",
+    "getActiveUser": "http://www.portal.onap.org:9080/portal-be-os/portalApi/dashboard/activeUsers",
+    "getSearchAllByStringResults": "http://www.portal.onap.org:9080/portal-be-os/portalApi/dashboard/search",
+    "commonWidget": "http://www.portal.onap.org:9080/portal-be-os/portalApi/dashboard/widgetData",
+    "deleteCommonWidget": "http://www.portal.onap.org:9080/portal-be-os/portalApi/dashboard/deleteData",
+    "getContactUS": "http://www.portal.onap.org:9080/portal-be-os/portalApi/contactus/list",
+    "getAppsAndContacts": "http://www.portal.onap.org:9080/portal-be-os/portalApi/contactus/allapps",
+    "saveContactUS": "http://www.portal.onap.org:9080/portal-be-os/portalApi/contactus/save",
+    "deleteContactUS": "http://www.portal.onap.org:9080/portal-be-os/portalApi/contactus/delete",
+    "getContactUSPortalDetails": "http://www.portal.onap.org:9080/portal-be-os/portalApi/contactus/feedback",
+    "getAppCategoryFunctions": "http://www.portal.onap.org:9080/portal-be-os/portalApi/contactus/functions",
+    "onlineUserUpdateRate": "http://www.portal.onap.org:9080/portal-be-os/portalApi/dashboard/onlineUserUpdateRate",
+    "storeAuditLog": "http://www.portal.onap.org:9080/portal-be-os/portalApi/auditLog/store",
+    "leftmenuItems": "http://www.portal.onap.org:9080/portal-be-os/portalApi/leftmenuItems",
+    "getFunctionalMenuRole": "http://www.portal.onap.org:9080/portal-be-os/portalApi/getFunctionalMenuRole",
+    "getNotifications": "http://www.portal.onap.org:9080/portal-be-os/portalApi/getNotifications",
+    "getMessageRecipients": "http://www.portal.onap.org:9080/portal-be-os/portalApi/getMessageRecipients",
+    "getRecommendations": "http://www.portal.onap.org:9080/portal-be-os/portalApi/getRecommendations",
+    "getAdminNotifications": "http://www.portal.onap.org:9080/portal-be-os/portalApi/getAdminNotifications",
+    "getAllAppRoleIds": "http://www.portal.onap.org:9080/portal-be-os/portalApi/getNotificationAppRoles",
+    "getNotificationHistory": "http://www.portal.onap.org:9080/portal-be-os/portalApi/getNotificationHistory",
+    "notificationUpdateRate": "http://www.portal.onap.org:9080/portal-be-os/portalApi/notificationUpdateRate",
+    "notificationRead": "http://www.portal.onap.org:9080/portal-be-os/portalApi/notificationRead",
+    "saveNotification": "http://www.portal.onap.org:9080/portal-be-os/portalApi/saveNotification",
+    "getNotificationRoles": "http://www.portal.onap.org:9080/portal-be-os/portalApi/notificationRole",
+    "getRole": "http://www.portal.onap.org:9080/portal-be-os/portalApi/get_role",
+    "getRoles": "http://www.portal.onap.org:9080/portal-be-os/portalApi/get_roles/:appId",
+    "toggleRole": "http://www.portal.onap.org:9080/portal-be-os/portalApi/role_list/toggleRole",
+    "removeRole": "http://www.portal.onap.org:9080/portal-be-os/portalApi/role_list/removeRole",
+    "saveRole": "http://www.portal.onap.org:9080/portal-be-os/portalApi/role/saveRole/:appId",
+    "toggleRoleRoleFunction": "http://www.portal.onap.org:9080/portal-be-os/portalApi/role/removeRoleFunction.htm",
+    "addRoleRoleFunction": "http://www.portal.onap.org:9080/portal-be-os/portalApi/role/addRoleFunction.htm",
+    "toggleRoleChildRole": "http://www.portal.onap.org:9080/portal-be-os/portalApi/role/removeChildRole.htm",
+    "addRoleChildRole": "http://www.portal.onap.org:9080/portal-be-os/portalApi/role/addChildRole.htm",
+    "getRoleFunctions": "http://www.portal.onap.org:9080/portal-be-os/portalApi/get_role_functions/:appId",
+    "saveRoleFunction": "http://www.portal.onap.org:9080/portal-be-os/portalApi/role_function_list/saveRoleFunction/:appId",
+    "removeRoleFunction": "http://www.portal.onap.org:9080/portal-be-os/portalApi/role_function_list/removeRoleFunction/:appId",
+    "userAppsOrderBySortPref": "http://www.portal.onap.org:9080/portal-be-os/portalApi/userAppsOrderBySortPref",
+    "userAppsOrderByName": "http://www.portal.onap.org:9080/portal-be-os/portalApi/userAppsOrderByName",
+    "saveUserAppsSortingPreference": "http://www.portal.onap.org:9080/portal-be-os/portalApi/saveUserAppsSortingPreference",
+    "userAppsSortTypePreference": "http://www.portal.onap.org:9080/portal-be-os/portalApi/userAppsSortTypePreference",
+    "userAppsOrderByLastUsed": "http://www.portal.onap.org:9080/portal-be-os/portalApi/userAppsOrderByLastUsed",
+    "userAppsOrderByMostUsed": "http://www.portal.onap.org:9080/portal-be-os/portalApi/userAppsOrderByMostUsed",
+    "userAppsOrderByManual": "http://www.portal.onap.org:9080/portal-be-os/portalApi/userAppsOrderByManual",
+    "saveUserAppsSortingManual": "http://www.portal.onap.org:9080/portal-be-os/portalApi/saveUserAppsSortingManual",
+    "saveUserWidgetsSortManual": "http://www.portal.onap.org:9080/portal-be-os/portalApi/saveUserWidgetsSortManual",
+    "updateWidgetsSortPref": "http://www.portal.onap.org:9080/portal-be-os/portalApi/updateWidgetsSortPref",
+    "UpdateUserAppsSortManual": "http://www.portal.onap.org:9080/portal-be-os/portalApi/UpdateUserAppsSortManual",
+    "widgetCatalogSelection": "http://www.portal.onap.org:9080/portal-be-os/portalApi/widgetCatalogSelection",
+    "widgetCommon": "http://www.portal.onap.org:9080/portal-be-os/portalApi/microservices",
+    "appCatalogRoles": "http://www.portal.onap.org:9080/portal-be-os/portalApi/appCatalogRoles",
+    "saveUserAppRoles": "http://www.portal.onap.org:9080/portal-be-os/portalApi/saveUserAppRoles",
+    "userApplicationRoles": "http://www.portal.onap.org:9080/portal-be-os/portalApi/userApplicationRoles",
+    "microserviceProxy": "http://www.portal.onap.org:9080/portal-be-os/portalApi/microservice/proxy",
+    "getUserAppsWebAnalytics": "http://www.portal.onap.org:9080/portal-be-os/portalApi/getUserAppsWebAnalytics",
+    "getWebAnalyticsOfApp": "http://www.portal.onap.org:9080/portal-be-os/portalApi/getWebAnalyticsOfApp",
+    "basicAuthAccount": "http://www.portal.onap.org:9080/portal-be-os/portalApi/basicAuthAccount",
+    "addWebAnalyticsReport": "http://www.portal.onap.org:9080/portal-be-os/portalApi/addWebAnalyticsReport",
+    "getUserJourneyAnalyticsReport": "http://www.portal.onap.org:9080/portal-be-os/portalApi/getUserJourneyAnalyticsReport",
+    "deleteWebAnalyticsReport": "http://www.portal.onap.org:9080/portal-be-os/portalApi/deleteWebAnalyticsReport",
+    "getAllWebAnalytics": "http://www.portal.onap.org:9080/portal-be-os/portalApi/getAllWebAnalytics",
+    "modifyWebAnalyticsReport": "http://www.portal.onap.org:9080/portal-be-os/portalApi/modifyWebAnalyticsReport",
+    "appsFullList": "http://www.portal.onap.org:9080/portal-be-os/portalApi/appsFullList",
+    "ecompTitle": "http://www.portal.onap.org:9080/portal-be-os/portalApi/ecompTitle",
+    "centralizedApps": "http://www.portal.onap.org:9080/portal-be-os/portalApi/centralizedApps",
+    "getSchedulerId": "http://www.portal.onap.org:9080/portal-be-os/portalApi/post_create_new_vnf_change",
+    "getTimeslotsForScheduler": "http://www.portal.onap.org:9080/portal-be-os/portalApi/get_time_slots",
+    "postSubmitForApprovedTimeslots": "http://www.portal.onap.org:9080/portal-be-os/portalApi/submit_vnf_change_timeslots",
+    "getPolicy": "http://www.portal.onap.org:9080/portal-be-os/portalApi/get_policy",
+    "getSchedulerConstants": "http://www.portal.onap.org:9080/portal-be-os/portalApi/get_scheduler_constant",
+    "uploadRoleFunction": "http://www.portal.onap.org:9080/portal-be-os/portalApi/uploadRoleFunction/:appId",
+    "checkIfUserIsSuperAdmin": "http://www.portal.onap.org:9080/portal-be-os/portalApi/checkIfUserIsSuperAdmin",
+    "getCurrentLang": "http://www.portal.onap.org:9080/portal-be-os/auxapi/languageSetting/user/:loginId",
+    "getLanguages": "http://www.portal.onap.org:9080/portal-be-os/auxapi/language",
+    "updateLang": "http://www.portal.onap.org:9080/portal-be-os/auxapi/languageSetting/user/:loginId"
+
+  },
+  "cookieDomain": "att.com"
+};
+
+/*
+ * For easier debugging in development mode, you can import the following file
+ * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
+ *
+ * This import should be commented out in production mode because it will have a negative impact
+ * on performance if an error is thrown.
+ */
+// import 'zone.js/dist/zone-error';  // Included with Angular CLI.
diff --git a/portal-FE-os/src/favicon.ico b/portal-FE-os/src/favicon.ico
new file mode 100644 (file)
index 0000000..d2c5e0f
Binary files /dev/null and b/portal-FE-os/src/favicon.ico differ
diff --git a/portal-FE-os/src/index.html b/portal-FE-os/src/index.html
new file mode 100644 (file)
index 0000000..5c8085f
--- /dev/null
@@ -0,0 +1,89 @@
+<!--
+  ============LICENSE_START==========================================
+  ONAP Portal
+  ===================================================================
+  Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+  ===================================================================
+  Unless otherwise specified, all software contained herein is licensed
+  under the Apache License, Version 2.0 (the "License");
+  you may not use this software except in compliance with the License.
+  You may obtain a copy of the License at
+              http://www.apache.org/licenses/LICENSE-2.0
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  Unless otherwise specified, all documentation contained herein is licensed
+  under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+  you may not use this documentation except in compliance with the License.
+  You may obtain a copy of the License at
+              https://creativecommons.org/licenses/by/4.0/
+  Unless required by applicable law or agreed to in writing, documentation
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT 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============================================
+  
+  -->
+<!doctype html>
+<html lang="en">
+<head>
+<script>
+        __Zone_enable_cross_context_check = true;
+        function nthIndex(str, pat, n) {
+          var L = str.length, i = -1;
+          while (n-- && i++ < L) {
+            i = str.indexOf(pat, i);
+            if (i < 0) break;
+          }
+          return i;
+        }
+        function addBaseHref(base) {
+          //document.write("<base href='" + base + "' />");
+          baseNode=document.createElement('base');
+          baseNode.href=base;
+
+          //document.getElementsByTagName('head')[0].appendChild(baseNode);
+          var head = document.getElementsByTagName('head')[0];
+          head.insertBefore(baseNode,head.childNodes[0] || null);
+          window.base = base;
+        }
+        if (window.location.href.includes('webtest.csp.att.com') || window.location.href.includes('www.e-access.att.com') || window.location.href.includes('ecomp.e-access.att.com')) {
+          //change to webjuction context
+          var base = window.location.pathname.substring(0, nthIndex(window.location.pathname, "/", 3) + 1);
+          //document.write("<base href='/ecompportal/ecompportal/' />");
+          addBaseHref(base);
+
+        } else {
+          //not webjunction
+          var base = window.location.pathname.substring(0, nthIndex(window.location.pathname,"/", 1) + 1);
+          //document.write("<base href='/ecompportal/' />");
+          addBaseHref(base);
+
+        }
+      </script>
+  <meta charset="utf-8">
+  <title>ONAP Portal</title>
+  <base href="/">
+
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <link rel="icon" type="image/x-icon" href="favicon.ico">
+  <link rel="stylesheet" href="styles.19ce2a92d11ceb6c5db4.css">
+</head>
+<body>
+  <app-root>Loading...</app-root>
+  <script>
+      __Zone_enable_cross_context_check = true;
+      </script>
+</body>
+</html>
diff --git a/portal-FE-os/src/karma.conf.js b/portal-FE-os/src/karma.conf.js
new file mode 100644 (file)
index 0000000..b6e0042
--- /dev/null
@@ -0,0 +1,31 @@
+// Karma configuration file, see link for more information
+// https://karma-runner.github.io/1.0/config/configuration-file.html
+
+module.exports = function (config) {
+  config.set({
+    basePath: '',
+    frameworks: ['jasmine', '@angular-devkit/build-angular'],
+    plugins: [
+      require('karma-jasmine'),
+      require('karma-chrome-launcher'),
+      require('karma-jasmine-html-reporter'),
+      require('karma-coverage-istanbul-reporter'),
+      require('@angular-devkit/build-angular/plugins/karma')
+    ],
+    client: {
+      clearContext: false // leave Jasmine Spec Runner output visible in browser
+    },
+    coverageIstanbulReporter: {
+      dir: require('path').join(__dirname, '../coverage'),
+      reports: ['html', 'lcovonly'],
+      fixWebpackSourcePaths: true
+    },
+    reporters: ['progress', 'kjhtml'],
+    port: 9876,
+    colors: true,
+    logLevel: config.LOG_INFO,
+    autoWatch: true,
+    browsers: ['Chrome'],
+    singleRun: false
+  });
+};
\ No newline at end of file
diff --git a/portal-FE-os/src/main.ts b/portal-FE-os/src/main.ts
new file mode 100644 (file)
index 0000000..c7b673c
--- /dev/null
@@ -0,0 +1,12 @@
+import { enableProdMode } from '@angular/core';
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+
+import { AppModule } from './app/app.module';
+import { environment } from './environments/environment';
+
+if (environment.production) {
+  enableProdMode();
+}
+
+platformBrowserDynamic().bootstrapModule(AppModule)
+  .catch(err => console.error(err));
diff --git a/portal-FE-os/src/polyfills.ts b/portal-FE-os/src/polyfills.ts
new file mode 100644 (file)
index 0000000..91286f4
--- /dev/null
@@ -0,0 +1,80 @@
+/**
+ * This file includes polyfills needed by Angular and is loaded before the app.
+ * You can add your own extra polyfills to this file.
+ *
+ * This file is divided into 2 sections:
+ *   1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
+ *   2. Application imports. Files imported after ZoneJS that should be loaded before your main
+ *      file.
+ *
+ * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
+ * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
+ * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
+ *
+ * Learn more in https://angular.io/guide/browser-support
+ */
+
+/***************************************************************************************************
+ * BROWSER POLYFILLS
+ */
+
+/** IE9, IE10 and IE11 requires all of the following polyfills. **/
+import 'core-js/es6/symbol';
+import 'core-js/es6/object';
+import 'core-js/es6/function';
+import 'core-js/es6/parse-int';
+import 'core-js/es6/parse-float';
+import 'core-js/es6/number';
+import 'core-js/es6/math';
+import 'core-js/es6/string';
+import 'core-js/es6/date';
+import 'core-js/es6/array';
+import 'core-js/es6/regexp';
+import 'core-js/es6/map';
+import 'core-js/es6/weak-map';
+import 'core-js/es6/set';
+
+/**
+ * If the application will be indexed by Google Search, the following is required.
+ * Googlebot uses a renderer based on Chrome 41.
+ * https://developers.google.com/search/docs/guides/rendering
+ **/
+// import 'core-js/es6/array';
+
+/** IE10 and IE11 requires the following for NgClass support on SVG elements */
+import 'classlist.js';  // Run `npm install --save classlist.js`.
+
+/** IE10 and IE11 requires the following for the Reflect API. */
+import 'core-js/es6/reflect';
+
+/**
+ * Web Animations `@angular/platform-browser/animations`
+ * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
+ * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
+ **/
+ import 'web-animations-js';  // Run `npm install --save web-animations-js`.
+
+/**
+ * By default, zone.js will patch all possible macroTask and DomEvents
+ * user can disable parts of macroTask/DomEvents patch by setting following flags
+ */
+
+ (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
+ (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
+ (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
+
+ /*
+ * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
+ * with the following flag, it will bypass `zone.js` patch for IE/Edge
+ */
+(window as any).__Zone_enable_cross_context_check = true;
+
+/***************************************************************************************************
+ * Zone JS is required by default for Angular itself.
+ */
+import 'zone.js/dist/zone';  // Included with Angular CLI.
+
+
+/***************************************************************************************************
+ * APPLICATION IMPORTS
+ */
diff --git a/portal-FE-os/src/styles.scss b/portal-FE-os/src/styles.scss
new file mode 100644 (file)
index 0000000..b8769e1
--- /dev/null
@@ -0,0 +1,5 @@
+/* You can add global styles to this file, and also import other style files */
+
+.cdk-overlay-connected-position-bounding-box {
+    z-index: 99999 !important;
+  }
\ No newline at end of file
diff --git a/portal-FE-os/src/test.ts b/portal-FE-os/src/test.ts
new file mode 100644 (file)
index 0000000..1631789
--- /dev/null
@@ -0,0 +1,20 @@
+// This file is required by karma.conf.js and loads recursively all the .spec and framework files
+
+import 'zone.js/dist/zone-testing';
+import { getTestBed } from '@angular/core/testing';
+import {
+  BrowserDynamicTestingModule,
+  platformBrowserDynamicTesting
+} from '@angular/platform-browser-dynamic/testing';
+
+declare const require: any;
+
+// First, initialize the Angular testing environment.
+getTestBed().initTestEnvironment(
+  BrowserDynamicTestingModule,
+  platformBrowserDynamicTesting()
+);
+// Then we find all the tests.
+const context = require.context('./', true, /\.spec\.ts$/);
+// And load the modules.
+context.keys().map(context);
diff --git a/portal-FE-os/src/tsconfig.app.json b/portal-FE-os/src/tsconfig.app.json
new file mode 100644 (file)
index 0000000..190fd30
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "extends": "../tsconfig.json",
+  "compilerOptions": {
+    "outDir": "../out-tsc/app",
+    "types": []
+  },
+  "exclude": [
+    "test.ts",
+    "**/*.spec.ts"
+  ]
+}
diff --git a/portal-FE-os/src/tsconfig.spec.json b/portal-FE-os/src/tsconfig.spec.json
new file mode 100644 (file)
index 0000000..de77336
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  "extends": "../tsconfig.json",
+  "compilerOptions": {
+    "outDir": "../out-tsc/spec",
+    "types": [
+      "jasmine",
+      "node"
+    ]
+  },
+  "files": [
+    "test.ts",
+    "polyfills.ts"
+  ],
+  "include": [
+    "**/*.spec.ts",
+    "**/*.d.ts"
+  ]
+}
diff --git a/portal-FE-os/src/tslint.json b/portal-FE-os/src/tslint.json
new file mode 100644 (file)
index 0000000..52e2c1a
--- /dev/null
@@ -0,0 +1,17 @@
+{
+    "extends": "../tslint.json",
+    "rules": {
+        "directive-selector": [
+            true,
+            "attribute",
+            "app",
+            "camelCase"
+        ],
+        "component-selector": [
+            true,
+            "element",
+            "app",
+            "kebab-case"
+        ]
+    }
+}
diff --git a/portal-FE-os/tsconfig.json b/portal-FE-os/tsconfig.json
new file mode 100644 (file)
index 0000000..eb05bdc
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "compileOnSave": false,
+  "compilerOptions": {
+    "baseUrl": "./",
+    "outDir": "./dist/out-tsc",
+    "sourceMap": true,
+    "declaration": false,
+    "module": "esnext",
+    "moduleResolution": "node",
+    "emitDecoratorMetadata": true,
+    "experimentalDecorators": true,
+    "target": "es5",
+    "typeRoots": [
+      "node_modules/@types"
+    ],
+    "lib": [
+      "es2018",
+      "dom"
+    ]
+  }
+}
diff --git a/portal-FE-os/tslint.json b/portal-FE-os/tslint.json
new file mode 100644 (file)
index 0000000..6ddb6b2
--- /dev/null
@@ -0,0 +1,131 @@
+{
+  "rulesDirectory": [
+    "node_modules/codelyzer"
+  ],
+  "rules": {
+    "arrow-return-shorthand": true,
+    "callable-types": true,
+    "class-name": true,
+    "comment-format": [
+      true,
+      "check-space"
+    ],
+    "curly": true,
+    "deprecation": {
+      "severity": "warn"
+    },
+    "eofline": true,
+    "forin": true,
+    "import-blacklist": [
+      true,
+      "rxjs/Rx"
+    ],
+    "import-spacing": true,
+    "indent": [
+      true,
+      "spaces"
+    ],
+    "interface-over-type-literal": true,
+    "label-position": true,
+    "max-line-length": [
+      true,
+      140
+    ],
+    "member-access": false,
+    "member-ordering": [
+      true,
+      {
+        "order": [
+          "static-field",
+          "instance-field",
+          "static-method",
+          "instance-method"
+        ]
+      }
+    ],
+    "no-arg": true,
+    "no-bitwise": true,
+    "no-console": [
+      true,
+      "debug",
+      "info",
+      "time",
+      "timeEnd",
+      "trace"
+    ],
+    "no-construct": true,
+    "no-debugger": true,
+    "no-duplicate-super": true,
+    "no-empty": false,
+    "no-empty-interface": true,
+    "no-eval": true,
+    "no-inferrable-types": [
+      true,
+      "ignore-params"
+    ],
+    "no-misused-new": true,
+    "no-non-null-assertion": true,
+    "no-redundant-jsdoc": true,
+    "no-shadowed-variable": true,
+    "no-string-literal": false,
+    "no-string-throw": true,
+    "no-switch-case-fall-through": true,
+    "no-trailing-whitespace": true,
+    "no-unnecessary-initializer": true,
+    "no-unused-expression": true,
+    "no-use-before-declare": true,
+    "no-var-keyword": true,
+    "object-literal-sort-keys": false,
+    "one-line": [
+      true,
+      "check-open-brace",
+      "check-catch",
+      "check-else",
+      "check-whitespace"
+    ],
+    "prefer-const": true,
+    "quotemark": [
+      true,
+      "single"
+    ],
+    "radix": true,
+    "semicolon": [
+      true,
+      "always"
+    ],
+    "triple-equals": [
+      true,
+      "allow-null-check"
+    ],
+    "typedef-whitespace": [
+      true,
+      {
+        "call-signature": "nospace",
+        "index-signature": "nospace",
+        "parameter": "nospace",
+        "property-declaration": "nospace",
+        "variable-declaration": "nospace"
+      }
+    ],
+    "unified-signatures": true,
+    "variable-name": false,
+    "whitespace": [
+      true,
+      "check-branch",
+      "check-decl",
+      "check-operator",
+      "check-separator",
+      "check-type"
+    ],
+    "no-output-on-prefix": true,
+    "use-input-property-decorator": true,
+    "use-output-property-decorator": true,
+    "use-host-property-decorator": true,
+    "no-input-rename": true,
+    "no-output-rename": true,
+    "use-life-cycle-interface": true,
+    "use-pipe-transform-interface": true,
+    "component-class-suffix": true,
+    "directive-class-suffix": true
+  }
+}